blob: f493ecb3fe9ae1e2a3dc59363daf9f91bd7c99ca [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
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB 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
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
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 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
Gregory P. Smitha703a212003-11-03 01:04:41 +000087#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000088#include <Python.h>
89#include <db.h>
90
91/* --------------------------------------------------------------------- */
92/* Various macro definitions */
93
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000094/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
95#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000096#if DB_VERSION_MINOR > 9
97#error "eek! DBVER can't handle minor versions > 9"
98#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
Gregory P. Smithac741c52005-06-06 17:31:32 +0000100#define PY_BSDDB_VERSION "4.3.3"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000101static char *rcs_id = "$Id$";
102
103
104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Gregory P. Smitha703a212003-11-03 01:04:41 +0000194#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
195#define HAVE_WEAKREF
196#else
197#undef HAVE_WEAKREF
198#endif
199
Gregory P. Smith31c50652004-06-28 01:20:40 +0000200/* if Python >= 2.1 better support warnings */
201#if PYTHON_API_VERSION >= 1010
202#define HAVE_WARNINGS
203#else
204#undef HAVE_WARNINGS
205#endif
206
Neal Norwitzb4a55812004-07-09 23:30:57 +0000207#if PYTHON_API_VERSION <= 1007
208 /* 1.5 compatibility */
209#define PyObject_New PyObject_NEW
210#define PyObject_Del PyMem_DEL
211#endif
212
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000213struct behaviourFlags {
214 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000215 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000216 unsigned int getReturnsNone : 1;
217 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000218 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000219 unsigned int cursorSetReturnsNone : 1;
220};
221
222#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000223#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000225typedef struct {
226 PyObject_HEAD
227 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000228 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000231#ifdef HAVE_WEAKREF
232 PyObject *in_weakreflist; /* List of weak references */
233#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234} DBEnvObject;
235
236
237typedef struct {
238 PyObject_HEAD
239 DB* db;
240 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000241 u_int32_t flags; /* saved flags from open() */
242 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000244 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245#if (DBVER >= 33)
246 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000247 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int primaryDBType;
249#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000250#ifdef HAVE_WEAKREF
251 PyObject *in_weakreflist; /* List of weak references */
252#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253} DBObject;
254
255
256typedef struct {
257 PyObject_HEAD
258 DBC* dbc;
259 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000260#ifdef HAVE_WEAKREF
261 PyObject *in_weakreflist; /* List of weak references */
262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000263} DBCursorObject;
264
265
266typedef struct {
267 PyObject_HEAD
268 DB_TXN* txn;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000269#ifdef HAVE_WEAKREF
270 PyObject *in_weakreflist; /* List of weak references */
271#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000272} DBTxnObject;
273
274
275typedef struct {
276 PyObject_HEAD
277 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000278#ifdef HAVE_WEAKREF
279 PyObject *in_weakreflist; /* List of weak references */
280#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000281} DBLockObject;
282
283
284
285staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
286
287#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
288#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
289#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
290#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
291#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
292
293
294/* --------------------------------------------------------------------- */
295/* Utility macros and functions */
296
297#define RETURN_IF_ERR() \
298 if (makeDBError(err)) { \
299 return NULL; \
300 }
301
302#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
303
Gregory P. Smithe2767172003-11-02 08:06:29 +0000304#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
305 if ((nonNull) == NULL) { \
306 PyObject *errTuple = NULL; \
307 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
308 PyErr_SetObject((pyErrObj), errTuple); \
309 Py_DECREF(errTuple); \
310 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311 }
312
Gregory P. Smithe2767172003-11-02 08:06:29 +0000313#define CHECK_DB_NOT_CLOSED(dbobj) \
314 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
315
316#define CHECK_ENV_NOT_CLOSED(env) \
317 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000318
319#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000320 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000321
322
323#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
324 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
325
326#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
327
328#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000329 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330
331
332static int makeDBError(int err);
333
334
335/* Return the access method type of the DBObject */
336static int _DB_get_type(DBObject* self)
337{
338#if (DBVER >= 33)
339 DBTYPE type;
340 int err;
341 err = self->db->get_type(self->db, &type);
342 if (makeDBError(err)) {
343 return -1;
344 }
345 return type;
346#else
347 return self->db->get_type(self->db);
348#endif
349}
350
351
352/* Create a DBT structure (containing key and data values) from Python
353 strings. Returns 1 on success, 0 on an error. */
354static int make_dbt(PyObject* obj, DBT* dbt)
355{
356 CLEAR_DBT(*dbt);
357 if (obj == Py_None) {
358 /* no need to do anything, the structure has already been zeroed */
359 }
360 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
361 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000362 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000363 return 0;
364 }
365 return 1;
366}
367
368
369/* Recno and Queue DBs can have integer keys. This function figures out
370 what's been given, verifies that it's allowed, and then makes the DBT.
371
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000372 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000373static int
374make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000375{
376 db_recno_t recno;
377 int type;
378
379 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000380 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000381 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000382 if (type == -1)
383 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000384 if (type == DB_RECNO || type == DB_QUEUE) {
385 PyErr_SetString(
386 PyExc_TypeError,
387 "None keys not allowed for Recno and Queue DB's");
388 return 0;
389 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000390 /* no need to do anything, the structure has already been zeroed */
391 }
392
393 else if (PyString_Check(keyobj)) {
394 /* verify access method type */
395 type = _DB_get_type(self);
396 if (type == -1)
397 return 0;
398 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000399 PyErr_SetString(
400 PyExc_TypeError,
401 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000402 return 0;
403 }
404
405 key->data = PyString_AS_STRING(keyobj);
406 key->size = PyString_GET_SIZE(keyobj);
407 }
408
409 else if (PyInt_Check(keyobj)) {
410 /* verify access method type */
411 type = _DB_get_type(self);
412 if (type == -1)
413 return 0;
414 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000415 /* if BTREE then an Integer key is allowed with the
416 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000417 *pflags |= DB_SET_RECNO;
418 }
419 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000420 PyErr_SetString(
421 PyExc_TypeError,
422 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000423 return 0;
424 }
425
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000426 /* Make a key out of the requested recno, use allocated space so DB
427 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 recno = PyInt_AS_LONG(keyobj);
429 key->data = malloc(sizeof(db_recno_t));
430 if (key->data == NULL) {
431 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
432 return 0;
433 }
434 key->ulen = key->size = sizeof(db_recno_t);
435 memcpy(key->data, &recno, sizeof(db_recno_t));
436 key->flags = DB_DBT_REALLOC;
437 }
438 else {
439 PyErr_Format(PyExc_TypeError,
440 "String or Integer object expected for key, %s found",
441 keyobj->ob_type->tp_name);
442 return 0;
443 }
444
445 return 1;
446}
447
448
449/* Add partial record access to an existing DBT data struct.
450 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
451 and the data storage/retrieval will be done using dlen and doff. */
452static int add_partial_dbt(DBT* d, int dlen, int doff) {
453 /* if neither were set we do nothing (-1 is the default value) */
454 if ((dlen == -1) && (doff == -1)) {
455 return 1;
456 }
457
458 if ((dlen < 0) || (doff < 0)) {
459 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
460 return 0;
461 }
462
463 d->flags = d->flags | DB_DBT_PARTIAL;
464 d->dlen = (unsigned int) dlen;
465 d->doff = (unsigned int) doff;
466 return 1;
467}
468
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000469/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
470/* TODO: make this use the native libc strlcpy() when available (BSD) */
471unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
472{
473 unsigned int srclen, copylen;
474
475 srclen = strlen(src);
476 if (n <= 0)
477 return srclen;
478 copylen = (srclen > n-1) ? n-1 : srclen;
479 /* populate dest[0] thru dest[copylen-1] */
480 memcpy(dest, src, copylen);
481 /* guarantee null termination */
482 dest[copylen] = 0;
483
484 return srclen;
485}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000486
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000487/* Callback used to save away more information about errors from the DB
488 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000489static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000490#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000491static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492#else
493static void _db_errorCallback(const DB_ENV *db_env,
494 const char* prefix, const char* msg)
495#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000496{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000497 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000498}
499
500
501/* make a nice exception object to raise for errors. */
502static int makeDBError(int err)
503{
504 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000505 PyObject *errObj = NULL;
506 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000507 int exceptionRaised = 0;
508
509 switch (err) {
510 case 0: /* successful, no error */ break;
511
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000512#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513 case DB_INCOMPLETE:
514#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000516 if (_db_errmsg[0]) {
517 strcat(errTxt, " -- ");
518 strcat(errTxt, _db_errmsg);
519 _db_errmsg[0] = 0;
520 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000521#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000522 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
523#else
524 fprintf(stderr, errTxt);
525 fprintf(stderr, "\n");
526#endif
527
528#else /* do an exception instead */
529 errObj = DBIncompleteError;
530#endif
531 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000532#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533
534 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
535 case DB_KEYEXIST: errObj = DBKeyExistError; break;
536 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
537 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
538 case DB_NOTFOUND: errObj = DBNotFoundError; break;
539 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
540 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
541 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
542 case DB_NOSERVER: errObj = DBNoServerError; break;
543 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
544 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
545#if (DBVER >= 33)
546 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
547 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
548#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000549 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000550
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000551#if (DBVER >= 43)
552 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
553 case ENOMEM: errObj = PyExc_MemoryError; break;
554#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000555 case EINVAL: errObj = DBInvalidArgError; break;
556 case EACCES: errObj = DBAccessError; break;
557 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558 case EAGAIN: errObj = DBAgainError; break;
559 case EBUSY : errObj = DBBusyError; break;
560 case EEXIST: errObj = DBFileExistsError; break;
561 case ENOENT: errObj = DBNoSuchFileError; break;
562 case EPERM : errObj = DBPermissionsError; break;
563
564 default: errObj = DBError; break;
565 }
566
567 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000568 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000569 if (_db_errmsg[0]) {
570 strcat(errTxt, " -- ");
571 strcat(errTxt, _db_errmsg);
572 _db_errmsg[0] = 0;
573 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000574
575 errTuple = Py_BuildValue("(is)", err, errTxt);
576 PyErr_SetObject(errObj, errTuple);
577 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000578 }
579
580 return ((errObj != NULL) || exceptionRaised);
581}
582
583
584
585/* set a type exception */
586static void makeTypeError(char* expected, PyObject* found)
587{
588 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
589 expected, found->ob_type->tp_name);
590}
591
592
593/* verify that an obj is either None or a DBTxn, and set the txn pointer */
594static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
595{
596 if (txnobj == Py_None || txnobj == NULL) {
597 *txn = NULL;
598 return 1;
599 }
600 if (DBTxnObject_Check(txnobj)) {
601 *txn = ((DBTxnObject*)txnobj)->txn;
602 return 1;
603 }
604 else
605 makeTypeError("DBTxn", txnobj);
606 return 0;
607}
608
609
610/* Delete a key from a database
611 Returns 0 on success, -1 on an error. */
612static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
613{
614 int err;
615
616 MYDB_BEGIN_ALLOW_THREADS;
617 err = self->db->del(self->db, txn, key, 0);
618 MYDB_END_ALLOW_THREADS;
619 if (makeDBError(err)) {
620 return -1;
621 }
622 self->haveStat = 0;
623 return 0;
624}
625
626
627/* Store a key into a database
628 Returns 0 on success, -1 on an error. */
629static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
630{
631 int err;
632
633 MYDB_BEGIN_ALLOW_THREADS;
634 err = self->db->put(self->db, txn, key, data, flags);
635 MYDB_END_ALLOW_THREADS;
636 if (makeDBError(err)) {
637 return -1;
638 }
639 self->haveStat = 0;
640 return 0;
641}
642
643/* Get a key/data pair from a cursor */
644static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
645 PyObject *args, PyObject *kwargs, char *format)
646{
647 int err;
648 PyObject* retval = NULL;
649 DBT key, data;
650 int dlen = -1;
651 int doff = -1;
652 int flags = 0;
653 char* kwnames[] = { "flags", "dlen", "doff", NULL };
654
655 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
656 &flags, &dlen, &doff))
657 return NULL;
658
659 CHECK_CURSOR_NOT_CLOSED(self);
660
661 flags |= extra_flags;
662 CLEAR_DBT(key);
663 CLEAR_DBT(data);
664 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
665 /* Tell BerkeleyDB to malloc the return value (thread safe) */
666 data.flags = DB_DBT_MALLOC;
667 key.flags = DB_DBT_MALLOC;
668 }
669 if (!add_partial_dbt(&data, dlen, doff))
670 return NULL;
671
672 MYDB_BEGIN_ALLOW_THREADS;
673 err = self->dbc->c_get(self->dbc, &key, &data, flags);
674 MYDB_END_ALLOW_THREADS;
675
Gregory P. Smithe9477062005-06-04 06:46:59 +0000676 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
677 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678 Py_INCREF(Py_None);
679 retval = Py_None;
680 }
681 else if (makeDBError(err)) {
682 retval = NULL;
683 }
684 else { /* otherwise, success! */
685
686 /* if Recno or Queue, return the key as an Int */
687 switch (_DB_get_type(self->mydb)) {
688 case -1:
689 retval = NULL;
690 break;
691
692 case DB_RECNO:
693 case DB_QUEUE:
694 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
695 data.data, data.size);
696 break;
697 case DB_HASH:
698 case DB_BTREE:
699 default:
700 retval = Py_BuildValue("s#s#", key.data, key.size,
701 data.data, data.size);
702 break;
703 }
704 }
705 if (!err) {
706 FREE_DBT(key);
707 FREE_DBT(data);
708 }
709 return retval;
710}
711
712
713/* add an integer to a dictionary using the given name as a key */
714static void _addIntToDict(PyObject* dict, char *name, int value)
715{
716 PyObject* v = PyInt_FromLong((long) value);
717 if (!v || PyDict_SetItemString(dict, name, v))
718 PyErr_Clear();
719
720 Py_XDECREF(v);
721}
722
723
724
725
726/* --------------------------------------------------------------------- */
727/* Allocators and deallocators */
728
729static DBObject*
730newDBObject(DBEnvObject* arg, int flags)
731{
732 DBObject* self;
733 DB_ENV* db_env = NULL;
734 int err;
735
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000736 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 if (self == NULL)
738 return NULL;
739
740 self->haveStat = 0;
741 self->flags = 0;
742 self->setflags = 0;
743 self->myenvobj = NULL;
744#if (DBVER >= 33)
745 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000746 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000747 self->primaryDBType = 0;
748#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000749#ifdef HAVE_WEAKREF
750 self->in_weakreflist = NULL;
751#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752
753 /* keep a reference to our python DBEnv object */
754 if (arg) {
755 Py_INCREF(arg);
756 self->myenvobj = arg;
757 db_env = arg->db_env;
758 }
759
760 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000761 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000763 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
764 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765
766 MYDB_BEGIN_ALLOW_THREADS;
767 err = db_create(&self->db, db_env, flags);
768 self->db->set_errcall(self->db, _db_errorCallback);
769#if (DBVER >= 33)
770 self->db->app_private = (void*)self;
771#endif
772 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000773 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
774 * list so that a DBEnv can refuse to close without aborting any open
775 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776 if (makeDBError(err)) {
777 if (self->myenvobj) {
778 Py_DECREF(self->myenvobj);
779 self->myenvobj = NULL;
780 }
781 self = NULL;
782 }
783 return self;
784}
785
786
787static void
788DB_dealloc(DBObject* self)
789{
790 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000791 /* avoid closing a DB when its DBEnv has been closed out from under
792 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000794 (self->myenvobj && self->myenvobj->db_env))
795 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000796 MYDB_BEGIN_ALLOW_THREADS;
797 self->db->close(self->db, 0);
798 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000799#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000800 } else {
801 PyErr_Warn(PyExc_RuntimeWarning,
802 "DB could not be closed in destructor: DBEnv already closed");
803#endif
804 }
805 self->db = NULL;
806 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000807#ifdef HAVE_WEAKREF
808 if (self->in_weakreflist != NULL) {
809 PyObject_ClearWeakRefs((PyObject *) self);
810 }
811#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812 if (self->myenvobj) {
813 Py_DECREF(self->myenvobj);
814 self->myenvobj = NULL;
815 }
816#if (DBVER >= 33)
817 if (self->associateCallback != NULL) {
818 Py_DECREF(self->associateCallback);
819 self->associateCallback = NULL;
820 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000821 if (self->btCompareCallback != NULL) {
822 Py_DECREF(self->btCompareCallback);
823 self->btCompareCallback = NULL;
824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000825#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827}
828
829
830static DBCursorObject*
831newDBCursorObject(DBC* dbc, DBObject* db)
832{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000833 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 if (self == NULL)
835 return NULL;
836
837 self->dbc = dbc;
838 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000839#ifdef HAVE_WEAKREF
840 self->in_weakreflist = NULL;
841#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 Py_INCREF(self->mydb);
843 return self;
844}
845
846
847static void
848DBCursor_dealloc(DBCursorObject* self)
849{
850 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000851
852#ifdef HAVE_WEAKREF
853 if (self->in_weakreflist != NULL) {
854 PyObject_ClearWeakRefs((PyObject *) self);
855 }
856#endif
857
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000858 if (self->dbc != NULL) {
859 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000860 /* If the underlying database has been closed, we don't
861 need to do anything. If the environment has been closed
862 we need to leak, as BerkeleyDB will crash trying to access
863 the environment. There was an exception when the
864 user closed the environment even though there still was
865 a database open. */
866 if (self->mydb->db && self->mydb->myenvobj &&
867 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000868 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 self->dbc = NULL;
870 MYDB_END_ALLOW_THREADS;
871 }
872 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000873 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000874}
875
876
877static DBEnvObject*
878newDBEnvObject(int flags)
879{
880 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000881 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882 if (self == NULL)
883 return NULL;
884
885 self->closed = 1;
886 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000887 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
888 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000889#ifdef HAVE_WEAKREF
890 self->in_weakreflist = NULL;
891#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892
893 MYDB_BEGIN_ALLOW_THREADS;
894 err = db_env_create(&self->db_env, flags);
895 MYDB_END_ALLOW_THREADS;
896 if (makeDBError(err)) {
897 self = NULL;
898 }
899 else {
900 self->db_env->set_errcall(self->db_env, _db_errorCallback);
901 }
902 return self;
903}
904
905
906static void
907DBEnv_dealloc(DBEnvObject* self)
908{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000909#ifdef HAVE_WEAKREF
910 if (self->in_weakreflist != NULL) {
911 PyObject_ClearWeakRefs((PyObject *) self);
912 }
913#endif
914
Neal Norwitz37b0c1d2004-07-09 23:33:06 +0000915 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 MYDB_BEGIN_ALLOW_THREADS;
917 self->db_env->close(self->db_env, 0);
918 MYDB_END_ALLOW_THREADS;
919 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000920 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921}
922
923
924static DBTxnObject*
925newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
926{
927 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000928 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000929 if (self == NULL)
930 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000931#ifdef HAVE_WEAKREF
932 self->in_weakreflist = NULL;
933#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934
935 MYDB_BEGIN_ALLOW_THREADS;
936#if (DBVER >= 40)
937 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
938#else
939 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
940#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000941 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
942 * list so that a DBEnv can refuse to close without aborting any open
943 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 MYDB_END_ALLOW_THREADS;
945 if (makeDBError(err)) {
946 self = NULL;
947 }
948 return self;
949}
950
951
952static void
953DBTxn_dealloc(DBTxnObject* self)
954{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000955#ifdef HAVE_WEAKREF
956 if (self->in_weakreflist != NULL) {
957 PyObject_ClearWeakRefs((PyObject *) self);
958 }
959#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960
Gregory P. Smith31c50652004-06-28 01:20:40 +0000961#ifdef HAVE_WARNINGS
962 if (self->txn) {
963 /* it hasn't been finalized, abort it! */
964 MYDB_BEGIN_ALLOW_THREADS;
965#if (DBVER >= 40)
966 self->txn->abort(self->txn);
967#else
968 txn_abort(self->txn);
969#endif
970 MYDB_END_ALLOW_THREADS;
971 PyErr_Warn(PyExc_RuntimeWarning,
972 "DBTxn aborted in destructor. No prior commit() or abort().");
973 }
974#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000977}
978
979
980static DBLockObject*
981newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
982 db_lockmode_t lock_mode, int flags)
983{
984 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000985 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000986 if (self == NULL)
987 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000988#ifdef HAVE_WEAKREF
989 self->in_weakreflist = NULL;
990#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991
992 MYDB_BEGIN_ALLOW_THREADS;
993#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000994 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
995 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996#else
997 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
998#endif
999 MYDB_END_ALLOW_THREADS;
1000 if (makeDBError(err)) {
1001 self = NULL;
1002 }
1003
1004 return self;
1005}
1006
1007
1008static void
1009DBLock_dealloc(DBLockObject* self)
1010{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001011#ifdef HAVE_WEAKREF
1012 if (self->in_weakreflist != NULL) {
1013 PyObject_ClearWeakRefs((PyObject *) self);
1014 }
1015#endif
1016 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001018 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019}
1020
1021
1022/* --------------------------------------------------------------------- */
1023/* DB methods */
1024
1025static PyObject*
1026DB_append(DBObject* self, PyObject* args)
1027{
1028 PyObject* txnobj = NULL;
1029 PyObject* dataobj;
1030 db_recno_t recno;
1031 DBT key, data;
1032 DB_TXN *txn = NULL;
1033
1034 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1035 return NULL;
1036
1037 CHECK_DB_NOT_CLOSED(self);
1038
1039 /* make a dummy key out of a recno */
1040 recno = 0;
1041 CLEAR_DBT(key);
1042 key.data = &recno;
1043 key.size = sizeof(recno);
1044 key.ulen = key.size;
1045 key.flags = DB_DBT_USERMEM;
1046
1047 if (!make_dbt(dataobj, &data)) return NULL;
1048 if (!checkTxnObj(txnobj, &txn)) return NULL;
1049
1050 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1051 return NULL;
1052
1053 return PyInt_FromLong(recno);
1054}
1055
1056
1057#if (DBVER >= 33)
1058
1059static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001060_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1061 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062{
1063 int retval = DB_DONOTINDEX;
1064 DBObject* secondaryDB = (DBObject*)db->app_private;
1065 PyObject* callback = secondaryDB->associateCallback;
1066 int type = secondaryDB->primaryDBType;
1067 PyObject* key;
1068 PyObject* data;
1069 PyObject* args;
1070 PyObject* result;
1071
1072
1073 if (callback != NULL) {
1074 MYDB_BEGIN_BLOCK_THREADS;
1075
1076 if (type == DB_RECNO || type == DB_QUEUE) {
1077 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1078 }
1079 else {
1080 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1081 }
1082 data = PyString_FromStringAndSize(priData->data, priData->size);
1083 args = PyTuple_New(2);
1084 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1085 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1086
1087 result = PyEval_CallObject(callback, args);
1088
1089 if (result == NULL) {
1090 PyErr_Print();
1091 }
1092 else if (result == Py_None) {
1093 retval = DB_DONOTINDEX;
1094 }
1095 else if (PyInt_Check(result)) {
1096 retval = PyInt_AsLong(result);
1097 }
1098 else if (PyString_Check(result)) {
1099 char* data;
1100 int size;
1101
1102 CLEAR_DBT(*secKey);
1103#if PYTHON_API_VERSION <= 1007
1104 /* 1.5 compatibility */
1105 size = PyString_Size(result);
1106 data = PyString_AsString(result);
1107#else
1108 PyString_AsStringAndSize(result, &data, &size);
1109#endif
1110 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1111 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001112 if (secKey->data) {
1113 memcpy(secKey->data, data, size);
1114 secKey->size = size;
1115 retval = 0;
1116 }
1117 else {
1118 PyErr_SetString(PyExc_MemoryError,
1119 "malloc failed in _db_associateCallback");
1120 PyErr_Print();
1121 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001122 }
1123 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001124 PyErr_SetString(
1125 PyExc_TypeError,
1126 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 PyErr_Print();
1128 }
1129
1130 Py_DECREF(args);
1131 if (result) {
1132 Py_DECREF(result);
1133 }
1134
1135 MYDB_END_BLOCK_THREADS;
1136 }
1137 return retval;
1138}
1139
1140
1141static PyObject*
1142DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1143{
1144 int err, flags=0;
1145 DBObject* secondaryDB;
1146 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001147#if (DBVER >= 41)
1148 PyObject *txnobj = NULL;
1149 DB_TXN *txn = NULL;
1150 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1151#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001153#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001155#if (DBVER >= 41)
1156 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1157 &secondaryDB, &callback, &flags,
1158 &txnobj)) {
1159#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001161 &secondaryDB, &callback, &flags)) {
1162#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001164 }
1165
1166#if (DBVER >= 41)
1167 if (!checkTxnObj(txnobj, &txn)) return NULL;
1168#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169
1170 CHECK_DB_NOT_CLOSED(self);
1171 if (!DBObject_Check(secondaryDB)) {
1172 makeTypeError("DB", (PyObject*)secondaryDB);
1173 return NULL;
1174 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001175 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176 if (callback == Py_None) {
1177 callback = NULL;
1178 }
1179 else if (!PyCallable_Check(callback)) {
1180 makeTypeError("Callable", callback);
1181 return NULL;
1182 }
1183
1184 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001185 Py_XDECREF(secondaryDB->associateCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001186 Py_INCREF(callback);
1187 secondaryDB->associateCallback = callback;
1188 secondaryDB->primaryDBType = _DB_get_type(self);
1189
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001190 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1191 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1192 * The global interepreter lock is not initialized until the first
1193 * thread is created using thread.start_new_thread() or fork() is
1194 * called. that would cause the ALLOW_THREADS here to segfault due
1195 * to a null pointer reference if no threads or child processes
1196 * have been created. This works around that and is a no-op if
1197 * threads have already been initialized.
1198 * (see pybsddb-users mailing list post on 2002-08-07)
1199 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001200#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001201 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001202#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001204#if (DBVER >= 41)
1205 err = self->db->associate(self->db,
1206 txn,
1207 secondaryDB->db,
1208 _db_associateCallback,
1209 flags);
1210#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001211 err = self->db->associate(self->db,
1212 secondaryDB->db,
1213 _db_associateCallback,
1214 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001215#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001216 MYDB_END_ALLOW_THREADS;
1217
1218 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001219 Py_XDECREF(secondaryDB->associateCallback);
1220 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001221 secondaryDB->primaryDBType = 0;
1222 }
1223
1224 RETURN_IF_ERR();
1225 RETURN_NONE();
1226}
1227
1228
1229#endif
1230
1231
1232static PyObject*
1233DB_close(DBObject* self, PyObject* args)
1234{
1235 int err, flags=0;
1236 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1237 return NULL;
1238 if (self->db != NULL) {
1239 if (self->myenvobj)
1240 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 self->db = NULL;
1243 RETURN_IF_ERR();
1244 }
1245 RETURN_NONE();
1246}
1247
1248
1249#if (DBVER >= 32)
1250static PyObject*
1251_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1252{
1253 int err, flags=0, type;
1254 PyObject* txnobj = NULL;
1255 PyObject* retval = NULL;
1256 DBT key, data;
1257 DB_TXN *txn = NULL;
1258 char* kwnames[] = { "txn", "flags", NULL };
1259
1260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1261 &txnobj, &flags))
1262 return NULL;
1263
1264 CHECK_DB_NOT_CLOSED(self);
1265 type = _DB_get_type(self);
1266 if (type == -1)
1267 return NULL;
1268 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001269 PyErr_SetString(PyExc_TypeError,
1270 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271 return NULL;
1272 }
1273 if (!checkTxnObj(txnobj, &txn))
1274 return NULL;
1275
1276 CLEAR_DBT(key);
1277 CLEAR_DBT(data);
1278 if (CHECK_DBFLAG(self, DB_THREAD)) {
1279 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1280 data.flags = DB_DBT_MALLOC;
1281 key.flags = DB_DBT_MALLOC;
1282 }
1283
1284 MYDB_BEGIN_ALLOW_THREADS;
1285 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1286 MYDB_END_ALLOW_THREADS;
1287
Gregory P. Smithe9477062005-06-04 06:46:59 +00001288 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1289 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290 err = 0;
1291 Py_INCREF(Py_None);
1292 retval = Py_None;
1293 }
1294 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001295 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1296 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 FREE_DBT(key);
1298 FREE_DBT(data);
1299 }
1300
1301 RETURN_IF_ERR();
1302 return retval;
1303}
1304
1305static PyObject*
1306DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1307{
1308 return _DB_consume(self, args, kwargs, DB_CONSUME);
1309}
1310
1311static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001312DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1313 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314{
1315 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1316}
1317#endif
1318
1319
1320
1321static PyObject*
1322DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1323{
1324 int err, flags=0;
1325 DBC* dbc;
1326 PyObject* txnobj = NULL;
1327 DB_TXN *txn = NULL;
1328 char* kwnames[] = { "txn", "flags", NULL };
1329
1330 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1331 &txnobj, &flags))
1332 return NULL;
1333 CHECK_DB_NOT_CLOSED(self);
1334 if (!checkTxnObj(txnobj, &txn))
1335 return NULL;
1336
1337 MYDB_BEGIN_ALLOW_THREADS;
1338 err = self->db->cursor(self->db, txn, &dbc, flags);
1339 MYDB_END_ALLOW_THREADS;
1340 RETURN_IF_ERR();
1341 return (PyObject*) newDBCursorObject(dbc, self);
1342}
1343
1344
1345static PyObject*
1346DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1347{
1348 PyObject* txnobj = NULL;
1349 int flags = 0;
1350 PyObject* keyobj;
1351 DBT key;
1352 DB_TXN *txn = NULL;
1353 char* kwnames[] = { "key", "txn", "flags", NULL };
1354
1355 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1356 &keyobj, &txnobj, &flags))
1357 return NULL;
1358 CHECK_DB_NOT_CLOSED(self);
1359 if (!make_key_dbt(self, keyobj, &key, NULL))
1360 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001361 if (!checkTxnObj(txnobj, &txn)) {
1362 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001364 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001365
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001366 if (-1 == _DB_delete(self, txn, &key, 0)) {
1367 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001369 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001370
1371 FREE_DBT(key);
1372 RETURN_NONE();
1373}
1374
1375
1376static PyObject*
1377DB_fd(DBObject* self, PyObject* args)
1378{
1379 int err, the_fd;
1380
1381 if (!PyArg_ParseTuple(args,":fd"))
1382 return NULL;
1383 CHECK_DB_NOT_CLOSED(self);
1384
1385 MYDB_BEGIN_ALLOW_THREADS;
1386 err = self->db->fd(self->db, &the_fd);
1387 MYDB_END_ALLOW_THREADS;
1388 RETURN_IF_ERR();
1389 return PyInt_FromLong(the_fd);
1390}
1391
1392
1393static PyObject*
1394DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1395{
1396 int err, flags=0;
1397 PyObject* txnobj = NULL;
1398 PyObject* keyobj;
1399 PyObject* dfltobj = NULL;
1400 PyObject* retval = NULL;
1401 int dlen = -1;
1402 int doff = -1;
1403 DBT key, data;
1404 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001405 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001406
1407 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001408 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1409 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410 return NULL;
1411
1412 CHECK_DB_NOT_CLOSED(self);
1413 if (!make_key_dbt(self, keyobj, &key, &flags))
1414 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001415 if (!checkTxnObj(txnobj, &txn)) {
1416 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001417 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419
1420 CLEAR_DBT(data);
1421 if (CHECK_DBFLAG(self, DB_THREAD)) {
1422 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1423 data.flags = DB_DBT_MALLOC;
1424 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001425 if (!add_partial_dbt(&data, dlen, doff)) {
1426 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001428 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 MYDB_BEGIN_ALLOW_THREADS;
1431 err = self->db->get(self->db, txn, &key, &data, flags);
1432 MYDB_END_ALLOW_THREADS;
1433
Gregory P. Smithe9477062005-06-04 06:46:59 +00001434 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435 err = 0;
1436 Py_INCREF(dfltobj);
1437 retval = dfltobj;
1438 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001439 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1440 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441 err = 0;
1442 Py_INCREF(Py_None);
1443 retval = Py_None;
1444 }
1445 else if (!err) {
1446 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001447 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1448 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001449 else /* return just the data */
1450 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001451 FREE_DBT(data);
1452 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001453 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454
1455 RETURN_IF_ERR();
1456 return retval;
1457}
1458
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001459#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001460static PyObject*
1461DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1462{
1463 int err, flags=0;
1464 PyObject* txnobj = NULL;
1465 PyObject* keyobj;
1466 PyObject* dfltobj = NULL;
1467 PyObject* retval = NULL;
1468 int dlen = -1;
1469 int doff = -1;
1470 DBT key, pkey, data;
1471 DB_TXN *txn = NULL;
1472 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1473
1474 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1475 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1476 &doff))
1477 return NULL;
1478
1479 CHECK_DB_NOT_CLOSED(self);
1480 if (!make_key_dbt(self, keyobj, &key, &flags))
1481 return NULL;
1482 if (!checkTxnObj(txnobj, &txn)) {
1483 FREE_DBT(key);
1484 return NULL;
1485 }
1486
1487 CLEAR_DBT(data);
1488 if (CHECK_DBFLAG(self, DB_THREAD)) {
1489 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1490 data.flags = DB_DBT_MALLOC;
1491 }
1492 if (!add_partial_dbt(&data, dlen, doff)) {
1493 FREE_DBT(key);
1494 return NULL;
1495 }
1496
1497 CLEAR_DBT(pkey);
1498 pkey.flags = DB_DBT_MALLOC;
1499
1500 MYDB_BEGIN_ALLOW_THREADS;
1501 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1502 MYDB_END_ALLOW_THREADS;
1503
Gregory P. Smithe9477062005-06-04 06:46:59 +00001504 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001505 err = 0;
1506 Py_INCREF(dfltobj);
1507 retval = dfltobj;
1508 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001509 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1510 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001511 err = 0;
1512 Py_INCREF(Py_None);
1513 retval = Py_None;
1514 }
1515 else if (!err) {
1516 PyObject *pkeyObj;
1517 PyObject *dataObj;
1518 dataObj = PyString_FromStringAndSize(data.data, data.size);
1519
1520 if (self->primaryDBType == DB_RECNO ||
1521 self->primaryDBType == DB_QUEUE)
1522 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1523 else
1524 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1525
1526 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1527 {
1528 PyObject *keyObj;
1529 int type = _DB_get_type(self);
1530 if (type == DB_RECNO || type == DB_QUEUE)
1531 keyObj = PyInt_FromLong(*(long *)key.data);
1532 else
1533 keyObj = PyString_FromStringAndSize(key.data, key.size);
1534 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1535 }
1536 else /* return just the pkey and data */
1537 {
1538 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1539 }
1540 FREE_DBT(pkey);
1541 FREE_DBT(data);
1542 }
1543 FREE_DBT(key);
1544
1545 RETURN_IF_ERR();
1546 return retval;
1547}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001548#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001549
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550
1551/* Return size of entry */
1552static PyObject*
1553DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1554{
1555 int err, flags=0;
1556 PyObject* txnobj = NULL;
1557 PyObject* keyobj;
1558 PyObject* retval = NULL;
1559 DBT key, data;
1560 DB_TXN *txn = NULL;
1561 char* kwnames[] = { "key", "txn", NULL };
1562
1563 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1564 &keyobj, &txnobj))
1565 return NULL;
1566 CHECK_DB_NOT_CLOSED(self);
1567 if (!make_key_dbt(self, keyobj, &key, &flags))
1568 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001569 if (!checkTxnObj(txnobj, &txn)) {
1570 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001571 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001572 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001573 CLEAR_DBT(data);
1574
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001575 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1576 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001577 data.flags = DB_DBT_USERMEM;
1578 data.ulen = 0;
1579 MYDB_BEGIN_ALLOW_THREADS;
1580 err = self->db->get(self->db, txn, &key, &data, flags);
1581 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001582 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001583 retval = PyInt_FromLong((long)data.size);
1584 err = 0;
1585 }
1586
1587 FREE_DBT(key);
1588 FREE_DBT(data);
1589 RETURN_IF_ERR();
1590 return retval;
1591}
1592
1593
1594static PyObject*
1595DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1596{
1597 int err, flags=0;
1598 PyObject* txnobj = NULL;
1599 PyObject* keyobj;
1600 PyObject* dataobj;
1601 PyObject* retval = NULL;
1602 DBT key, data;
1603 DB_TXN *txn = NULL;
1604 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1605
1606
1607 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1608 &keyobj, &dataobj, &txnobj, &flags))
1609 return NULL;
1610
1611 CHECK_DB_NOT_CLOSED(self);
1612 if (!make_key_dbt(self, keyobj, &key, NULL))
1613 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001614 if ( !make_dbt(dataobj, &data) ||
1615 !checkTxnObj(txnobj, &txn) )
1616 {
1617 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001618 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001619 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001620
1621 flags |= DB_GET_BOTH;
1622
1623 if (CHECK_DBFLAG(self, DB_THREAD)) {
1624 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1625 data.flags = DB_DBT_MALLOC;
1626 /* TODO: Is this flag needed? We're passing a data object that should
1627 match what's in the DB, so there should be no need to malloc.
1628 We run the risk of freeing something twice! Check this. */
1629 }
1630
1631 MYDB_BEGIN_ALLOW_THREADS;
1632 err = self->db->get(self->db, txn, &key, &data, flags);
1633 MYDB_END_ALLOW_THREADS;
1634
Gregory P. Smithe9477062005-06-04 06:46:59 +00001635 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1636 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637 err = 0;
1638 Py_INCREF(Py_None);
1639 retval = Py_None;
1640 }
1641 else if (!err) {
1642 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1643 FREE_DBT(data); /* Only if retrieval was successful */
1644 }
1645
1646 FREE_DBT(key);
1647 RETURN_IF_ERR();
1648 return retval;
1649}
1650
1651
1652static PyObject*
1653DB_get_byteswapped(DBObject* self, PyObject* args)
1654{
1655#if (DBVER >= 33)
1656 int err = 0;
1657#endif
1658 int retval = -1;
1659
1660 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1661 return NULL;
1662 CHECK_DB_NOT_CLOSED(self);
1663
1664#if (DBVER >= 33)
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->get_byteswapped(self->db, &retval);
1667 MYDB_END_ALLOW_THREADS;
1668 RETURN_IF_ERR();
1669#else
1670 MYDB_BEGIN_ALLOW_THREADS;
1671 retval = self->db->get_byteswapped(self->db);
1672 MYDB_END_ALLOW_THREADS;
1673#endif
1674 return PyInt_FromLong(retval);
1675}
1676
1677
1678static PyObject*
1679DB_get_type(DBObject* self, PyObject* args)
1680{
1681 int type;
1682
1683 if (!PyArg_ParseTuple(args,":get_type"))
1684 return NULL;
1685 CHECK_DB_NOT_CLOSED(self);
1686
1687 MYDB_BEGIN_ALLOW_THREADS;
1688 type = _DB_get_type(self);
1689 MYDB_END_ALLOW_THREADS;
1690 if (type == -1)
1691 return NULL;
1692 return PyInt_FromLong(type);
1693}
1694
1695
1696static PyObject*
1697DB_join(DBObject* self, PyObject* args)
1698{
1699 int err, flags=0;
1700 int length, x;
1701 PyObject* cursorsObj;
1702 DBC** cursors;
1703 DBC* dbc;
1704
1705
1706 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1707 return NULL;
1708
1709 CHECK_DB_NOT_CLOSED(self);
1710
1711 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001712 PyErr_SetString(PyExc_TypeError,
1713 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 return NULL;
1715 }
1716
1717 length = PyObject_Length(cursorsObj);
1718 cursors = malloc((length+1) * sizeof(DBC*));
1719 cursors[length] = NULL;
1720 for (x=0; x<length; x++) {
1721 PyObject* item = PySequence_GetItem(cursorsObj, x);
1722 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001723 PyErr_SetString(PyExc_TypeError,
1724 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001725 free(cursors);
1726 return NULL;
1727 }
1728 cursors[x] = ((DBCursorObject*)item)->dbc;
1729 }
1730
1731 MYDB_BEGIN_ALLOW_THREADS;
1732 err = self->db->join(self->db, cursors, &dbc, flags);
1733 MYDB_END_ALLOW_THREADS;
1734 free(cursors);
1735 RETURN_IF_ERR();
1736
Gregory P. Smith7441e652003-11-03 21:35:31 +00001737 /* FIXME: this is a buggy interface. The returned cursor
1738 contains internal references to the passed in cursors
1739 but does not hold python references to them or prevent
1740 them from being closed prematurely. This can cause
1741 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 return (PyObject*) newDBCursorObject(dbc, self);
1743}
1744
1745
1746static PyObject*
1747DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1748{
1749 int err, flags=0;
1750 PyObject* txnobj = NULL;
1751 PyObject* keyobj;
1752 DBT key;
1753 DB_TXN *txn = NULL;
1754 DB_KEY_RANGE range;
1755 char* kwnames[] = { "key", "txn", "flags", NULL };
1756
1757 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1758 &keyobj, &txnobj, &flags))
1759 return NULL;
1760 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001761 if (!make_dbt(keyobj, &key))
1762 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001763 return NULL;
1764 if (!checkTxnObj(txnobj, &txn))
1765 return NULL;
1766
1767 MYDB_BEGIN_ALLOW_THREADS;
1768 err = self->db->key_range(self->db, txn, &key, &range, flags);
1769 MYDB_END_ALLOW_THREADS;
1770
1771 RETURN_IF_ERR();
1772 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1773}
1774
1775
1776static PyObject*
1777DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1778{
1779 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1780 char* filename = NULL;
1781 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001782#if (DBVER >= 41)
1783 PyObject *txnobj = NULL;
1784 DB_TXN *txn = NULL;
1785 /* with dbname */
1786 char* kwnames[] = {
1787 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1788 /* without dbname */
1789 char* kwnames_basic[] = {
1790 "filename", "dbtype", "flags", "mode", "txn", NULL};
1791#else
1792 /* with dbname */
1793 char* kwnames[] = {
1794 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1795 /* without dbname */
1796 char* kwnames_basic[] = {
1797 "filename", "dbtype", "flags", "mode", NULL};
1798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001800#if (DBVER >= 41)
1801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1802 &filename, &dbname, &type, &flags, &mode,
1803 &txnobj))
1804#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001806 &filename, &dbname, &type, &flags,
1807 &mode))
1808#endif
1809 {
1810 PyErr_Clear();
1811 type = DB_UNKNOWN; flags = 0; mode = 0660;
1812 filename = NULL; dbname = NULL;
1813#if (DBVER >= 41)
1814 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1815 kwnames_basic,
1816 &filename, &type, &flags, &mode,
1817 &txnobj))
1818 return NULL;
1819#else
1820 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1821 kwnames_basic,
1822 &filename, &type, &flags, &mode))
1823 return NULL;
1824#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 }
1826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827#if (DBVER >= 41)
1828 if (!checkTxnObj(txnobj, &txn)) return NULL;
1829#endif
1830
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 if (NULL == self->db) {
1832 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1833 "Cannot call open() twice for DB object"));
1834 return NULL;
1835 }
1836
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001837#if 0 && (DBVER >= 41)
1838 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1839 && (self->myenvobj->flags & DB_INIT_TXN))
1840 {
1841 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1842 * explicitly passed) but we are in a transaction ready environment:
1843 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1844 * to work on BerkeleyDB 4.1 without needing to modify their
1845 * DBEnv or DB open calls.
1846 * TODO make this behaviour of the library configurable.
1847 */
1848 flags |= DB_AUTO_COMMIT;
1849 }
1850#endif
1851
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001853#if (DBVER >= 41)
1854 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1855#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001857#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858 MYDB_END_ALLOW_THREADS;
1859 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001860 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 self->db = NULL;
1862 return NULL;
1863 }
1864
1865 self->flags = flags;
1866 RETURN_NONE();
1867}
1868
1869
1870static PyObject*
1871DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1872{
1873 int flags=0;
1874 PyObject* txnobj = NULL;
1875 int dlen = -1;
1876 int doff = -1;
1877 PyObject* keyobj, *dataobj, *retval;
1878 DBT key, data;
1879 DB_TXN *txn = NULL;
1880 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1881
1882 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1883 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1884 return NULL;
1885
1886 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001887 if (!make_key_dbt(self, keyobj, &key, NULL))
1888 return NULL;
1889 if ( !make_dbt(dataobj, &data) ||
1890 !add_partial_dbt(&data, dlen, doff) ||
1891 !checkTxnObj(txnobj, &txn) )
1892 {
1893 FREE_DBT(key);
1894 return NULL;
1895 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001896
1897 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1898 FREE_DBT(key);
1899 return NULL;
1900 }
1901
1902 if (flags & DB_APPEND)
1903 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1904 else {
1905 retval = Py_None;
1906 Py_INCREF(retval);
1907 }
1908 FREE_DBT(key);
1909 return retval;
1910}
1911
1912
1913
1914static PyObject*
1915DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1916{
1917 char* filename;
1918 char* database = NULL;
1919 int err, flags=0;
1920 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1921
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1923 &filename, &database, &flags))
1924 return NULL;
1925 CHECK_DB_NOT_CLOSED(self);
1926
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001927 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001928 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001929 RETURN_IF_ERR();
1930 RETURN_NONE();
1931}
1932
1933
1934
1935static PyObject*
1936DB_rename(DBObject* self, PyObject* args)
1937{
1938 char* filename;
1939 char* database;
1940 char* newname;
1941 int err, flags=0;
1942
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001943 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1944 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945 return NULL;
1946 CHECK_DB_NOT_CLOSED(self);
1947
1948 MYDB_BEGIN_ALLOW_THREADS;
1949 err = self->db->rename(self->db, filename, database, newname, flags);
1950 MYDB_END_ALLOW_THREADS;
1951 RETURN_IF_ERR();
1952 RETURN_NONE();
1953}
1954
1955
1956static PyObject*
1957DB_set_bt_minkey(DBObject* self, PyObject* args)
1958{
1959 int err, minkey;
1960
1961 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1962 return NULL;
1963 CHECK_DB_NOT_CLOSED(self);
1964
1965 MYDB_BEGIN_ALLOW_THREADS;
1966 err = self->db->set_bt_minkey(self->db, minkey);
1967 MYDB_END_ALLOW_THREADS;
1968 RETURN_IF_ERR();
1969 RETURN_NONE();
1970}
1971
Neal Norwitz84562352005-10-20 04:30:15 +00001972#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001973static int
1974_default_cmp (const DBT *leftKey,
1975 const DBT *rightKey)
1976{
1977 int res;
1978 int lsize = leftKey->size, rsize = rightKey->size;
1979
1980 res = memcmp (leftKey->data, rightKey->data,
1981 lsize < rsize ? lsize : rsize);
1982
1983 if (res == 0) {
1984 if (lsize < rsize) {
1985 res = -1;
1986 }
1987 else if (lsize > rsize) {
1988 res = 1;
1989 }
1990 }
1991 return res;
1992}
1993
1994static int
1995_db_compareCallback (DB* db,
1996 const DBT *leftKey,
1997 const DBT *rightKey)
1998{
1999 int res = 0;
2000 PyObject *args;
2001 PyObject *result;
2002 PyObject *leftObject;
2003 PyObject *rightObject;
2004 DBObject *self = (DBObject *) db->app_private;
2005
2006 if (self == NULL || self->btCompareCallback == NULL) {
2007 MYDB_BEGIN_BLOCK_THREADS;
2008 PyErr_SetString (PyExc_TypeError,
2009 (self == 0
2010 ? "DB_bt_compare db is NULL."
2011 : "DB_bt_compare callback is NULL."));
2012 /* we're in a callback within the DB code, we can't raise */
2013 PyErr_Print ();
2014 res = _default_cmp (leftKey, rightKey);
2015 MYDB_END_BLOCK_THREADS;
2016 }
2017 else {
2018 MYDB_BEGIN_BLOCK_THREADS;
2019
2020 leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size);
2021 rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size);
2022
Gregory P. Smithac741c52005-06-06 17:31:32 +00002023 args = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002024 Py_INCREF (self);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002025 PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */
2026 PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002027
2028 result = PyEval_CallObject (self->btCompareCallback, args);
2029 if (result == 0) {
2030 /* we're in a callback within the DB code, we can't raise */
Gregory P. Smith8966d3d2005-06-16 19:01:42 +00002031 PyErr_Print ();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002032 res = _default_cmp (leftKey, rightKey);
2033 }
2034 else if (PyInt_Check (result)) {
2035 res = PyInt_AsLong (result);
2036 }
2037 else {
2038 PyErr_SetString (PyExc_TypeError,
2039 "DB_bt_compare callback MUST return an int.");
2040 /* we're in a callback within the DB code, we can't raise */
2041 PyErr_Print ();
2042 res = _default_cmp (leftKey, rightKey);
2043 }
2044
2045 Py_DECREF (args);
2046 Py_XDECREF (result);
2047
2048 MYDB_END_BLOCK_THREADS;
2049 }
2050 return res;
2051}
2052
2053static PyObject*
2054DB_set_bt_compare (DBObject* self, PyObject* args)
2055{
2056 int err;
2057 PyObject *comparator;
2058 PyObject *tuple, *emptyStr, *result;
2059
2060 if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator ))
2061 return NULL;
2062
2063 CHECK_DB_NOT_CLOSED (self);
2064
2065 if (! PyCallable_Check (comparator)) {
2066 makeTypeError ("Callable", comparator);
2067 return NULL;
2068 }
2069
2070 /*
2071 * Perform a test call of the comparator function with two empty
2072 * string objects here. verify that it returns an int (0).
2073 * err if not.
2074 */
Gregory P. Smithac741c52005-06-06 17:31:32 +00002075 tuple = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002076
2077 emptyStr = PyString_FromStringAndSize (NULL, 0);
2078 Py_INCREF(emptyStr);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002079 PyTuple_SET_ITEM (tuple, 0, emptyStr);
2080 PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081 result = PyEval_CallObject (comparator, tuple);
2082 Py_DECREF (tuple);
2083 if (result == 0 || !PyInt_Check(result)) {
2084 PyErr_SetString (PyExc_TypeError,
2085 "callback MUST return an int");
2086 return NULL;
2087 }
2088 else if (PyInt_AsLong(result) != 0) {
2089 PyErr_SetString (PyExc_TypeError,
2090 "callback failed to return 0 on two empty strings");
2091 return NULL;
2092 }
2093
2094 /* We don't accept multiple set_bt_compare operations, in order to
2095 * simplify the code. This would have no real use, as one cannot
2096 * change the function once the db is opened anyway */
2097 if (self->btCompareCallback != NULL) {
2098 PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once");
2099 return NULL;
2100 }
2101
2102 Py_INCREF (comparator);
2103 self->btCompareCallback = comparator;
2104
2105 /* This is to workaround a problem with un-initialized threads (see
2106 comment in DB_associate) */
2107#ifdef WITH_THREAD
2108 PyEval_InitThreads();
2109#endif
2110
2111 err = self->db->set_bt_compare (self->db,
2112 (comparator != NULL ?
2113 _db_compareCallback : NULL));
2114
2115 if (err) {
2116 /* restore the old state in case of error */
2117 Py_DECREF (comparator);
2118 self->btCompareCallback = NULL;
2119 }
2120
2121 RETURN_IF_ERR ();
2122 RETURN_NONE ();
2123}
Neal Norwitz84562352005-10-20 04:30:15 +00002124#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002126
2127static PyObject*
2128DB_set_cachesize(DBObject* self, PyObject* args)
2129{
2130 int err;
2131 int gbytes = 0, bytes = 0, ncache = 0;
2132
2133 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2134 &gbytes,&bytes,&ncache))
2135 return NULL;
2136 CHECK_DB_NOT_CLOSED(self);
2137
2138 MYDB_BEGIN_ALLOW_THREADS;
2139 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2140 MYDB_END_ALLOW_THREADS;
2141 RETURN_IF_ERR();
2142 RETURN_NONE();
2143}
2144
2145
2146static PyObject*
2147DB_set_flags(DBObject* self, PyObject* args)
2148{
2149 int err, flags;
2150
2151 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2152 return NULL;
2153 CHECK_DB_NOT_CLOSED(self);
2154
2155 MYDB_BEGIN_ALLOW_THREADS;
2156 err = self->db->set_flags(self->db, flags);
2157 MYDB_END_ALLOW_THREADS;
2158 RETURN_IF_ERR();
2159
2160 self->setflags |= flags;
2161 RETURN_NONE();
2162}
2163
2164
2165static PyObject*
2166DB_set_h_ffactor(DBObject* self, PyObject* args)
2167{
2168 int err, ffactor;
2169
2170 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2171 return NULL;
2172 CHECK_DB_NOT_CLOSED(self);
2173
2174 MYDB_BEGIN_ALLOW_THREADS;
2175 err = self->db->set_h_ffactor(self->db, ffactor);
2176 MYDB_END_ALLOW_THREADS;
2177 RETURN_IF_ERR();
2178 RETURN_NONE();
2179}
2180
2181
2182static PyObject*
2183DB_set_h_nelem(DBObject* self, PyObject* args)
2184{
2185 int err, nelem;
2186
2187 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2188 return NULL;
2189 CHECK_DB_NOT_CLOSED(self);
2190
2191 MYDB_BEGIN_ALLOW_THREADS;
2192 err = self->db->set_h_nelem(self->db, nelem);
2193 MYDB_END_ALLOW_THREADS;
2194 RETURN_IF_ERR();
2195 RETURN_NONE();
2196}
2197
2198
2199static PyObject*
2200DB_set_lorder(DBObject* self, PyObject* args)
2201{
2202 int err, lorder;
2203
2204 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2205 return NULL;
2206 CHECK_DB_NOT_CLOSED(self);
2207
2208 MYDB_BEGIN_ALLOW_THREADS;
2209 err = self->db->set_lorder(self->db, lorder);
2210 MYDB_END_ALLOW_THREADS;
2211 RETURN_IF_ERR();
2212 RETURN_NONE();
2213}
2214
2215
2216static PyObject*
2217DB_set_pagesize(DBObject* self, PyObject* args)
2218{
2219 int err, pagesize;
2220
2221 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2222 return NULL;
2223 CHECK_DB_NOT_CLOSED(self);
2224
2225 MYDB_BEGIN_ALLOW_THREADS;
2226 err = self->db->set_pagesize(self->db, pagesize);
2227 MYDB_END_ALLOW_THREADS;
2228 RETURN_IF_ERR();
2229 RETURN_NONE();
2230}
2231
2232
2233static PyObject*
2234DB_set_re_delim(DBObject* self, PyObject* args)
2235{
2236 int err;
2237 char delim;
2238
2239 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2240 PyErr_Clear();
2241 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2242 return NULL;
2243 }
2244
2245 CHECK_DB_NOT_CLOSED(self);
2246
2247 MYDB_BEGIN_ALLOW_THREADS;
2248 err = self->db->set_re_delim(self->db, delim);
2249 MYDB_END_ALLOW_THREADS;
2250 RETURN_IF_ERR();
2251 RETURN_NONE();
2252}
2253
2254static PyObject*
2255DB_set_re_len(DBObject* self, PyObject* args)
2256{
2257 int err, len;
2258
2259 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2260 return NULL;
2261 CHECK_DB_NOT_CLOSED(self);
2262
2263 MYDB_BEGIN_ALLOW_THREADS;
2264 err = self->db->set_re_len(self->db, len);
2265 MYDB_END_ALLOW_THREADS;
2266 RETURN_IF_ERR();
2267 RETURN_NONE();
2268}
2269
2270
2271static PyObject*
2272DB_set_re_pad(DBObject* self, PyObject* args)
2273{
2274 int err;
2275 char pad;
2276
2277 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2278 PyErr_Clear();
2279 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2280 return NULL;
2281 }
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_re_pad(self->db, pad);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
2291
2292static PyObject*
2293DB_set_re_source(DBObject* self, PyObject* args)
2294{
2295 int err;
2296 char *re_source;
2297
2298 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2299 return NULL;
2300 CHECK_DB_NOT_CLOSED(self);
2301
2302 MYDB_BEGIN_ALLOW_THREADS;
2303 err = self->db->set_re_source(self->db, re_source);
2304 MYDB_END_ALLOW_THREADS;
2305 RETURN_IF_ERR();
2306 RETURN_NONE();
2307}
2308
2309
2310#if (DBVER >= 32)
2311static PyObject*
2312DB_set_q_extentsize(DBObject* self, PyObject* args)
2313{
2314 int err;
2315 int extentsize;
2316
2317 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2318 return NULL;
2319 CHECK_DB_NOT_CLOSED(self);
2320
2321 MYDB_BEGIN_ALLOW_THREADS;
2322 err = self->db->set_q_extentsize(self->db, extentsize);
2323 MYDB_END_ALLOW_THREADS;
2324 RETURN_IF_ERR();
2325 RETURN_NONE();
2326}
2327#endif
2328
2329static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002330DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002331{
2332 int err, flags = 0, type;
2333 void* sp;
2334 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002335#if (DBVER >= 43)
2336 PyObject* txnobj = NULL;
2337 DB_TXN *txn = NULL;
2338 char* kwnames[] = { "txn", "flags", NULL };
2339#else
2340 char* kwnames[] = { "flags", NULL };
2341#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002342
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002343#if (DBVER >= 43)
2344 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2345 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002346 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002347 if (!checkTxnObj(txnobj, &txn))
2348 return NULL;
2349#else
2350 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2351 return NULL;
2352#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002353 CHECK_DB_NOT_CLOSED(self);
2354
2355 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002356#if (DBVER >= 43)
2357 err = self->db->stat(self->db, txn, &sp, flags);
2358#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002359 err = self->db->stat(self->db, &sp, flags);
2360#else
2361 err = self->db->stat(self->db, &sp, NULL, flags);
2362#endif
2363 MYDB_END_ALLOW_THREADS;
2364 RETURN_IF_ERR();
2365
2366 self->haveStat = 1;
2367
2368 /* Turn the stat structure into a dictionary */
2369 type = _DB_get_type(self);
2370 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2371 free(sp);
2372 return NULL;
2373 }
2374
2375#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2376#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2377#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2378
2379 switch (type) {
2380 case DB_HASH:
2381 MAKE_HASH_ENTRY(magic);
2382 MAKE_HASH_ENTRY(version);
2383 MAKE_HASH_ENTRY(nkeys);
2384 MAKE_HASH_ENTRY(ndata);
2385 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002386#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002387 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002388#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002389 MAKE_HASH_ENTRY(ffactor);
2390 MAKE_HASH_ENTRY(buckets);
2391 MAKE_HASH_ENTRY(free);
2392 MAKE_HASH_ENTRY(bfree);
2393 MAKE_HASH_ENTRY(bigpages);
2394 MAKE_HASH_ENTRY(big_bfree);
2395 MAKE_HASH_ENTRY(overflows);
2396 MAKE_HASH_ENTRY(ovfl_free);
2397 MAKE_HASH_ENTRY(dup);
2398 MAKE_HASH_ENTRY(dup_free);
2399 break;
2400
2401 case DB_BTREE:
2402 case DB_RECNO:
2403 MAKE_BT_ENTRY(magic);
2404 MAKE_BT_ENTRY(version);
2405 MAKE_BT_ENTRY(nkeys);
2406 MAKE_BT_ENTRY(ndata);
2407 MAKE_BT_ENTRY(pagesize);
2408 MAKE_BT_ENTRY(minkey);
2409 MAKE_BT_ENTRY(re_len);
2410 MAKE_BT_ENTRY(re_pad);
2411 MAKE_BT_ENTRY(levels);
2412 MAKE_BT_ENTRY(int_pg);
2413 MAKE_BT_ENTRY(leaf_pg);
2414 MAKE_BT_ENTRY(dup_pg);
2415 MAKE_BT_ENTRY(over_pg);
2416 MAKE_BT_ENTRY(free);
2417 MAKE_BT_ENTRY(int_pgfree);
2418 MAKE_BT_ENTRY(leaf_pgfree);
2419 MAKE_BT_ENTRY(dup_pgfree);
2420 MAKE_BT_ENTRY(over_pgfree);
2421 break;
2422
2423 case DB_QUEUE:
2424 MAKE_QUEUE_ENTRY(magic);
2425 MAKE_QUEUE_ENTRY(version);
2426 MAKE_QUEUE_ENTRY(nkeys);
2427 MAKE_QUEUE_ENTRY(ndata);
2428 MAKE_QUEUE_ENTRY(pagesize);
2429 MAKE_QUEUE_ENTRY(pages);
2430 MAKE_QUEUE_ENTRY(re_len);
2431 MAKE_QUEUE_ENTRY(re_pad);
2432 MAKE_QUEUE_ENTRY(pgfree);
2433#if (DBVER == 31)
2434 MAKE_QUEUE_ENTRY(start);
2435#endif
2436 MAKE_QUEUE_ENTRY(first_recno);
2437 MAKE_QUEUE_ENTRY(cur_recno);
2438 break;
2439
2440 default:
2441 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2442 Py_DECREF(d);
2443 d = NULL;
2444 }
2445
2446#undef MAKE_HASH_ENTRY
2447#undef MAKE_BT_ENTRY
2448#undef MAKE_QUEUE_ENTRY
2449
2450 free(sp);
2451 return d;
2452}
2453
2454static PyObject*
2455DB_sync(DBObject* self, PyObject* args)
2456{
2457 int err;
2458 int flags = 0;
2459
2460 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2461 return NULL;
2462 CHECK_DB_NOT_CLOSED(self);
2463
2464 MYDB_BEGIN_ALLOW_THREADS;
2465 err = self->db->sync(self->db, flags);
2466 MYDB_END_ALLOW_THREADS;
2467 RETURN_IF_ERR();
2468 RETURN_NONE();
2469}
2470
2471
2472#if (DBVER >= 33)
2473static PyObject*
2474DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2475{
2476 int err, flags=0;
2477 u_int32_t count=0;
2478 PyObject* txnobj = NULL;
2479 DB_TXN *txn = NULL;
2480 char* kwnames[] = { "txn", "flags", NULL };
2481
2482 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2483 &txnobj, &flags))
2484 return NULL;
2485 CHECK_DB_NOT_CLOSED(self);
2486 if (!checkTxnObj(txnobj, &txn))
2487 return NULL;
2488
2489 MYDB_BEGIN_ALLOW_THREADS;
2490 err = self->db->truncate(self->db, txn, &count, flags);
2491 MYDB_END_ALLOW_THREADS;
2492 RETURN_IF_ERR();
2493 return PyInt_FromLong(count);
2494}
2495#endif
2496
2497
2498static PyObject*
2499DB_upgrade(DBObject* self, PyObject* args)
2500{
2501 int err, flags=0;
2502 char *filename;
2503
2504 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2505 return NULL;
2506 CHECK_DB_NOT_CLOSED(self);
2507
2508 MYDB_BEGIN_ALLOW_THREADS;
2509 err = self->db->upgrade(self->db, filename, flags);
2510 MYDB_END_ALLOW_THREADS;
2511 RETURN_IF_ERR();
2512 RETURN_NONE();
2513}
2514
2515
2516static PyObject*
2517DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2518{
2519 int err, flags=0;
2520 char* fileName;
2521 char* dbName=NULL;
2522 char* outFileName=NULL;
2523 FILE* outFile=NULL;
2524 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2525
2526 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2527 &fileName, &dbName, &outFileName, &flags))
2528 return NULL;
2529
2530 CHECK_DB_NOT_CLOSED(self);
2531 if (outFileName)
2532 outFile = fopen(outFileName, "w");
2533
2534 MYDB_BEGIN_ALLOW_THREADS;
2535 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2536 MYDB_END_ALLOW_THREADS;
2537 if (outFileName)
2538 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002539
2540 /* DB.verify acts as a DB handle destructor (like close); this was
2541 * documented in BerkeleyDB 4.2 but had the undocumented effect
2542 * of not being safe in prior versions while still requiring an explicit
2543 * DB.close call afterwards. Lets call close for the user to emulate
2544 * the safe 4.2 behaviour. */
2545#if (DBVER <= 41)
2546 self->db->close(self->db, 0);
2547#endif
2548 self->db = NULL;
2549
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002550 RETURN_IF_ERR();
2551 RETURN_NONE();
2552}
2553
2554
2555static PyObject*
2556DB_set_get_returns_none(DBObject* self, PyObject* args)
2557{
2558 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002559 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002560
2561 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2562 return NULL;
2563 CHECK_DB_NOT_CLOSED(self);
2564
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002565 if (self->moduleFlags.getReturnsNone)
2566 ++oldValue;
2567 if (self->moduleFlags.cursorSetReturnsNone)
2568 ++oldValue;
2569 self->moduleFlags.getReturnsNone = (flags >= 1);
2570 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002571 return PyInt_FromLong(oldValue);
2572}
2573
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002574#if (DBVER >= 41)
2575static PyObject*
2576DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2577{
2578 int err;
2579 u_int32_t flags=0;
2580 char *passwd = NULL;
2581 char* kwnames[] = { "passwd", "flags", NULL };
2582
2583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2584 &passwd, &flags)) {
2585 return NULL;
2586 }
2587
2588 MYDB_BEGIN_ALLOW_THREADS;
2589 err = self->db->set_encrypt(self->db, passwd, flags);
2590 MYDB_END_ALLOW_THREADS;
2591
2592 RETURN_IF_ERR();
2593 RETURN_NONE();
2594}
2595#endif /* DBVER >= 41 */
2596
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002597
2598/*-------------------------------------------------------------- */
2599/* Mapping and Dictionary-like access routines */
2600
2601int DB_length(DBObject* self)
2602{
2603 int err;
2604 long size = 0;
2605 int flags = 0;
2606 void* sp;
2607
2608 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002609 PyErr_SetObject(DBError,
2610 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002611 return -1;
2612 }
2613
2614 if (self->haveStat) { /* Has the stat function been called recently? If
2615 so, we can use the cached value. */
2616 flags = DB_CACHED_COUNTS;
2617 }
2618
2619 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002620#if (DBVER >= 43)
2621 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2622#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002623 err = self->db->stat(self->db, &sp, flags);
2624#else
2625 err = self->db->stat(self->db, &sp, NULL, flags);
2626#endif
2627 MYDB_END_ALLOW_THREADS;
2628
2629 if (err)
2630 return -1;
2631
2632 self->haveStat = 1;
2633
2634 /* All the stat structures have matching fields upto the ndata field,
2635 so we can use any of them for the type cast */
2636 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2637 free(sp);
2638 return size;
2639}
2640
2641
2642PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2643{
2644 int err;
2645 PyObject* retval;
2646 DBT key;
2647 DBT data;
2648
2649 CHECK_DB_NOT_CLOSED(self);
2650 if (!make_key_dbt(self, keyobj, &key, NULL))
2651 return NULL;
2652
2653 CLEAR_DBT(data);
2654 if (CHECK_DBFLAG(self, DB_THREAD)) {
2655 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2656 data.flags = DB_DBT_MALLOC;
2657 }
2658 MYDB_BEGIN_ALLOW_THREADS;
2659 err = self->db->get(self->db, NULL, &key, &data, 0);
2660 MYDB_END_ALLOW_THREADS;
2661 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2662 PyErr_SetObject(PyExc_KeyError, keyobj);
2663 retval = NULL;
2664 }
2665 else if (makeDBError(err)) {
2666 retval = NULL;
2667 }
2668 else {
2669 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2670 FREE_DBT(data);
2671 }
2672
2673 FREE_DBT(key);
2674 return retval;
2675}
2676
2677
2678static int
2679DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2680{
2681 DBT key, data;
2682 int retval;
2683 int flags = 0;
2684
2685 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002686 PyErr_SetObject(DBError,
2687 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 return -1;
2689 }
2690
2691 if (!make_key_dbt(self, keyobj, &key, NULL))
2692 return -1;
2693
2694 if (dataobj != NULL) {
2695 if (!make_dbt(dataobj, &data))
2696 retval = -1;
2697 else {
2698 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002699 /* dictionaries shouldn't have duplicate keys */
2700 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002701 retval = _DB_put(self, NULL, &key, &data, flags);
2702
2703 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002704 /* try deleting any old record that matches and then PUT it
2705 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 _DB_delete(self, NULL, &key, 0);
2707 PyErr_Clear();
2708 retval = _DB_put(self, NULL, &key, &data, flags);
2709 }
2710 }
2711 }
2712 else {
2713 /* dataobj == NULL, so delete the key */
2714 retval = _DB_delete(self, NULL, &key, 0);
2715 }
2716 FREE_DBT(key);
2717 return retval;
2718}
2719
2720
2721static PyObject*
2722DB_has_key(DBObject* self, PyObject* args)
2723{
2724 int err;
2725 PyObject* keyobj;
2726 DBT key, data;
2727 PyObject* txnobj = NULL;
2728 DB_TXN *txn = NULL;
2729
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002730 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002731 return NULL;
2732 CHECK_DB_NOT_CLOSED(self);
2733 if (!make_key_dbt(self, keyobj, &key, NULL))
2734 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002735 if (!checkTxnObj(txnobj, &txn)) {
2736 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002738 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002739
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002740 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002741 it has a record but can't allocate a buffer for the data. This saves
2742 having to deal with data we won't be using.
2743 */
2744 CLEAR_DBT(data);
2745 data.flags = DB_DBT_USERMEM;
2746
2747 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002748 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002749 MYDB_END_ALLOW_THREADS;
2750 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002751
2752 if (err == DB_BUFFER_SMALL || err == 0) {
2753 return PyInt_FromLong(1);
2754 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2755 return PyInt_FromLong(0);
2756 }
2757
2758 makeDBError(err);
2759 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002760}
2761
2762
2763#define _KEYS_LIST 1
2764#define _VALUES_LIST 2
2765#define _ITEMS_LIST 3
2766
2767static PyObject*
2768_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2769{
2770 int err, dbtype;
2771 DBT key;
2772 DBT data;
2773 DBC *cursor;
2774 PyObject* list;
2775 PyObject* item = NULL;
2776
2777 CHECK_DB_NOT_CLOSED(self);
2778 CLEAR_DBT(key);
2779 CLEAR_DBT(data);
2780
2781 dbtype = _DB_get_type(self);
2782 if (dbtype == -1)
2783 return NULL;
2784
2785 list = PyList_New(0);
2786 if (list == NULL) {
2787 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2788 return NULL;
2789 }
2790
2791 /* get a cursor */
2792 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002793 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002794 MYDB_END_ALLOW_THREADS;
2795 RETURN_IF_ERR();
2796
2797 if (CHECK_DBFLAG(self, DB_THREAD)) {
2798 key.flags = DB_DBT_REALLOC;
2799 data.flags = DB_DBT_REALLOC;
2800 }
2801
2802 while (1) { /* use the cursor to traverse the DB, collecting items */
2803 MYDB_BEGIN_ALLOW_THREADS;
2804 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2805 MYDB_END_ALLOW_THREADS;
2806
2807 if (err) {
2808 /* for any error, break out of the loop */
2809 break;
2810 }
2811
2812 switch (type) {
2813 case _KEYS_LIST:
2814 switch(dbtype) {
2815 case DB_BTREE:
2816 case DB_HASH:
2817 default:
2818 item = PyString_FromStringAndSize((char*)key.data, key.size);
2819 break;
2820 case DB_RECNO:
2821 case DB_QUEUE:
2822 item = PyInt_FromLong(*((db_recno_t*)key.data));
2823 break;
2824 }
2825 break;
2826
2827 case _VALUES_LIST:
2828 item = PyString_FromStringAndSize((char*)data.data, data.size);
2829 break;
2830
2831 case _ITEMS_LIST:
2832 switch(dbtype) {
2833 case DB_BTREE:
2834 case DB_HASH:
2835 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002836 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2837 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 break;
2839 case DB_RECNO:
2840 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002841 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2842 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 break;
2844 }
2845 break;
2846 }
2847 if (item == NULL) {
2848 Py_DECREF(list);
2849 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2850 list = NULL;
2851 goto done;
2852 }
2853 PyList_Append(list, item);
2854 Py_DECREF(item);
2855 }
2856
Gregory P. Smithe9477062005-06-04 06:46:59 +00002857 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2858 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002859 Py_DECREF(list);
2860 list = NULL;
2861 }
2862
2863 done:
2864 FREE_DBT(key);
2865 FREE_DBT(data);
2866 MYDB_BEGIN_ALLOW_THREADS;
2867 cursor->c_close(cursor);
2868 MYDB_END_ALLOW_THREADS;
2869 return list;
2870}
2871
2872
2873static PyObject*
2874DB_keys(DBObject* self, PyObject* args)
2875{
2876 PyObject* txnobj = NULL;
2877 DB_TXN *txn = NULL;
2878
2879 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2880 return NULL;
2881 if (!checkTxnObj(txnobj, &txn))
2882 return NULL;
2883 return _DB_make_list(self, txn, _KEYS_LIST);
2884}
2885
2886
2887static PyObject*
2888DB_items(DBObject* self, PyObject* args)
2889{
2890 PyObject* txnobj = NULL;
2891 DB_TXN *txn = NULL;
2892
2893 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2894 return NULL;
2895 if (!checkTxnObj(txnobj, &txn))
2896 return NULL;
2897 return _DB_make_list(self, txn, _ITEMS_LIST);
2898}
2899
2900
2901static PyObject*
2902DB_values(DBObject* self, PyObject* args)
2903{
2904 PyObject* txnobj = NULL;
2905 DB_TXN *txn = NULL;
2906
2907 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2908 return NULL;
2909 if (!checkTxnObj(txnobj, &txn))
2910 return NULL;
2911 return _DB_make_list(self, txn, _VALUES_LIST);
2912}
2913
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002914/* --------------------------------------------------------------------- */
2915/* DBCursor methods */
2916
2917
2918static PyObject*
2919DBC_close(DBCursorObject* self, PyObject* args)
2920{
2921 int err = 0;
2922
2923 if (!PyArg_ParseTuple(args, ":close"))
2924 return NULL;
2925
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002926 if (self->dbc != NULL) {
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = self->dbc->c_close(self->dbc);
2929 self->dbc = NULL;
2930 MYDB_END_ALLOW_THREADS;
2931 }
2932 RETURN_IF_ERR();
2933 RETURN_NONE();
2934}
2935
2936
2937static PyObject*
2938DBC_count(DBCursorObject* self, PyObject* args)
2939{
2940 int err = 0;
2941 db_recno_t count;
2942 int flags = 0;
2943
2944 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2945 return NULL;
2946
2947 CHECK_CURSOR_NOT_CLOSED(self);
2948
2949 MYDB_BEGIN_ALLOW_THREADS;
2950 err = self->dbc->c_count(self->dbc, &count, flags);
2951 MYDB_END_ALLOW_THREADS;
2952 RETURN_IF_ERR();
2953
2954 return PyInt_FromLong(count);
2955}
2956
2957
2958static PyObject*
2959DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2960{
2961 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2962}
2963
2964
2965static PyObject*
2966DBC_delete(DBCursorObject* self, PyObject* args)
2967{
2968 int err, flags=0;
2969
2970 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2971 return NULL;
2972
2973 CHECK_CURSOR_NOT_CLOSED(self);
2974
2975 MYDB_BEGIN_ALLOW_THREADS;
2976 err = self->dbc->c_del(self->dbc, flags);
2977 MYDB_END_ALLOW_THREADS;
2978 RETURN_IF_ERR();
2979
2980 self->mydb->haveStat = 0;
2981 RETURN_NONE();
2982}
2983
2984
2985static PyObject*
2986DBC_dup(DBCursorObject* self, PyObject* args)
2987{
2988 int err, flags =0;
2989 DBC* dbc = NULL;
2990
2991 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2992 return NULL;
2993
2994 CHECK_CURSOR_NOT_CLOSED(self);
2995
2996 MYDB_BEGIN_ALLOW_THREADS;
2997 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2998 MYDB_END_ALLOW_THREADS;
2999 RETURN_IF_ERR();
3000
3001 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3002}
3003
3004static PyObject*
3005DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3006{
3007 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3008}
3009
3010
3011static PyObject*
3012DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3013{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003014 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 PyObject* keyobj = NULL;
3016 PyObject* dataobj = NULL;
3017 PyObject* retval = NULL;
3018 int dlen = -1;
3019 int doff = -1;
3020 DBT key, data;
3021 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
3022
3023 CLEAR_DBT(key);
3024 CLEAR_DBT(data);
3025 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003026 &flags, &dlen, &doff))
3027 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003029 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3030 &kwnames[1],
3031 &keyobj, &flags, &dlen, &doff))
3032 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003034 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3035 kwnames, &keyobj, &dataobj,
3036 &flags, &dlen, &doff))
3037 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003038 return NULL;
3039 }
3040 }
3041 }
3042
3043 CHECK_CURSOR_NOT_CLOSED(self);
3044
3045 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3046 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003047 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3048 (!add_partial_dbt(&data, dlen, doff)) )
3049 {
3050 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003052 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053
3054 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3055 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003056 if (!(key.flags & DB_DBT_REALLOC)) {
3057 key.flags |= DB_DBT_MALLOC;
3058 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059 }
3060
3061 MYDB_BEGIN_ALLOW_THREADS;
3062 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3063 MYDB_END_ALLOW_THREADS;
3064
Gregory P. Smithe9477062005-06-04 06:46:59 +00003065 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3066 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 Py_INCREF(Py_None);
3068 retval = Py_None;
3069 }
3070 else if (makeDBError(err)) {
3071 retval = NULL;
3072 }
3073 else {
3074 switch (_DB_get_type(self->mydb)) {
3075 case -1:
3076 retval = NULL;
3077 break;
3078 case DB_BTREE:
3079 case DB_HASH:
3080 default:
3081 retval = Py_BuildValue("s#s#", key.data, key.size,
3082 data.data, data.size);
3083 break;
3084 case DB_RECNO:
3085 case DB_QUEUE:
3086 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3087 data.data, data.size);
3088 break;
3089 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003090 FREE_DBT(data);
3091 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003092 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003093 return retval;
3094}
3095
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003096#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003097static PyObject*
3098DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3099{
3100 int err, flags=0;
3101 PyObject* keyobj = NULL;
3102 PyObject* dataobj = NULL;
3103 PyObject* retval = NULL;
3104 int dlen = -1;
3105 int doff = -1;
3106 DBT key, pkey, data;
3107 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
3108
3109 CLEAR_DBT(key);
3110 CLEAR_DBT(data);
3111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3112 &flags, &dlen, &doff))
3113 {
3114 PyErr_Clear();
3115 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3116 &kwnames[1],
3117 &keyobj, &flags, &dlen, &doff))
3118 {
3119 PyErr_Clear();
3120 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3121 kwnames, &keyobj, &dataobj,
3122 &flags, &dlen, &doff))
3123 {
3124 return NULL;
3125 }
3126 }
3127 }
3128
3129 CHECK_CURSOR_NOT_CLOSED(self);
3130
3131 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3132 return NULL;
3133 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3134 (!add_partial_dbt(&data, dlen, doff)) ) {
3135 FREE_DBT(key);
3136 return NULL;
3137 }
3138
3139 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3140 data.flags = DB_DBT_MALLOC;
3141 if (!(key.flags & DB_DBT_REALLOC)) {
3142 key.flags |= DB_DBT_MALLOC;
3143 }
3144 }
3145
3146 CLEAR_DBT(pkey);
3147 pkey.flags = DB_DBT_MALLOC;
3148
3149 MYDB_BEGIN_ALLOW_THREADS;
3150 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3151 MYDB_END_ALLOW_THREADS;
3152
Gregory P. Smithe9477062005-06-04 06:46:59 +00003153 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3154 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003155 Py_INCREF(Py_None);
3156 retval = Py_None;
3157 }
3158 else if (makeDBError(err)) {
3159 retval = NULL;
3160 }
3161 else {
3162 PyObject *pkeyObj;
3163 PyObject *dataObj;
3164 dataObj = PyString_FromStringAndSize(data.data, data.size);
3165
3166 if (self->mydb->primaryDBType == DB_RECNO ||
3167 self->mydb->primaryDBType == DB_QUEUE)
3168 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
3169 else
3170 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3171
3172 if (flags & DB_SET_RECNO) /* return key, pkey and data */
3173 {
3174 PyObject *keyObj;
3175 int type = _DB_get_type(self->mydb);
3176 if (type == DB_RECNO || type == DB_QUEUE)
3177 keyObj = PyInt_FromLong(*(long *)key.data);
3178 else
3179 keyObj = PyString_FromStringAndSize(key.data, key.size);
3180 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3181 FREE_DBT(key);
3182 }
3183 else /* return just the pkey and data */
3184 {
3185 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3186 }
3187 FREE_DBT(pkey);
3188 FREE_DBT(data);
3189 }
3190 /* the only time REALLOC should be set is if we used an integer
3191 * key that make_key_dbt malloc'd for us. always free these. */
3192 if (key.flags & DB_DBT_REALLOC) {
3193 FREE_DBT(key);
3194 }
3195 return retval;
3196}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003197#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003198
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003199
3200static PyObject*
3201DBC_get_recno(DBCursorObject* self, PyObject* args)
3202{
3203 int err;
3204 db_recno_t recno;
3205 DBT key;
3206 DBT data;
3207
3208 if (!PyArg_ParseTuple(args, ":get_recno"))
3209 return NULL;
3210
3211 CHECK_CURSOR_NOT_CLOSED(self);
3212
3213 CLEAR_DBT(key);
3214 CLEAR_DBT(data);
3215 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3216 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3217 data.flags = DB_DBT_MALLOC;
3218 key.flags = DB_DBT_MALLOC;
3219 }
3220
3221 MYDB_BEGIN_ALLOW_THREADS;
3222 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3223 MYDB_END_ALLOW_THREADS;
3224 RETURN_IF_ERR();
3225
3226 recno = *((db_recno_t*)data.data);
3227 FREE_DBT(key);
3228 FREE_DBT(data);
3229 return PyInt_FromLong(recno);
3230}
3231
3232
3233static PyObject*
3234DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3235{
3236 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3237}
3238
3239
3240static PyObject*
3241DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3242{
3243 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3244}
3245
3246
3247static PyObject*
3248DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3249{
3250 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3251}
3252
3253
3254static PyObject*
3255DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3256{
3257 int err, flags = 0;
3258 PyObject* keyobj, *dataobj;
3259 DBT key, data;
3260 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3261 int dlen = -1;
3262 int doff = -1;
3263
3264 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3265 &keyobj, &dataobj, &flags, &dlen, &doff))
3266 return NULL;
3267
3268 CHECK_CURSOR_NOT_CLOSED(self);
3269
3270 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3271 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003272 if (!make_dbt(dataobj, &data) ||
3273 !add_partial_dbt(&data, dlen, doff) )
3274 {
3275 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003276 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003277 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003278
3279 MYDB_BEGIN_ALLOW_THREADS;
3280 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3281 MYDB_END_ALLOW_THREADS;
3282 FREE_DBT(key);
3283 RETURN_IF_ERR();
3284 self->mydb->haveStat = 0;
3285 RETURN_NONE();
3286}
3287
3288
3289static PyObject*
3290DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3291{
3292 int err, flags = 0;
3293 DBT key, data;
3294 PyObject* retval, *keyobj;
3295 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3296 int dlen = -1;
3297 int doff = -1;
3298
3299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3300 &keyobj, &flags, &dlen, &doff))
3301 return NULL;
3302
3303 CHECK_CURSOR_NOT_CLOSED(self);
3304
3305 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3306 return NULL;
3307
3308 CLEAR_DBT(data);
3309 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3310 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3311 data.flags = DB_DBT_MALLOC;
3312 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003313 if (!add_partial_dbt(&data, dlen, doff)) {
3314 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003315 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003316 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003317
3318 MYDB_BEGIN_ALLOW_THREADS;
3319 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3320 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003321 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3322 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003323 Py_INCREF(Py_None);
3324 retval = Py_None;
3325 }
3326 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003327 retval = NULL;
3328 }
3329 else {
3330 switch (_DB_get_type(self->mydb)) {
3331 case -1:
3332 retval = NULL;
3333 break;
3334 case DB_BTREE:
3335 case DB_HASH:
3336 default:
3337 retval = Py_BuildValue("s#s#", key.data, key.size,
3338 data.data, data.size);
3339 break;
3340 case DB_RECNO:
3341 case DB_QUEUE:
3342 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3343 data.data, data.size);
3344 break;
3345 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003347 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003349 /* the only time REALLOC should be set is if we used an integer
3350 * key that make_key_dbt malloc'd for us. always free these. */
3351 if (key.flags & DB_DBT_REALLOC) {
3352 FREE_DBT(key);
3353 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354
3355 return retval;
3356}
3357
3358
3359static PyObject*
3360DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3361{
3362 int err, flags = 0;
3363 DBT key, data;
3364 PyObject* retval, *keyobj;
3365 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3366 int dlen = -1;
3367 int doff = -1;
3368
3369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3370 &keyobj, &flags, &dlen, &doff))
3371 return NULL;
3372
3373 CHECK_CURSOR_NOT_CLOSED(self);
3374
3375 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3376 return NULL;
3377
3378 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003379 if (!add_partial_dbt(&data, dlen, doff)) {
3380 FREE_DBT(key);
3381 return NULL;
3382 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003383 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3384 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003385 data.flags |= DB_DBT_MALLOC;
3386 /* only BTREE databases will return anything in the key */
3387 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3388 key.flags |= DB_DBT_MALLOC;
3389 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 MYDB_BEGIN_ALLOW_THREADS;
3392 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3393 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003394 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3395 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003396 Py_INCREF(Py_None);
3397 retval = Py_None;
3398 }
3399 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003400 retval = NULL;
3401 }
3402 else {
3403 switch (_DB_get_type(self->mydb)) {
3404 case -1:
3405 retval = NULL;
3406 break;
3407 case DB_BTREE:
3408 case DB_HASH:
3409 default:
3410 retval = Py_BuildValue("s#s#", key.data, key.size,
3411 data.data, data.size);
3412 break;
3413 case DB_RECNO:
3414 case DB_QUEUE:
3415 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3416 data.data, data.size);
3417 break;
3418 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003419 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003420 FREE_DBT(data);
3421 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003422 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003423 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003424 if (key.flags & DB_DBT_REALLOC) {
3425 FREE_DBT(key);
3426 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427
3428 return retval;
3429}
3430
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003432_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3433 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003434{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003435 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003436 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003437 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003438
Gregory P. Smith7441e652003-11-03 21:35:31 +00003439 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003440 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3441 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003442 if (!make_dbt(dataobj, &data)) {
3443 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003445 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446
3447 MYDB_BEGIN_ALLOW_THREADS;
3448 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3449 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003450 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003451 Py_INCREF(Py_None);
3452 retval = Py_None;
3453 }
3454 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003455 retval = NULL;
3456 }
3457 else {
3458 switch (_DB_get_type(self->mydb)) {
3459 case -1:
3460 retval = NULL;
3461 break;
3462 case DB_BTREE:
3463 case DB_HASH:
3464 default:
3465 retval = Py_BuildValue("s#s#", key.data, key.size,
3466 data.data, data.size);
3467 break;
3468 case DB_RECNO:
3469 case DB_QUEUE:
3470 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3471 data.data, data.size);
3472 break;
3473 }
3474 }
3475
3476 FREE_DBT(key);
3477 return retval;
3478}
3479
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003480static PyObject*
3481DBC_get_both(DBCursorObject* self, PyObject* args)
3482{
3483 int flags=0;
3484 PyObject *keyobj, *dataobj;
3485
3486 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3487 return NULL;
3488
Gregory P. Smith7441e652003-11-03 21:35:31 +00003489 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003490 CHECK_CURSOR_NOT_CLOSED(self);
3491
3492 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3493 self->mydb->moduleFlags.getReturnsNone);
3494}
3495
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003496/* Return size of entry */
3497static PyObject*
3498DBC_get_current_size(DBCursorObject* self, PyObject* args)
3499{
3500 int err, flags=DB_CURRENT;
3501 PyObject* retval = NULL;
3502 DBT key, data;
3503
3504 if (!PyArg_ParseTuple(args, ":get_current_size"))
3505 return NULL;
3506 CHECK_CURSOR_NOT_CLOSED(self);
3507 CLEAR_DBT(key);
3508 CLEAR_DBT(data);
3509
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003510 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003511 getting the record size. */
3512 data.flags = DB_DBT_USERMEM;
3513 data.ulen = 0;
3514 MYDB_BEGIN_ALLOW_THREADS;
3515 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3516 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003517 if (err == DB_BUFFER_SMALL || !err) {
3518 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003519 retval = PyInt_FromLong((long)data.size);
3520 err = 0;
3521 }
3522
3523 FREE_DBT(key);
3524 FREE_DBT(data);
3525 RETURN_IF_ERR();
3526 return retval;
3527}
3528
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003529static PyObject*
3530DBC_set_both(DBCursorObject* self, PyObject* args)
3531{
3532 int flags=0;
3533 PyObject *keyobj, *dataobj;
3534
3535 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3536 return NULL;
3537
Gregory P. Smith7441e652003-11-03 21:35:31 +00003538 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003539 CHECK_CURSOR_NOT_CLOSED(self);
3540
3541 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3542 self->mydb->moduleFlags.cursorSetReturnsNone);
3543}
3544
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545
3546static PyObject*
3547DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3548{
3549 int err, irecno, flags=0;
3550 db_recno_t recno;
3551 DBT key, data;
3552 PyObject* retval;
3553 int dlen = -1;
3554 int doff = -1;
3555 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3556
3557 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3558 &irecno, &flags, &dlen, &doff))
3559 return NULL;
3560
3561 CHECK_CURSOR_NOT_CLOSED(self);
3562
3563 CLEAR_DBT(key);
3564 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003565 /* use allocated space so DB will be able to realloc room for the real
3566 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567 key.data = malloc(sizeof(db_recno_t));
3568 if (key.data == NULL) {
3569 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3570 return NULL;
3571 }
3572 key.size = sizeof(db_recno_t);
3573 key.ulen = key.size;
3574 memcpy(key.data, &recno, sizeof(db_recno_t));
3575 key.flags = DB_DBT_REALLOC;
3576
3577 CLEAR_DBT(data);
3578 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3579 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3580 data.flags = DB_DBT_MALLOC;
3581 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003582 if (!add_partial_dbt(&data, dlen, doff)) {
3583 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003585 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586
3587 MYDB_BEGIN_ALLOW_THREADS;
3588 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3589 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003590 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3591 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003592 Py_INCREF(Py_None);
3593 retval = Py_None;
3594 }
3595 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 retval = NULL;
3597 }
3598 else { /* Can only be used for BTrees, so no need to return int key */
3599 retval = Py_BuildValue("s#s#", key.data, key.size,
3600 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003601 FREE_DBT(data);
3602 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003603 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604
3605 return retval;
3606}
3607
3608
3609static PyObject*
3610DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3611{
3612 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3613}
3614
3615
3616static PyObject*
3617DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3618{
3619 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3620}
3621
3622
3623static PyObject*
3624DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3625{
3626 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3627}
3628
3629
3630static PyObject*
3631DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3632{
3633 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3634}
3635
3636
3637static PyObject*
3638DBC_join_item(DBCursorObject* self, PyObject* args)
3639{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003640 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003641 DBT key, data;
3642 PyObject* retval;
3643
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003644 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003645 return NULL;
3646
3647 CHECK_CURSOR_NOT_CLOSED(self);
3648
3649 CLEAR_DBT(key);
3650 CLEAR_DBT(data);
3651 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3652 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3653 key.flags = DB_DBT_MALLOC;
3654 }
3655
3656 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003657 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003658 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003659 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3660 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003661 Py_INCREF(Py_None);
3662 retval = Py_None;
3663 }
3664 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003665 retval = NULL;
3666 }
3667 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003668 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003669 FREE_DBT(key);
3670 }
3671
3672 return retval;
3673}
3674
3675
3676
3677/* --------------------------------------------------------------------- */
3678/* DBEnv methods */
3679
3680
3681static PyObject*
3682DBEnv_close(DBEnvObject* self, PyObject* args)
3683{
3684 int err, flags = 0;
3685
3686 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3687 return NULL;
3688 if (!self->closed) { /* Don't close more than once */
3689 MYDB_BEGIN_ALLOW_THREADS;
3690 err = self->db_env->close(self->db_env, flags);
3691 MYDB_END_ALLOW_THREADS;
3692 /* after calling DBEnv->close, regardless of error, this DBEnv
3693 * may not be accessed again (BerkeleyDB docs). */
3694 self->closed = 1;
3695 self->db_env = NULL;
3696 RETURN_IF_ERR();
3697 }
3698 RETURN_NONE();
3699}
3700
3701
3702static PyObject*
3703DBEnv_open(DBEnvObject* self, PyObject* args)
3704{
3705 int err, flags=0, mode=0660;
3706 char *db_home;
3707
3708 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3709 return NULL;
3710
3711 CHECK_ENV_NOT_CLOSED(self);
3712
3713 MYDB_BEGIN_ALLOW_THREADS;
3714 err = self->db_env->open(self->db_env, db_home, flags, mode);
3715 MYDB_END_ALLOW_THREADS;
3716 RETURN_IF_ERR();
3717 self->closed = 0;
3718 self->flags = flags;
3719 RETURN_NONE();
3720}
3721
3722
3723static PyObject*
3724DBEnv_remove(DBEnvObject* self, PyObject* args)
3725{
3726 int err, flags=0;
3727 char *db_home;
3728
3729 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3730 return NULL;
3731 CHECK_ENV_NOT_CLOSED(self);
3732 MYDB_BEGIN_ALLOW_THREADS;
3733 err = self->db_env->remove(self->db_env, db_home, flags);
3734 MYDB_END_ALLOW_THREADS;
3735 RETURN_IF_ERR();
3736 RETURN_NONE();
3737}
3738
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003739#if (DBVER >= 41)
3740static PyObject*
3741DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3742{
3743 int err;
3744 u_int32_t flags=0;
3745 char *file = NULL;
3746 char *database = NULL;
3747 PyObject *txnobj = NULL;
3748 DB_TXN *txn = NULL;
3749 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3750
3751 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3752 &file, &database, &txnobj, &flags)) {
3753 return NULL;
3754 }
3755 if (!checkTxnObj(txnobj, &txn)) {
3756 return NULL;
3757 }
3758 CHECK_ENV_NOT_CLOSED(self);
3759 MYDB_BEGIN_ALLOW_THREADS;
3760 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3761 MYDB_END_ALLOW_THREADS;
3762 RETURN_IF_ERR();
3763 RETURN_NONE();
3764}
3765
3766static PyObject*
3767DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3768{
3769 int err;
3770 u_int32_t flags=0;
3771 char *file = NULL;
3772 char *database = NULL;
3773 char *newname = NULL;
3774 PyObject *txnobj = NULL;
3775 DB_TXN *txn = NULL;
3776 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3777
3778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3779 &file, &database, &newname, &txnobj, &flags)) {
3780 return NULL;
3781 }
3782 if (!checkTxnObj(txnobj, &txn)) {
3783 return NULL;
3784 }
3785 CHECK_ENV_NOT_CLOSED(self);
3786 MYDB_BEGIN_ALLOW_THREADS;
3787 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3788 flags);
3789 MYDB_END_ALLOW_THREADS;
3790 RETURN_IF_ERR();
3791 RETURN_NONE();
3792}
3793
3794static PyObject*
3795DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3796{
3797 int err;
3798 u_int32_t flags=0;
3799 char *passwd = NULL;
3800 char* kwnames[] = { "passwd", "flags", NULL };
3801
3802 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3803 &passwd, &flags)) {
3804 return NULL;
3805 }
3806
3807 MYDB_BEGIN_ALLOW_THREADS;
3808 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3809 MYDB_END_ALLOW_THREADS;
3810
3811 RETURN_IF_ERR();
3812 RETURN_NONE();
3813}
3814#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003816#if (DBVER >= 40)
3817static PyObject*
3818DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3819{
3820 int err;
3821 u_int32_t flags=0;
3822 u_int32_t timeout = 0;
3823 char* kwnames[] = { "timeout", "flags", NULL };
3824
3825 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3826 &timeout, &flags)) {
3827 return NULL;
3828 }
3829
3830 MYDB_BEGIN_ALLOW_THREADS;
3831 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3832 MYDB_END_ALLOW_THREADS;
3833
3834 RETURN_IF_ERR();
3835 RETURN_NONE();
3836}
3837#endif /* DBVER >= 40 */
3838
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003839static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003840DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3841{
3842 int err;
3843 long shm_key = 0;
3844
3845 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3846 return NULL;
3847 CHECK_ENV_NOT_CLOSED(self);
3848
3849 err = self->db_env->set_shm_key(self->db_env, shm_key);
3850 RETURN_IF_ERR();
3851 RETURN_NONE();
3852}
3853
3854static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3856{
3857 int err, gbytes=0, bytes=0, ncache=0;
3858
3859 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3860 &gbytes, &bytes, &ncache))
3861 return NULL;
3862 CHECK_ENV_NOT_CLOSED(self);
3863
3864 MYDB_BEGIN_ALLOW_THREADS;
3865 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3866 MYDB_END_ALLOW_THREADS;
3867 RETURN_IF_ERR();
3868 RETURN_NONE();
3869}
3870
3871
3872#if (DBVER >= 32)
3873static PyObject*
3874DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3875{
3876 int err, flags=0, onoff=0;
3877
3878 if (!PyArg_ParseTuple(args, "ii:set_flags",
3879 &flags, &onoff))
3880 return NULL;
3881 CHECK_ENV_NOT_CLOSED(self);
3882
3883 MYDB_BEGIN_ALLOW_THREADS;
3884 err = self->db_env->set_flags(self->db_env, flags, onoff);
3885 MYDB_END_ALLOW_THREADS;
3886 RETURN_IF_ERR();
3887 RETURN_NONE();
3888}
3889#endif
3890
3891
3892static PyObject*
3893DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3894{
3895 int err;
3896 char *dir;
3897
3898 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3899 return NULL;
3900 CHECK_ENV_NOT_CLOSED(self);
3901
3902 MYDB_BEGIN_ALLOW_THREADS;
3903 err = self->db_env->set_data_dir(self->db_env, dir);
3904 MYDB_END_ALLOW_THREADS;
3905 RETURN_IF_ERR();
3906 RETURN_NONE();
3907}
3908
3909
3910static PyObject*
3911DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3912{
3913 int err, lg_bsize;
3914
3915 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3916 return NULL;
3917 CHECK_ENV_NOT_CLOSED(self);
3918
3919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3921 MYDB_END_ALLOW_THREADS;
3922 RETURN_IF_ERR();
3923 RETURN_NONE();
3924}
3925
3926
3927static PyObject*
3928DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3929{
3930 int err;
3931 char *dir;
3932
3933 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3934 return NULL;
3935 CHECK_ENV_NOT_CLOSED(self);
3936
3937 MYDB_BEGIN_ALLOW_THREADS;
3938 err = self->db_env->set_lg_dir(self->db_env, dir);
3939 MYDB_END_ALLOW_THREADS;
3940 RETURN_IF_ERR();
3941 RETURN_NONE();
3942}
3943
3944static PyObject*
3945DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3946{
3947 int err, lg_max;
3948
3949 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3950 return NULL;
3951 CHECK_ENV_NOT_CLOSED(self);
3952
3953 MYDB_BEGIN_ALLOW_THREADS;
3954 err = self->db_env->set_lg_max(self->db_env, lg_max);
3955 MYDB_END_ALLOW_THREADS;
3956 RETURN_IF_ERR();
3957 RETURN_NONE();
3958}
3959
3960
Neal Norwitz84562352005-10-20 04:30:15 +00003961#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003962static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003963DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3964{
3965 int err, lg_max;
3966
3967 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3968 return NULL;
3969 CHECK_ENV_NOT_CLOSED(self);
3970
3971 MYDB_BEGIN_ALLOW_THREADS;
3972 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3973 MYDB_END_ALLOW_THREADS;
3974 RETURN_IF_ERR();
3975 RETURN_NONE();
3976}
Neal Norwitz84562352005-10-20 04:30:15 +00003977#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00003978
3979
3980static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003981DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3982{
3983 int err, lk_detect;
3984
3985 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3986 return NULL;
3987 CHECK_ENV_NOT_CLOSED(self);
3988
3989 MYDB_BEGIN_ALLOW_THREADS;
3990 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3991 MYDB_END_ALLOW_THREADS;
3992 RETURN_IF_ERR();
3993 RETURN_NONE();
3994}
3995
3996
3997static PyObject*
3998DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3999{
4000 int err, max;
4001
4002 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4003 return NULL;
4004 CHECK_ENV_NOT_CLOSED(self);
4005
4006 MYDB_BEGIN_ALLOW_THREADS;
4007 err = self->db_env->set_lk_max(self->db_env, max);
4008 MYDB_END_ALLOW_THREADS;
4009 RETURN_IF_ERR();
4010 RETURN_NONE();
4011}
4012
4013
4014#if (DBVER >= 32)
4015
4016static PyObject*
4017DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4018{
4019 int err, max;
4020
4021 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4022 return NULL;
4023 CHECK_ENV_NOT_CLOSED(self);
4024
4025 MYDB_BEGIN_ALLOW_THREADS;
4026 err = self->db_env->set_lk_max_locks(self->db_env, max);
4027 MYDB_END_ALLOW_THREADS;
4028 RETURN_IF_ERR();
4029 RETURN_NONE();
4030}
4031
4032
4033static PyObject*
4034DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4035{
4036 int err, max;
4037
4038 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4039 return NULL;
4040 CHECK_ENV_NOT_CLOSED(self);
4041
4042 MYDB_BEGIN_ALLOW_THREADS;
4043 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4044 MYDB_END_ALLOW_THREADS;
4045 RETURN_IF_ERR();
4046 RETURN_NONE();
4047}
4048
4049
4050static PyObject*
4051DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4052{
4053 int err, max;
4054
4055 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4056 return NULL;
4057 CHECK_ENV_NOT_CLOSED(self);
4058
4059 MYDB_BEGIN_ALLOW_THREADS;
4060 err = self->db_env->set_lk_max_objects(self->db_env, max);
4061 MYDB_END_ALLOW_THREADS;
4062 RETURN_IF_ERR();
4063 RETURN_NONE();
4064}
4065
4066#endif
4067
4068
4069static PyObject*
4070DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4071{
4072 int err, mp_mmapsize;
4073
4074 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4075 return NULL;
4076 CHECK_ENV_NOT_CLOSED(self);
4077
4078 MYDB_BEGIN_ALLOW_THREADS;
4079 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4080 MYDB_END_ALLOW_THREADS;
4081 RETURN_IF_ERR();
4082 RETURN_NONE();
4083}
4084
4085
4086static PyObject*
4087DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4088{
4089 int err;
4090 char *dir;
4091
4092 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4093 return NULL;
4094 CHECK_ENV_NOT_CLOSED(self);
4095
4096 MYDB_BEGIN_ALLOW_THREADS;
4097 err = self->db_env->set_tmp_dir(self->db_env, dir);
4098 MYDB_END_ALLOW_THREADS;
4099 RETURN_IF_ERR();
4100 RETURN_NONE();
4101}
4102
4103
4104static PyObject*
4105DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4106{
4107 int flags = 0;
4108 PyObject* txnobj = NULL;
4109 DB_TXN *txn = NULL;
4110 char* kwnames[] = { "parent", "flags", NULL };
4111
4112 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4113 &txnobj, &flags))
4114 return NULL;
4115
4116 if (!checkTxnObj(txnobj, &txn))
4117 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4119
4120 return (PyObject*)newDBTxnObject(self, txn, flags);
4121}
4122
4123
4124static PyObject*
4125DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4126{
4127 int err, kbyte=0, min=0, flags=0;
4128
4129 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4130 return NULL;
4131 CHECK_ENV_NOT_CLOSED(self);
4132
4133 MYDB_BEGIN_ALLOW_THREADS;
4134#if (DBVER >= 40)
4135 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4136#else
4137 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4138#endif
4139 MYDB_END_ALLOW_THREADS;
4140 RETURN_IF_ERR();
4141 RETURN_NONE();
4142}
4143
4144
4145static PyObject*
4146DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4147{
4148 int err, max;
4149
4150 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4151 return NULL;
4152 CHECK_ENV_NOT_CLOSED(self);
4153
4154 MYDB_BEGIN_ALLOW_THREADS;
4155 err = self->db_env->set_tx_max(self->db_env, max);
4156 MYDB_END_ALLOW_THREADS;
4157 RETURN_IF_ERR();
4158 RETURN_NONE();
4159}
4160
4161
4162static PyObject*
4163DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4164{
4165 int err, atype, flags=0;
4166 int aborted = 0;
4167
4168 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4169 return NULL;
4170 CHECK_ENV_NOT_CLOSED(self);
4171
4172 MYDB_BEGIN_ALLOW_THREADS;
4173#if (DBVER >= 40)
4174 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4175#else
4176 err = lock_detect(self->db_env, flags, atype, &aborted);
4177#endif
4178 MYDB_END_ALLOW_THREADS;
4179 RETURN_IF_ERR();
4180 return PyInt_FromLong(aborted);
4181}
4182
4183
4184static PyObject*
4185DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4186{
4187 int flags=0;
4188 int locker, lock_mode;
4189 DBT obj;
4190 PyObject* objobj;
4191
4192 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4193 return NULL;
4194
4195
4196 if (!make_dbt(objobj, &obj))
4197 return NULL;
4198
4199 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4200}
4201
4202
4203static PyObject*
4204DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4205{
4206 int err;
4207 u_int32_t theID;
4208
4209 if (!PyArg_ParseTuple(args, ":lock_id"))
4210 return NULL;
4211
4212 CHECK_ENV_NOT_CLOSED(self);
4213 MYDB_BEGIN_ALLOW_THREADS;
4214#if (DBVER >= 40)
4215 err = self->db_env->lock_id(self->db_env, &theID);
4216#else
4217 err = lock_id(self->db_env, &theID);
4218#endif
4219 MYDB_END_ALLOW_THREADS;
4220 RETURN_IF_ERR();
4221
4222 return PyInt_FromLong((long)theID);
4223}
4224
4225
4226static PyObject*
4227DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4228{
4229 int err;
4230 DBLockObject* dblockobj;
4231
4232 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4233 return NULL;
4234
4235 CHECK_ENV_NOT_CLOSED(self);
4236 MYDB_BEGIN_ALLOW_THREADS;
4237#if (DBVER >= 40)
4238 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4239#else
4240 err = lock_put(self->db_env, &dblockobj->lock);
4241#endif
4242 MYDB_END_ALLOW_THREADS;
4243 RETURN_IF_ERR();
4244 RETURN_NONE();
4245}
4246
4247
4248static PyObject*
4249DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4250{
4251 int err;
4252 DB_LOCK_STAT* sp;
4253 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004254 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004255
4256 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4259
4260 MYDB_BEGIN_ALLOW_THREADS;
4261#if (DBVER >= 40)
4262 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4263#else
4264#if (DBVER >= 33)
4265 err = lock_stat(self->db_env, &sp);
4266#else
4267 err = lock_stat(self->db_env, &sp, NULL);
4268#endif
4269#endif
4270 MYDB_END_ALLOW_THREADS;
4271 RETURN_IF_ERR();
4272
4273 /* Turn the stat structure into a dictionary */
4274 d = PyDict_New();
4275 if (d == NULL) {
4276 free(sp);
4277 return NULL;
4278 }
4279
4280#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4281
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004282#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004283 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004284#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004285 MAKE_ENTRY(nmodes);
4286#if (DBVER >= 32)
4287 MAKE_ENTRY(maxlocks);
4288 MAKE_ENTRY(maxlockers);
4289 MAKE_ENTRY(maxobjects);
4290 MAKE_ENTRY(nlocks);
4291 MAKE_ENTRY(maxnlocks);
4292#endif
4293 MAKE_ENTRY(nlockers);
4294 MAKE_ENTRY(maxnlockers);
4295#if (DBVER >= 32)
4296 MAKE_ENTRY(nobjects);
4297 MAKE_ENTRY(maxnobjects);
4298#endif
4299 MAKE_ENTRY(nrequests);
4300 MAKE_ENTRY(nreleases);
4301 MAKE_ENTRY(nnowaits);
4302 MAKE_ENTRY(nconflicts);
4303 MAKE_ENTRY(ndeadlocks);
4304 MAKE_ENTRY(regsize);
4305 MAKE_ENTRY(region_wait);
4306 MAKE_ENTRY(region_nowait);
4307
4308#undef MAKE_ENTRY
4309 free(sp);
4310 return d;
4311}
4312
4313
4314static PyObject*
4315DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4316{
4317 int flags=0;
4318 int err;
4319 char **log_list_start, **log_list;
4320 PyObject* list;
4321 PyObject* item = NULL;
4322
4323 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4324 return NULL;
4325
4326 CHECK_ENV_NOT_CLOSED(self);
4327 MYDB_BEGIN_ALLOW_THREADS;
4328#if (DBVER >= 40)
4329 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4330#elif (DBVER == 33)
4331 err = log_archive(self->db_env, &log_list, flags);
4332#else
4333 err = log_archive(self->db_env, &log_list, flags, NULL);
4334#endif
4335 MYDB_END_ALLOW_THREADS;
4336 RETURN_IF_ERR();
4337
4338 list = PyList_New(0);
4339 if (list == NULL) {
4340 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4341 return NULL;
4342 }
4343
4344 if (log_list) {
4345 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4346 item = PyString_FromString (*log_list);
4347 if (item == NULL) {
4348 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004349 PyErr_SetString(PyExc_MemoryError,
4350 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004351 list = NULL;
4352 break;
4353 }
4354 PyList_Append(list, item);
4355 Py_DECREF(item);
4356 }
4357 free(log_list_start);
4358 }
4359 return list;
4360}
4361
4362
4363static PyObject*
4364DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4365{
4366 int err;
4367 DB_TXN_STAT* sp;
4368 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004369 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004370
4371 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4372 return NULL;
4373 CHECK_ENV_NOT_CLOSED(self);
4374
4375 MYDB_BEGIN_ALLOW_THREADS;
4376#if (DBVER >= 40)
4377 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4378#elif (DBVER == 33)
4379 err = txn_stat(self->db_env, &sp);
4380#else
4381 err = txn_stat(self->db_env, &sp, NULL);
4382#endif
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385
4386 /* Turn the stat structure into a dictionary */
4387 d = PyDict_New();
4388 if (d == NULL) {
4389 free(sp);
4390 return NULL;
4391 }
4392
4393#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4394
4395 MAKE_ENTRY(time_ckp);
4396 MAKE_ENTRY(last_txnid);
4397 MAKE_ENTRY(maxtxns);
4398 MAKE_ENTRY(nactive);
4399 MAKE_ENTRY(maxnactive);
4400 MAKE_ENTRY(nbegins);
4401 MAKE_ENTRY(naborts);
4402 MAKE_ENTRY(ncommits);
4403 MAKE_ENTRY(regsize);
4404 MAKE_ENTRY(region_wait);
4405 MAKE_ENTRY(region_nowait);
4406
4407#undef MAKE_ENTRY
4408 free(sp);
4409 return d;
4410}
4411
4412
4413static PyObject*
4414DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4415{
4416 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004417 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004418
4419 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4420 return NULL;
4421 CHECK_ENV_NOT_CLOSED(self);
4422
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004423 if (self->moduleFlags.getReturnsNone)
4424 ++oldValue;
4425 if (self->moduleFlags.cursorSetReturnsNone)
4426 ++oldValue;
4427 self->moduleFlags.getReturnsNone = (flags >= 1);
4428 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004429 return PyInt_FromLong(oldValue);
4430}
4431
4432
4433/* --------------------------------------------------------------------- */
4434/* DBTxn methods */
4435
4436
4437static PyObject*
4438DBTxn_commit(DBTxnObject* self, PyObject* args)
4439{
4440 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004441 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004442
4443 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4444 return NULL;
4445
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004446 if (!self->txn) {
4447 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4448 "DBTxn must not be used after txn_commit or txn_abort"));
4449 return NULL;
4450 }
4451 txn = self->txn;
4452 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004453 MYDB_BEGIN_ALLOW_THREADS;
4454#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004455 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004456#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004457 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004458#endif
4459 MYDB_END_ALLOW_THREADS;
4460 RETURN_IF_ERR();
4461 RETURN_NONE();
4462}
4463
4464static PyObject*
4465DBTxn_prepare(DBTxnObject* self, PyObject* args)
4466{
4467#if (DBVER >= 33)
4468 int err;
4469 char* gid=NULL;
4470 int gid_size=0;
4471
4472 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4473 return NULL;
4474
4475 if (gid_size != DB_XIDDATASIZE) {
4476 PyErr_SetString(PyExc_TypeError,
4477 "gid must be DB_XIDDATASIZE bytes long");
4478 return NULL;
4479 }
4480
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004481 if (!self->txn) {
4482 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4483 "DBTxn must not be used after txn_commit or txn_abort"));
4484 return NULL;
4485 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004486 MYDB_BEGIN_ALLOW_THREADS;
4487#if (DBVER >= 40)
4488 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4489#else
4490 err = txn_prepare(self->txn, (u_int8_t*)gid);
4491#endif
4492 MYDB_END_ALLOW_THREADS;
4493 RETURN_IF_ERR();
4494 RETURN_NONE();
4495#else
4496 int err;
4497
4498 if (!PyArg_ParseTuple(args, ":prepare"))
4499 return NULL;
4500
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004501 if (!self->txn) {
4502 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4503 "DBTxn must not be used after txn_commit or txn_abort"));
4504 return NULL;
4505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004506 MYDB_BEGIN_ALLOW_THREADS;
4507 err = txn_prepare(self->txn);
4508 MYDB_END_ALLOW_THREADS;
4509 RETURN_IF_ERR();
4510 RETURN_NONE();
4511#endif
4512}
4513
4514
4515static PyObject*
4516DBTxn_abort(DBTxnObject* self, PyObject* args)
4517{
4518 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004519 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004520
4521 if (!PyArg_ParseTuple(args, ":abort"))
4522 return NULL;
4523
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004524 if (!self->txn) {
4525 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4526 "DBTxn must not be used after txn_commit or txn_abort"));
4527 return NULL;
4528 }
4529 txn = self->txn;
4530 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004531 MYDB_BEGIN_ALLOW_THREADS;
4532#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004533 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004534#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004535 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004536#endif
4537 MYDB_END_ALLOW_THREADS;
4538 RETURN_IF_ERR();
4539 RETURN_NONE();
4540}
4541
4542
4543static PyObject*
4544DBTxn_id(DBTxnObject* self, PyObject* args)
4545{
4546 int id;
4547
4548 if (!PyArg_ParseTuple(args, ":id"))
4549 return NULL;
4550
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004551 if (!self->txn) {
4552 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4553 "DBTxn must not be used after txn_commit or txn_abort"));
4554 return NULL;
4555 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004556 MYDB_BEGIN_ALLOW_THREADS;
4557#if (DBVER >= 40)
4558 id = self->txn->id(self->txn);
4559#else
4560 id = txn_id(self->txn);
4561#endif
4562 MYDB_END_ALLOW_THREADS;
4563 return PyInt_FromLong(id);
4564}
4565
4566/* --------------------------------------------------------------------- */
4567/* Method definition tables and type objects */
4568
4569static PyMethodDef DB_methods[] = {
4570 {"append", (PyCFunction)DB_append, METH_VARARGS},
4571#if (DBVER >= 33)
4572 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4573#endif
4574 {"close", (PyCFunction)DB_close, METH_VARARGS},
4575#if (DBVER >= 32)
4576 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4577 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4578#endif
4579 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4580 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4581 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4582 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004583#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004584 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004585#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004586 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4587 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4588 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4589 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4590 {"join", (PyCFunction)DB_join, METH_VARARGS},
4591 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4592 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4593 {"items", (PyCFunction)DB_items, METH_VARARGS},
4594 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4595 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4596 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4597 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4598 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4599 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004600#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004601 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004602#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004603 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004604#if (DBVER >= 41)
4605 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4606#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4608 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4609 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4610 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4611 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4612 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4613 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4614 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4615 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4616#if (DBVER >= 32)
4617 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4618#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004619 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004620 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4621#if (DBVER >= 33)
4622 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4623#endif
4624 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4625 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4626 {"values", (PyCFunction)DB_values, METH_VARARGS},
4627 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4628 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4629 {NULL, NULL} /* sentinel */
4630};
4631
4632
4633static PyMappingMethods DB_mapping = {
4634 (inquiry)DB_length, /*mp_length*/
4635 (binaryfunc)DB_subscript, /*mp_subscript*/
4636 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4637};
4638
4639
4640static PyMethodDef DBCursor_methods[] = {
4641 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4642 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4643 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4644 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4645 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4646 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4647 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004648#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004649 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004651 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4652 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4653 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4654 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4655 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4656 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4657 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4658 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004659 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004660 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4662 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4663 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4664 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4665 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4666 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4667 {NULL, NULL} /* sentinel */
4668};
4669
4670
4671static PyMethodDef DBEnv_methods[] = {
4672 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4673 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4674 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004675#if (DBVER >= 41)
4676 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4677 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4678 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4679#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004680#if (DBVER >= 40)
4681 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4682#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004683 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4685 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4686#if (DBVER >= 32)
4687 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4688#endif
4689 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4690 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4691 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004692#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00004693 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004694#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004695 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4696 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4697#if (DBVER >= 32)
4698 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4699 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4700 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4701#endif
4702 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4703 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4704 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4705 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4706 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4707 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4708 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4709 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4710 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4711 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4712 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4713 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4714 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4715 {NULL, NULL} /* sentinel */
4716};
4717
4718
4719static PyMethodDef DBTxn_methods[] = {
4720 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4721 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4722 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4723 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4724 {NULL, NULL} /* sentinel */
4725};
4726
4727
4728static PyObject*
4729DB_getattr(DBObject* self, char *name)
4730{
4731 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4732}
4733
4734
4735static PyObject*
4736DBEnv_getattr(DBEnvObject* self, char *name)
4737{
4738 if (!strcmp(name, "db_home")) {
4739 CHECK_ENV_NOT_CLOSED(self);
4740 if (self->db_env->db_home == NULL) {
4741 RETURN_NONE();
4742 }
4743 return PyString_FromString(self->db_env->db_home);
4744 }
4745
4746 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4747}
4748
4749
4750static PyObject*
4751DBCursor_getattr(DBCursorObject* self, char *name)
4752{
4753 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4754}
4755
4756static PyObject*
4757DBTxn_getattr(DBTxnObject* self, char *name)
4758{
4759 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4760}
4761
4762static PyObject*
4763DBLock_getattr(DBLockObject* self, char *name)
4764{
4765 return NULL;
4766}
4767
4768statichere PyTypeObject DB_Type = {
4769 PyObject_HEAD_INIT(NULL)
4770 0, /*ob_size*/
4771 "DB", /*tp_name*/
4772 sizeof(DBObject), /*tp_basicsize*/
4773 0, /*tp_itemsize*/
4774 /* methods */
4775 (destructor)DB_dealloc, /*tp_dealloc*/
4776 0, /*tp_print*/
4777 (getattrfunc)DB_getattr, /*tp_getattr*/
4778 0, /*tp_setattr*/
4779 0, /*tp_compare*/
4780 0, /*tp_repr*/
4781 0, /*tp_as_number*/
4782 0, /*tp_as_sequence*/
4783 &DB_mapping,/*tp_as_mapping*/
4784 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004785#ifdef HAVE_WEAKREF
4786 0, /* tp_call */
4787 0, /* tp_str */
4788 0, /* tp_getattro */
4789 0, /* tp_setattro */
4790 0, /* tp_as_buffer */
4791 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4792 0, /* tp_doc */
4793 0, /* tp_traverse */
4794 0, /* tp_clear */
4795 0, /* tp_richcompare */
4796 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4797#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004798};
4799
4800
4801statichere PyTypeObject DBCursor_Type = {
4802 PyObject_HEAD_INIT(NULL)
4803 0, /*ob_size*/
4804 "DBCursor", /*tp_name*/
4805 sizeof(DBCursorObject), /*tp_basicsize*/
4806 0, /*tp_itemsize*/
4807 /* methods */
4808 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4809 0, /*tp_print*/
4810 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4811 0, /*tp_setattr*/
4812 0, /*tp_compare*/
4813 0, /*tp_repr*/
4814 0, /*tp_as_number*/
4815 0, /*tp_as_sequence*/
4816 0, /*tp_as_mapping*/
4817 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004818#ifdef HAVE_WEAKREF
4819 0, /* tp_call */
4820 0, /* tp_str */
4821 0, /* tp_getattro */
4822 0, /* tp_setattro */
4823 0, /* tp_as_buffer */
4824 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4825 0, /* tp_doc */
4826 0, /* tp_traverse */
4827 0, /* tp_clear */
4828 0, /* tp_richcompare */
4829 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4830#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004831};
4832
4833
4834statichere PyTypeObject DBEnv_Type = {
4835 PyObject_HEAD_INIT(NULL)
4836 0, /*ob_size*/
4837 "DBEnv", /*tp_name*/
4838 sizeof(DBEnvObject), /*tp_basicsize*/
4839 0, /*tp_itemsize*/
4840 /* methods */
4841 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4842 0, /*tp_print*/
4843 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4844 0, /*tp_setattr*/
4845 0, /*tp_compare*/
4846 0, /*tp_repr*/
4847 0, /*tp_as_number*/
4848 0, /*tp_as_sequence*/
4849 0, /*tp_as_mapping*/
4850 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004851#ifdef HAVE_WEAKREF
4852 0, /* tp_call */
4853 0, /* tp_str */
4854 0, /* tp_getattro */
4855 0, /* tp_setattro */
4856 0, /* tp_as_buffer */
4857 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4858 0, /* tp_doc */
4859 0, /* tp_traverse */
4860 0, /* tp_clear */
4861 0, /* tp_richcompare */
4862 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4863#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004864};
4865
4866statichere PyTypeObject DBTxn_Type = {
4867 PyObject_HEAD_INIT(NULL)
4868 0, /*ob_size*/
4869 "DBTxn", /*tp_name*/
4870 sizeof(DBTxnObject), /*tp_basicsize*/
4871 0, /*tp_itemsize*/
4872 /* methods */
4873 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4874 0, /*tp_print*/
4875 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4876 0, /*tp_setattr*/
4877 0, /*tp_compare*/
4878 0, /*tp_repr*/
4879 0, /*tp_as_number*/
4880 0, /*tp_as_sequence*/
4881 0, /*tp_as_mapping*/
4882 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004883#ifdef HAVE_WEAKREF
4884 0, /* tp_call */
4885 0, /* tp_str */
4886 0, /* tp_getattro */
4887 0, /* tp_setattro */
4888 0, /* tp_as_buffer */
4889 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4890 0, /* tp_doc */
4891 0, /* tp_traverse */
4892 0, /* tp_clear */
4893 0, /* tp_richcompare */
4894 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4895#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004896};
4897
4898
4899statichere PyTypeObject DBLock_Type = {
4900 PyObject_HEAD_INIT(NULL)
4901 0, /*ob_size*/
4902 "DBLock", /*tp_name*/
4903 sizeof(DBLockObject), /*tp_basicsize*/
4904 0, /*tp_itemsize*/
4905 /* methods */
4906 (destructor)DBLock_dealloc, /*tp_dealloc*/
4907 0, /*tp_print*/
4908 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4909 0, /*tp_setattr*/
4910 0, /*tp_compare*/
4911 0, /*tp_repr*/
4912 0, /*tp_as_number*/
4913 0, /*tp_as_sequence*/
4914 0, /*tp_as_mapping*/
4915 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004916#ifdef HAVE_WEAKREF
4917 0, /* tp_call */
4918 0, /* tp_str */
4919 0, /* tp_getattro */
4920 0, /* tp_setattro */
4921 0, /* tp_as_buffer */
4922 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4923 0, /* tp_doc */
4924 0, /* tp_traverse */
4925 0, /* tp_clear */
4926 0, /* tp_richcompare */
4927 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4928#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004929};
4930
4931
4932/* --------------------------------------------------------------------- */
4933/* Module-level functions */
4934
4935static PyObject*
4936DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4937{
4938 PyObject* dbenvobj = NULL;
4939 int flags = 0;
4940 char* kwnames[] = { "dbEnv", "flags", NULL};
4941
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4943 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004944 return NULL;
4945 if (dbenvobj == Py_None)
4946 dbenvobj = NULL;
4947 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4948 makeTypeError("DBEnv", dbenvobj);
4949 return NULL;
4950 }
4951
4952 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4953}
4954
4955
4956static PyObject*
4957DBEnv_construct(PyObject* self, PyObject* args)
4958{
4959 int flags = 0;
4960 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4961 return (PyObject* )newDBEnvObject(flags);
4962}
4963
4964
4965static char bsddb_version_doc[] =
4966"Returns a tuple of major, minor, and patch release numbers of the\n\
4967underlying DB library.";
4968
4969static PyObject*
4970bsddb_version(PyObject* self, PyObject* args)
4971{
4972 int major, minor, patch;
4973
4974 if (!PyArg_ParseTuple(args, ":version"))
4975 return NULL;
4976 db_version(&major, &minor, &patch);
4977 return Py_BuildValue("(iii)", major, minor, patch);
4978}
4979
4980
4981/* List of functions defined in the module */
4982
4983static PyMethodDef bsddb_methods[] = {
4984 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4985 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4986 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4987 {NULL, NULL} /* sentinel */
4988};
4989
4990
4991/* --------------------------------------------------------------------- */
4992/* Module initialization */
4993
4994
4995/* Convenience routine to export an integer value.
4996 * Errors are silently ignored, for better or for worse...
4997 */
4998#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4999
Gregory P. Smith41631e82003-09-21 00:08:14 +00005000#define MODULE_NAME_MAX_LEN 11
5001static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005002
5003DL_EXPORT(void) init_bsddb(void)
5004{
5005 PyObject* m;
5006 PyObject* d;
5007 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5008 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5009 PyObject* cvsid_s = PyString_FromString( rcs_id );
5010
5011 /* Initialize the type of the new type objects here; doing it here
5012 is required for portability to Windows without requiring C++. */
5013 DB_Type.ob_type = &PyType_Type;
5014 DBCursor_Type.ob_type = &PyType_Type;
5015 DBEnv_Type.ob_type = &PyType_Type;
5016 DBTxn_Type.ob_type = &PyType_Type;
5017 DBLock_Type.ob_type = &PyType_Type;
5018
5019
Mark Hammonda69d4092003-04-22 23:13:27 +00005020#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005021 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005022 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005023#endif
5024
5025 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005026 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005027
5028 /* Add some symbolic constants to the module */
5029 d = PyModule_GetDict(m);
5030 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5031 PyDict_SetItemString(d, "cvsid", cvsid_s);
5032 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5033 Py_DECREF(pybsddb_version_s);
5034 pybsddb_version_s = NULL;
5035 Py_DECREF(cvsid_s);
5036 cvsid_s = NULL;
5037 Py_DECREF(db_version_s);
5038 db_version_s = NULL;
5039
5040 ADD_INT(d, DB_VERSION_MAJOR);
5041 ADD_INT(d, DB_VERSION_MINOR);
5042 ADD_INT(d, DB_VERSION_PATCH);
5043
5044 ADD_INT(d, DB_MAX_PAGES);
5045 ADD_INT(d, DB_MAX_RECORDS);
5046
Gregory P. Smith41631e82003-09-21 00:08:14 +00005047#if (DBVER >= 42)
5048 ADD_INT(d, DB_RPCCLIENT);
5049#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005050 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005051 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5052 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5053#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005054 ADD_INT(d, DB_XA_CREATE);
5055
5056 ADD_INT(d, DB_CREATE);
5057 ADD_INT(d, DB_NOMMAP);
5058 ADD_INT(d, DB_THREAD);
5059
5060 ADD_INT(d, DB_FORCE);
5061 ADD_INT(d, DB_INIT_CDB);
5062 ADD_INT(d, DB_INIT_LOCK);
5063 ADD_INT(d, DB_INIT_LOG);
5064 ADD_INT(d, DB_INIT_MPOOL);
5065 ADD_INT(d, DB_INIT_TXN);
5066#if (DBVER >= 32)
5067 ADD_INT(d, DB_JOINENV);
5068#endif
5069
5070 ADD_INT(d, DB_RECOVER);
5071 ADD_INT(d, DB_RECOVER_FATAL);
5072 ADD_INT(d, DB_TXN_NOSYNC);
5073 ADD_INT(d, DB_USE_ENVIRON);
5074 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5075
5076 ADD_INT(d, DB_LOCKDOWN);
5077 ADD_INT(d, DB_PRIVATE);
5078 ADD_INT(d, DB_SYSTEM_MEM);
5079
5080 ADD_INT(d, DB_TXN_SYNC);
5081 ADD_INT(d, DB_TXN_NOWAIT);
5082
5083 ADD_INT(d, DB_EXCL);
5084 ADD_INT(d, DB_FCNTL_LOCKING);
5085 ADD_INT(d, DB_ODDFILESIZE);
5086 ADD_INT(d, DB_RDWRMASTER);
5087 ADD_INT(d, DB_RDONLY);
5088 ADD_INT(d, DB_TRUNCATE);
5089#if (DBVER >= 32)
5090 ADD_INT(d, DB_EXTENT);
5091 ADD_INT(d, DB_CDB_ALLDB);
5092 ADD_INT(d, DB_VERIFY);
5093#endif
5094 ADD_INT(d, DB_UPGRADE);
5095
5096 ADD_INT(d, DB_AGGRESSIVE);
5097 ADD_INT(d, DB_NOORDERCHK);
5098 ADD_INT(d, DB_ORDERCHKONLY);
5099 ADD_INT(d, DB_PR_PAGE);
5100#if ! (DBVER >= 33)
5101 ADD_INT(d, DB_VRFY_FLAGMASK);
5102 ADD_INT(d, DB_PR_HEADERS);
5103#endif
5104 ADD_INT(d, DB_PR_RECOVERYTEST);
5105 ADD_INT(d, DB_SALVAGE);
5106
5107 ADD_INT(d, DB_LOCK_NORUN);
5108 ADD_INT(d, DB_LOCK_DEFAULT);
5109 ADD_INT(d, DB_LOCK_OLDEST);
5110 ADD_INT(d, DB_LOCK_RANDOM);
5111 ADD_INT(d, DB_LOCK_YOUNGEST);
5112#if (DBVER >= 33)
5113 ADD_INT(d, DB_LOCK_MAXLOCKS);
5114 ADD_INT(d, DB_LOCK_MINLOCKS);
5115 ADD_INT(d, DB_LOCK_MINWRITE);
5116#endif
5117
5118
5119#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005120 /* docs say to use zero instead */
5121 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005122#else
5123 ADD_INT(d, DB_LOCK_CONFLICT);
5124#endif
5125
5126 ADD_INT(d, DB_LOCK_DUMP);
5127 ADD_INT(d, DB_LOCK_GET);
5128 ADD_INT(d, DB_LOCK_INHERIT);
5129 ADD_INT(d, DB_LOCK_PUT);
5130 ADD_INT(d, DB_LOCK_PUT_ALL);
5131 ADD_INT(d, DB_LOCK_PUT_OBJ);
5132
5133 ADD_INT(d, DB_LOCK_NG);
5134 ADD_INT(d, DB_LOCK_READ);
5135 ADD_INT(d, DB_LOCK_WRITE);
5136 ADD_INT(d, DB_LOCK_NOWAIT);
5137#if (DBVER >= 32)
5138 ADD_INT(d, DB_LOCK_WAIT);
5139#endif
5140 ADD_INT(d, DB_LOCK_IWRITE);
5141 ADD_INT(d, DB_LOCK_IREAD);
5142 ADD_INT(d, DB_LOCK_IWR);
5143#if (DBVER >= 33)
5144 ADD_INT(d, DB_LOCK_DIRTY);
5145 ADD_INT(d, DB_LOCK_WWRITE);
5146#endif
5147
5148 ADD_INT(d, DB_LOCK_RECORD);
5149 ADD_INT(d, DB_LOCK_UPGRADE);
5150#if (DBVER >= 32)
5151 ADD_INT(d, DB_LOCK_SWITCH);
5152#endif
5153#if (DBVER >= 33)
5154 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5155#endif
5156
5157 ADD_INT(d, DB_LOCK_NOWAIT);
5158 ADD_INT(d, DB_LOCK_RECORD);
5159 ADD_INT(d, DB_LOCK_UPGRADE);
5160
5161#if (DBVER >= 33)
5162 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005163#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005164 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005166 ADD_INT(d, DB_LSTAT_FREE);
5167 ADD_INT(d, DB_LSTAT_HELD);
5168#if (DBVER == 33)
5169 ADD_INT(d, DB_LSTAT_NOGRANT);
5170#endif
5171 ADD_INT(d, DB_LSTAT_PENDING);
5172 ADD_INT(d, DB_LSTAT_WAITING);
5173#endif
5174
5175 ADD_INT(d, DB_ARCH_ABS);
5176 ADD_INT(d, DB_ARCH_DATA);
5177 ADD_INT(d, DB_ARCH_LOG);
5178
5179 ADD_INT(d, DB_BTREE);
5180 ADD_INT(d, DB_HASH);
5181 ADD_INT(d, DB_RECNO);
5182 ADD_INT(d, DB_QUEUE);
5183 ADD_INT(d, DB_UNKNOWN);
5184
5185 ADD_INT(d, DB_DUP);
5186 ADD_INT(d, DB_DUPSORT);
5187 ADD_INT(d, DB_RECNUM);
5188 ADD_INT(d, DB_RENUMBER);
5189 ADD_INT(d, DB_REVSPLITOFF);
5190 ADD_INT(d, DB_SNAPSHOT);
5191
5192 ADD_INT(d, DB_JOIN_NOSORT);
5193
5194 ADD_INT(d, DB_AFTER);
5195 ADD_INT(d, DB_APPEND);
5196 ADD_INT(d, DB_BEFORE);
5197 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005198#if (DBVER >= 41)
5199 _addIntToDict(d, "DB_CHECKPOINT", 0);
5200#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005201 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005202 ADD_INT(d, DB_CURLSN);
5203#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005204#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005205 ADD_INT(d, DB_COMMIT);
5206#endif
5207 ADD_INT(d, DB_CONSUME);
5208#if (DBVER >= 32)
5209 ADD_INT(d, DB_CONSUME_WAIT);
5210#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005211 ADD_INT(d, DB_CURRENT);
5212#if (DBVER >= 33)
5213 ADD_INT(d, DB_FAST_STAT);
5214#endif
5215 ADD_INT(d, DB_FIRST);
5216 ADD_INT(d, DB_FLUSH);
5217 ADD_INT(d, DB_GET_BOTH);
5218 ADD_INT(d, DB_GET_RECNO);
5219 ADD_INT(d, DB_JOIN_ITEM);
5220 ADD_INT(d, DB_KEYFIRST);
5221 ADD_INT(d, DB_KEYLAST);
5222 ADD_INT(d, DB_LAST);
5223 ADD_INT(d, DB_NEXT);
5224 ADD_INT(d, DB_NEXT_DUP);
5225 ADD_INT(d, DB_NEXT_NODUP);
5226 ADD_INT(d, DB_NODUPDATA);
5227 ADD_INT(d, DB_NOOVERWRITE);
5228 ADD_INT(d, DB_NOSYNC);
5229 ADD_INT(d, DB_POSITION);
5230 ADD_INT(d, DB_PREV);
5231 ADD_INT(d, DB_PREV_NODUP);
5232 ADD_INT(d, DB_RECORDCOUNT);
5233 ADD_INT(d, DB_SET);
5234 ADD_INT(d, DB_SET_RANGE);
5235 ADD_INT(d, DB_SET_RECNO);
5236 ADD_INT(d, DB_WRITECURSOR);
5237
5238 ADD_INT(d, DB_OPFLAGS_MASK);
5239 ADD_INT(d, DB_RMW);
5240#if (DBVER >= 33)
5241 ADD_INT(d, DB_DIRTY_READ);
5242 ADD_INT(d, DB_MULTIPLE);
5243 ADD_INT(d, DB_MULTIPLE_KEY);
5244#endif
5245
5246#if (DBVER >= 33)
5247 ADD_INT(d, DB_DONOTINDEX);
5248#endif
5249
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005250#if (DBVER >= 41)
5251 _addIntToDict(d, "DB_INCOMPLETE", 0);
5252#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005253 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005254#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005255 ADD_INT(d, DB_KEYEMPTY);
5256 ADD_INT(d, DB_KEYEXIST);
5257 ADD_INT(d, DB_LOCK_DEADLOCK);
5258 ADD_INT(d, DB_LOCK_NOTGRANTED);
5259 ADD_INT(d, DB_NOSERVER);
5260 ADD_INT(d, DB_NOSERVER_HOME);
5261 ADD_INT(d, DB_NOSERVER_ID);
5262 ADD_INT(d, DB_NOTFOUND);
5263 ADD_INT(d, DB_OLD_VERSION);
5264 ADD_INT(d, DB_RUNRECOVERY);
5265 ADD_INT(d, DB_VERIFY_BAD);
5266#if (DBVER >= 33)
5267 ADD_INT(d, DB_PAGE_NOTFOUND);
5268 ADD_INT(d, DB_SECONDARY_BAD);
5269#endif
5270#if (DBVER >= 40)
5271 ADD_INT(d, DB_STAT_CLEAR);
5272 ADD_INT(d, DB_REGION_INIT);
5273 ADD_INT(d, DB_NOLOCKING);
5274 ADD_INT(d, DB_YIELDCPU);
5275 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5276 ADD_INT(d, DB_NOPANIC);
5277#endif
5278
Gregory P. Smith41631e82003-09-21 00:08:14 +00005279#if (DBVER >= 42)
5280 ADD_INT(d, DB_TIME_NOTGRANTED);
5281 ADD_INT(d, DB_TXN_NOT_DURABLE);
5282 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5283 ADD_INT(d, DB_LOG_AUTOREMOVE);
5284 ADD_INT(d, DB_DIRECT_LOG);
5285 ADD_INT(d, DB_DIRECT_DB);
5286 ADD_INT(d, DB_INIT_REP);
5287 ADD_INT(d, DB_ENCRYPT);
5288 ADD_INT(d, DB_CHKSUM);
5289#endif
5290
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005291#if (DBVER >= 43)
5292 ADD_INT(d, DB_LOG_INMEMORY);
5293 ADD_INT(d, DB_BUFFER_SMALL);
5294#endif
5295
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005296#if (DBVER >= 41)
5297 ADD_INT(d, DB_ENCRYPT_AES);
5298 ADD_INT(d, DB_AUTO_COMMIT);
5299#else
5300 /* allow berkeleydb 4.1 aware apps to run on older versions */
5301 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5302#endif
5303
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005304 ADD_INT(d, EINVAL);
5305 ADD_INT(d, EACCES);
5306 ADD_INT(d, ENOSPC);
5307 ADD_INT(d, ENOMEM);
5308 ADD_INT(d, EAGAIN);
5309 ADD_INT(d, EBUSY);
5310 ADD_INT(d, EEXIST);
5311 ADD_INT(d, ENOENT);
5312 ADD_INT(d, EPERM);
5313
Barry Warsaw1baa9822003-03-31 19:51:29 +00005314#if (DBVER >= 40)
5315 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5316 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5317#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005318
5319 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005320 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005321 PyDict_SetItemString(d, "DBError", DBError);
5322
Gregory P. Smithe9477062005-06-04 06:46:59 +00005323 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5324 * from both DBError and KeyError, since the API only supports
5325 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005326 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005327 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5328 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005329 Py_file_input, d, d);
5330 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005331 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005332 PyDict_DelItemString(d, "KeyError");
5333
5334
5335 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005336#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005337 PyDict_SetItemString(d, #name, name)
5338
5339#if !INCOMPLETE_IS_WARNING
5340 MAKE_EX(DBIncompleteError);
5341#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005342 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005343 MAKE_EX(DBKeyEmptyError);
5344 MAKE_EX(DBKeyExistError);
5345 MAKE_EX(DBLockDeadlockError);
5346 MAKE_EX(DBLockNotGrantedError);
5347 MAKE_EX(DBOldVersionError);
5348 MAKE_EX(DBRunRecoveryError);
5349 MAKE_EX(DBVerifyBadError);
5350 MAKE_EX(DBNoServerError);
5351 MAKE_EX(DBNoServerHomeError);
5352 MAKE_EX(DBNoServerIDError);
5353#if (DBVER >= 33)
5354 MAKE_EX(DBPageNotFoundError);
5355 MAKE_EX(DBSecondaryBadError);
5356#endif
5357
5358 MAKE_EX(DBInvalidArgError);
5359 MAKE_EX(DBAccessError);
5360 MAKE_EX(DBNoSpaceError);
5361 MAKE_EX(DBNoMemoryError);
5362 MAKE_EX(DBAgainError);
5363 MAKE_EX(DBBusyError);
5364 MAKE_EX(DBFileExistsError);
5365 MAKE_EX(DBNoSuchFileError);
5366 MAKE_EX(DBPermissionsError);
5367
5368#undef MAKE_EX
5369
5370 /* Check for errors */
5371 if (PyErr_Occurred()) {
5372 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005373 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005374 }
5375}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005376
5377/* allow this module to be named _pybsddb so that it can be installed
5378 * and imported on top of python >= 2.3 that includes its own older
5379 * copy of the library named _bsddb without importing the old version. */
5380DL_EXPORT(void) init_pybsddb(void)
5381{
5382 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5383 init_bsddb();
5384}