blob: 6b4f84b926522182de60d2a8257d27c7ffa60335 [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
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001972static int
1973_default_cmp (const DBT *leftKey,
1974 const DBT *rightKey)
1975{
1976 int res;
1977 int lsize = leftKey->size, rsize = rightKey->size;
1978
1979 res = memcmp (leftKey->data, rightKey->data,
1980 lsize < rsize ? lsize : rsize);
1981
1982 if (res == 0) {
1983 if (lsize < rsize) {
1984 res = -1;
1985 }
1986 else if (lsize > rsize) {
1987 res = 1;
1988 }
1989 }
1990 return res;
1991}
1992
1993static int
1994_db_compareCallback (DB* db,
1995 const DBT *leftKey,
1996 const DBT *rightKey)
1997{
1998 int res = 0;
1999 PyObject *args;
2000 PyObject *result;
2001 PyObject *leftObject;
2002 PyObject *rightObject;
2003 DBObject *self = (DBObject *) db->app_private;
2004
2005 if (self == NULL || self->btCompareCallback == NULL) {
2006 MYDB_BEGIN_BLOCK_THREADS;
2007 PyErr_SetString (PyExc_TypeError,
2008 (self == 0
2009 ? "DB_bt_compare db is NULL."
2010 : "DB_bt_compare callback is NULL."));
2011 /* we're in a callback within the DB code, we can't raise */
2012 PyErr_Print ();
2013 res = _default_cmp (leftKey, rightKey);
2014 MYDB_END_BLOCK_THREADS;
2015 }
2016 else {
2017 MYDB_BEGIN_BLOCK_THREADS;
2018
2019 leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size);
2020 rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size);
2021
Gregory P. Smithac741c52005-06-06 17:31:32 +00002022 args = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002023 Py_INCREF (self);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002024 PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */
2025 PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002026
2027 result = PyEval_CallObject (self->btCompareCallback, args);
2028 if (result == 0) {
2029 /* we're in a callback within the DB code, we can't raise */
Gregory P. Smith8966d3d2005-06-16 19:01:42 +00002030 PyErr_Print ();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002031 res = _default_cmp (leftKey, rightKey);
2032 }
2033 else if (PyInt_Check (result)) {
2034 res = PyInt_AsLong (result);
2035 }
2036 else {
2037 PyErr_SetString (PyExc_TypeError,
2038 "DB_bt_compare callback MUST return an int.");
2039 /* we're in a callback within the DB code, we can't raise */
2040 PyErr_Print ();
2041 res = _default_cmp (leftKey, rightKey);
2042 }
2043
2044 Py_DECREF (args);
2045 Py_XDECREF (result);
2046
2047 MYDB_END_BLOCK_THREADS;
2048 }
2049 return res;
2050}
2051
2052static PyObject*
2053DB_set_bt_compare (DBObject* self, PyObject* args)
2054{
2055 int err;
2056 PyObject *comparator;
2057 PyObject *tuple, *emptyStr, *result;
2058
2059 if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator ))
2060 return NULL;
2061
2062 CHECK_DB_NOT_CLOSED (self);
2063
2064 if (! PyCallable_Check (comparator)) {
2065 makeTypeError ("Callable", comparator);
2066 return NULL;
2067 }
2068
2069 /*
2070 * Perform a test call of the comparator function with two empty
2071 * string objects here. verify that it returns an int (0).
2072 * err if not.
2073 */
Gregory P. Smithac741c52005-06-06 17:31:32 +00002074 tuple = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002075
2076 emptyStr = PyString_FromStringAndSize (NULL, 0);
2077 Py_INCREF(emptyStr);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002078 PyTuple_SET_ITEM (tuple, 0, emptyStr);
2079 PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080 result = PyEval_CallObject (comparator, tuple);
2081 Py_DECREF (tuple);
2082 if (result == 0 || !PyInt_Check(result)) {
2083 PyErr_SetString (PyExc_TypeError,
2084 "callback MUST return an int");
2085 return NULL;
2086 }
2087 else if (PyInt_AsLong(result) != 0) {
2088 PyErr_SetString (PyExc_TypeError,
2089 "callback failed to return 0 on two empty strings");
2090 return NULL;
2091 }
2092
2093 /* We don't accept multiple set_bt_compare operations, in order to
2094 * simplify the code. This would have no real use, as one cannot
2095 * change the function once the db is opened anyway */
2096 if (self->btCompareCallback != NULL) {
2097 PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once");
2098 return NULL;
2099 }
2100
2101 Py_INCREF (comparator);
2102 self->btCompareCallback = comparator;
2103
2104 /* This is to workaround a problem with un-initialized threads (see
2105 comment in DB_associate) */
2106#ifdef WITH_THREAD
2107 PyEval_InitThreads();
2108#endif
2109
2110 err = self->db->set_bt_compare (self->db,
2111 (comparator != NULL ?
2112 _db_compareCallback : NULL));
2113
2114 if (err) {
2115 /* restore the old state in case of error */
2116 Py_DECREF (comparator);
2117 self->btCompareCallback = NULL;
2118 }
2119
2120 RETURN_IF_ERR ();
2121 RETURN_NONE ();
2122}
2123
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002124
2125static PyObject*
2126DB_set_cachesize(DBObject* self, PyObject* args)
2127{
2128 int err;
2129 int gbytes = 0, bytes = 0, ncache = 0;
2130
2131 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2132 &gbytes,&bytes,&ncache))
2133 return NULL;
2134 CHECK_DB_NOT_CLOSED(self);
2135
2136 MYDB_BEGIN_ALLOW_THREADS;
2137 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2138 MYDB_END_ALLOW_THREADS;
2139 RETURN_IF_ERR();
2140 RETURN_NONE();
2141}
2142
2143
2144static PyObject*
2145DB_set_flags(DBObject* self, PyObject* args)
2146{
2147 int err, flags;
2148
2149 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2150 return NULL;
2151 CHECK_DB_NOT_CLOSED(self);
2152
2153 MYDB_BEGIN_ALLOW_THREADS;
2154 err = self->db->set_flags(self->db, flags);
2155 MYDB_END_ALLOW_THREADS;
2156 RETURN_IF_ERR();
2157
2158 self->setflags |= flags;
2159 RETURN_NONE();
2160}
2161
2162
2163static PyObject*
2164DB_set_h_ffactor(DBObject* self, PyObject* args)
2165{
2166 int err, ffactor;
2167
2168 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2169 return NULL;
2170 CHECK_DB_NOT_CLOSED(self);
2171
2172 MYDB_BEGIN_ALLOW_THREADS;
2173 err = self->db->set_h_ffactor(self->db, ffactor);
2174 MYDB_END_ALLOW_THREADS;
2175 RETURN_IF_ERR();
2176 RETURN_NONE();
2177}
2178
2179
2180static PyObject*
2181DB_set_h_nelem(DBObject* self, PyObject* args)
2182{
2183 int err, nelem;
2184
2185 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2186 return NULL;
2187 CHECK_DB_NOT_CLOSED(self);
2188
2189 MYDB_BEGIN_ALLOW_THREADS;
2190 err = self->db->set_h_nelem(self->db, nelem);
2191 MYDB_END_ALLOW_THREADS;
2192 RETURN_IF_ERR();
2193 RETURN_NONE();
2194}
2195
2196
2197static PyObject*
2198DB_set_lorder(DBObject* self, PyObject* args)
2199{
2200 int err, lorder;
2201
2202 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2203 return NULL;
2204 CHECK_DB_NOT_CLOSED(self);
2205
2206 MYDB_BEGIN_ALLOW_THREADS;
2207 err = self->db->set_lorder(self->db, lorder);
2208 MYDB_END_ALLOW_THREADS;
2209 RETURN_IF_ERR();
2210 RETURN_NONE();
2211}
2212
2213
2214static PyObject*
2215DB_set_pagesize(DBObject* self, PyObject* args)
2216{
2217 int err, pagesize;
2218
2219 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2220 return NULL;
2221 CHECK_DB_NOT_CLOSED(self);
2222
2223 MYDB_BEGIN_ALLOW_THREADS;
2224 err = self->db->set_pagesize(self->db, pagesize);
2225 MYDB_END_ALLOW_THREADS;
2226 RETURN_IF_ERR();
2227 RETURN_NONE();
2228}
2229
2230
2231static PyObject*
2232DB_set_re_delim(DBObject* self, PyObject* args)
2233{
2234 int err;
2235 char delim;
2236
2237 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2238 PyErr_Clear();
2239 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2240 return NULL;
2241 }
2242
2243 CHECK_DB_NOT_CLOSED(self);
2244
2245 MYDB_BEGIN_ALLOW_THREADS;
2246 err = self->db->set_re_delim(self->db, delim);
2247 MYDB_END_ALLOW_THREADS;
2248 RETURN_IF_ERR();
2249 RETURN_NONE();
2250}
2251
2252static PyObject*
2253DB_set_re_len(DBObject* self, PyObject* args)
2254{
2255 int err, len;
2256
2257 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2258 return NULL;
2259 CHECK_DB_NOT_CLOSED(self);
2260
2261 MYDB_BEGIN_ALLOW_THREADS;
2262 err = self->db->set_re_len(self->db, len);
2263 MYDB_END_ALLOW_THREADS;
2264 RETURN_IF_ERR();
2265 RETURN_NONE();
2266}
2267
2268
2269static PyObject*
2270DB_set_re_pad(DBObject* self, PyObject* args)
2271{
2272 int err;
2273 char pad;
2274
2275 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2276 PyErr_Clear();
2277 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2278 return NULL;
2279 }
2280 CHECK_DB_NOT_CLOSED(self);
2281
2282 MYDB_BEGIN_ALLOW_THREADS;
2283 err = self->db->set_re_pad(self->db, pad);
2284 MYDB_END_ALLOW_THREADS;
2285 RETURN_IF_ERR();
2286 RETURN_NONE();
2287}
2288
2289
2290static PyObject*
2291DB_set_re_source(DBObject* self, PyObject* args)
2292{
2293 int err;
2294 char *re_source;
2295
2296 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2297 return NULL;
2298 CHECK_DB_NOT_CLOSED(self);
2299
2300 MYDB_BEGIN_ALLOW_THREADS;
2301 err = self->db->set_re_source(self->db, re_source);
2302 MYDB_END_ALLOW_THREADS;
2303 RETURN_IF_ERR();
2304 RETURN_NONE();
2305}
2306
2307
2308#if (DBVER >= 32)
2309static PyObject*
2310DB_set_q_extentsize(DBObject* self, PyObject* args)
2311{
2312 int err;
2313 int extentsize;
2314
2315 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2316 return NULL;
2317 CHECK_DB_NOT_CLOSED(self);
2318
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->set_q_extentsize(self->db, extentsize);
2321 MYDB_END_ALLOW_THREADS;
2322 RETURN_IF_ERR();
2323 RETURN_NONE();
2324}
2325#endif
2326
2327static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002328DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002329{
2330 int err, flags = 0, type;
2331 void* sp;
2332 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002333#if (DBVER >= 43)
2334 PyObject* txnobj = NULL;
2335 DB_TXN *txn = NULL;
2336 char* kwnames[] = { "txn", "flags", NULL };
2337#else
2338 char* kwnames[] = { "flags", NULL };
2339#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002340
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002341#if (DBVER >= 43)
2342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2343 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002344 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002345 if (!checkTxnObj(txnobj, &txn))
2346 return NULL;
2347#else
2348 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2349 return NULL;
2350#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002351 CHECK_DB_NOT_CLOSED(self);
2352
2353 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002354#if (DBVER >= 43)
2355 err = self->db->stat(self->db, txn, &sp, flags);
2356#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002357 err = self->db->stat(self->db, &sp, flags);
2358#else
2359 err = self->db->stat(self->db, &sp, NULL, flags);
2360#endif
2361 MYDB_END_ALLOW_THREADS;
2362 RETURN_IF_ERR();
2363
2364 self->haveStat = 1;
2365
2366 /* Turn the stat structure into a dictionary */
2367 type = _DB_get_type(self);
2368 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2369 free(sp);
2370 return NULL;
2371 }
2372
2373#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2374#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2375#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2376
2377 switch (type) {
2378 case DB_HASH:
2379 MAKE_HASH_ENTRY(magic);
2380 MAKE_HASH_ENTRY(version);
2381 MAKE_HASH_ENTRY(nkeys);
2382 MAKE_HASH_ENTRY(ndata);
2383 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002384#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002385 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002386#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002387 MAKE_HASH_ENTRY(ffactor);
2388 MAKE_HASH_ENTRY(buckets);
2389 MAKE_HASH_ENTRY(free);
2390 MAKE_HASH_ENTRY(bfree);
2391 MAKE_HASH_ENTRY(bigpages);
2392 MAKE_HASH_ENTRY(big_bfree);
2393 MAKE_HASH_ENTRY(overflows);
2394 MAKE_HASH_ENTRY(ovfl_free);
2395 MAKE_HASH_ENTRY(dup);
2396 MAKE_HASH_ENTRY(dup_free);
2397 break;
2398
2399 case DB_BTREE:
2400 case DB_RECNO:
2401 MAKE_BT_ENTRY(magic);
2402 MAKE_BT_ENTRY(version);
2403 MAKE_BT_ENTRY(nkeys);
2404 MAKE_BT_ENTRY(ndata);
2405 MAKE_BT_ENTRY(pagesize);
2406 MAKE_BT_ENTRY(minkey);
2407 MAKE_BT_ENTRY(re_len);
2408 MAKE_BT_ENTRY(re_pad);
2409 MAKE_BT_ENTRY(levels);
2410 MAKE_BT_ENTRY(int_pg);
2411 MAKE_BT_ENTRY(leaf_pg);
2412 MAKE_BT_ENTRY(dup_pg);
2413 MAKE_BT_ENTRY(over_pg);
2414 MAKE_BT_ENTRY(free);
2415 MAKE_BT_ENTRY(int_pgfree);
2416 MAKE_BT_ENTRY(leaf_pgfree);
2417 MAKE_BT_ENTRY(dup_pgfree);
2418 MAKE_BT_ENTRY(over_pgfree);
2419 break;
2420
2421 case DB_QUEUE:
2422 MAKE_QUEUE_ENTRY(magic);
2423 MAKE_QUEUE_ENTRY(version);
2424 MAKE_QUEUE_ENTRY(nkeys);
2425 MAKE_QUEUE_ENTRY(ndata);
2426 MAKE_QUEUE_ENTRY(pagesize);
2427 MAKE_QUEUE_ENTRY(pages);
2428 MAKE_QUEUE_ENTRY(re_len);
2429 MAKE_QUEUE_ENTRY(re_pad);
2430 MAKE_QUEUE_ENTRY(pgfree);
2431#if (DBVER == 31)
2432 MAKE_QUEUE_ENTRY(start);
2433#endif
2434 MAKE_QUEUE_ENTRY(first_recno);
2435 MAKE_QUEUE_ENTRY(cur_recno);
2436 break;
2437
2438 default:
2439 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2440 Py_DECREF(d);
2441 d = NULL;
2442 }
2443
2444#undef MAKE_HASH_ENTRY
2445#undef MAKE_BT_ENTRY
2446#undef MAKE_QUEUE_ENTRY
2447
2448 free(sp);
2449 return d;
2450}
2451
2452static PyObject*
2453DB_sync(DBObject* self, PyObject* args)
2454{
2455 int err;
2456 int flags = 0;
2457
2458 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2459 return NULL;
2460 CHECK_DB_NOT_CLOSED(self);
2461
2462 MYDB_BEGIN_ALLOW_THREADS;
2463 err = self->db->sync(self->db, flags);
2464 MYDB_END_ALLOW_THREADS;
2465 RETURN_IF_ERR();
2466 RETURN_NONE();
2467}
2468
2469
2470#if (DBVER >= 33)
2471static PyObject*
2472DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2473{
2474 int err, flags=0;
2475 u_int32_t count=0;
2476 PyObject* txnobj = NULL;
2477 DB_TXN *txn = NULL;
2478 char* kwnames[] = { "txn", "flags", NULL };
2479
2480 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2481 &txnobj, &flags))
2482 return NULL;
2483 CHECK_DB_NOT_CLOSED(self);
2484 if (!checkTxnObj(txnobj, &txn))
2485 return NULL;
2486
2487 MYDB_BEGIN_ALLOW_THREADS;
2488 err = self->db->truncate(self->db, txn, &count, flags);
2489 MYDB_END_ALLOW_THREADS;
2490 RETURN_IF_ERR();
2491 return PyInt_FromLong(count);
2492}
2493#endif
2494
2495
2496static PyObject*
2497DB_upgrade(DBObject* self, PyObject* args)
2498{
2499 int err, flags=0;
2500 char *filename;
2501
2502 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2503 return NULL;
2504 CHECK_DB_NOT_CLOSED(self);
2505
2506 MYDB_BEGIN_ALLOW_THREADS;
2507 err = self->db->upgrade(self->db, filename, flags);
2508 MYDB_END_ALLOW_THREADS;
2509 RETURN_IF_ERR();
2510 RETURN_NONE();
2511}
2512
2513
2514static PyObject*
2515DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2516{
2517 int err, flags=0;
2518 char* fileName;
2519 char* dbName=NULL;
2520 char* outFileName=NULL;
2521 FILE* outFile=NULL;
2522 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2523
2524 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2525 &fileName, &dbName, &outFileName, &flags))
2526 return NULL;
2527
2528 CHECK_DB_NOT_CLOSED(self);
2529 if (outFileName)
2530 outFile = fopen(outFileName, "w");
2531
2532 MYDB_BEGIN_ALLOW_THREADS;
2533 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2534 MYDB_END_ALLOW_THREADS;
2535 if (outFileName)
2536 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002537
2538 /* DB.verify acts as a DB handle destructor (like close); this was
2539 * documented in BerkeleyDB 4.2 but had the undocumented effect
2540 * of not being safe in prior versions while still requiring an explicit
2541 * DB.close call afterwards. Lets call close for the user to emulate
2542 * the safe 4.2 behaviour. */
2543#if (DBVER <= 41)
2544 self->db->close(self->db, 0);
2545#endif
2546 self->db = NULL;
2547
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002548 RETURN_IF_ERR();
2549 RETURN_NONE();
2550}
2551
2552
2553static PyObject*
2554DB_set_get_returns_none(DBObject* self, PyObject* args)
2555{
2556 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002557 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002558
2559 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2560 return NULL;
2561 CHECK_DB_NOT_CLOSED(self);
2562
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002563 if (self->moduleFlags.getReturnsNone)
2564 ++oldValue;
2565 if (self->moduleFlags.cursorSetReturnsNone)
2566 ++oldValue;
2567 self->moduleFlags.getReturnsNone = (flags >= 1);
2568 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002569 return PyInt_FromLong(oldValue);
2570}
2571
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002572#if (DBVER >= 41)
2573static PyObject*
2574DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2575{
2576 int err;
2577 u_int32_t flags=0;
2578 char *passwd = NULL;
2579 char* kwnames[] = { "passwd", "flags", NULL };
2580
2581 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2582 &passwd, &flags)) {
2583 return NULL;
2584 }
2585
2586 MYDB_BEGIN_ALLOW_THREADS;
2587 err = self->db->set_encrypt(self->db, passwd, flags);
2588 MYDB_END_ALLOW_THREADS;
2589
2590 RETURN_IF_ERR();
2591 RETURN_NONE();
2592}
2593#endif /* DBVER >= 41 */
2594
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002595
2596/*-------------------------------------------------------------- */
2597/* Mapping and Dictionary-like access routines */
2598
2599int DB_length(DBObject* self)
2600{
2601 int err;
2602 long size = 0;
2603 int flags = 0;
2604 void* sp;
2605
2606 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002607 PyErr_SetObject(DBError,
2608 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002609 return -1;
2610 }
2611
2612 if (self->haveStat) { /* Has the stat function been called recently? If
2613 so, we can use the cached value. */
2614 flags = DB_CACHED_COUNTS;
2615 }
2616
2617 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002618#if (DBVER >= 43)
2619 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2620#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002621 err = self->db->stat(self->db, &sp, flags);
2622#else
2623 err = self->db->stat(self->db, &sp, NULL, flags);
2624#endif
2625 MYDB_END_ALLOW_THREADS;
2626
2627 if (err)
2628 return -1;
2629
2630 self->haveStat = 1;
2631
2632 /* All the stat structures have matching fields upto the ndata field,
2633 so we can use any of them for the type cast */
2634 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2635 free(sp);
2636 return size;
2637}
2638
2639
2640PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2641{
2642 int err;
2643 PyObject* retval;
2644 DBT key;
2645 DBT data;
2646
2647 CHECK_DB_NOT_CLOSED(self);
2648 if (!make_key_dbt(self, keyobj, &key, NULL))
2649 return NULL;
2650
2651 CLEAR_DBT(data);
2652 if (CHECK_DBFLAG(self, DB_THREAD)) {
2653 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2654 data.flags = DB_DBT_MALLOC;
2655 }
2656 MYDB_BEGIN_ALLOW_THREADS;
2657 err = self->db->get(self->db, NULL, &key, &data, 0);
2658 MYDB_END_ALLOW_THREADS;
2659 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2660 PyErr_SetObject(PyExc_KeyError, keyobj);
2661 retval = NULL;
2662 }
2663 else if (makeDBError(err)) {
2664 retval = NULL;
2665 }
2666 else {
2667 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2668 FREE_DBT(data);
2669 }
2670
2671 FREE_DBT(key);
2672 return retval;
2673}
2674
2675
2676static int
2677DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2678{
2679 DBT key, data;
2680 int retval;
2681 int flags = 0;
2682
2683 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002684 PyErr_SetObject(DBError,
2685 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686 return -1;
2687 }
2688
2689 if (!make_key_dbt(self, keyobj, &key, NULL))
2690 return -1;
2691
2692 if (dataobj != NULL) {
2693 if (!make_dbt(dataobj, &data))
2694 retval = -1;
2695 else {
2696 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002697 /* dictionaries shouldn't have duplicate keys */
2698 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699 retval = _DB_put(self, NULL, &key, &data, flags);
2700
2701 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002702 /* try deleting any old record that matches and then PUT it
2703 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704 _DB_delete(self, NULL, &key, 0);
2705 PyErr_Clear();
2706 retval = _DB_put(self, NULL, &key, &data, flags);
2707 }
2708 }
2709 }
2710 else {
2711 /* dataobj == NULL, so delete the key */
2712 retval = _DB_delete(self, NULL, &key, 0);
2713 }
2714 FREE_DBT(key);
2715 return retval;
2716}
2717
2718
2719static PyObject*
2720DB_has_key(DBObject* self, PyObject* args)
2721{
2722 int err;
2723 PyObject* keyobj;
2724 DBT key, data;
2725 PyObject* txnobj = NULL;
2726 DB_TXN *txn = NULL;
2727
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002728 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002729 return NULL;
2730 CHECK_DB_NOT_CLOSED(self);
2731 if (!make_key_dbt(self, keyobj, &key, NULL))
2732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002733 if (!checkTxnObj(txnobj, &txn)) {
2734 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002735 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002736 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002738 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002739 it has a record but can't allocate a buffer for the data. This saves
2740 having to deal with data we won't be using.
2741 */
2742 CLEAR_DBT(data);
2743 data.flags = DB_DBT_USERMEM;
2744
2745 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002746 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 MYDB_END_ALLOW_THREADS;
2748 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002749
2750 if (err == DB_BUFFER_SMALL || err == 0) {
2751 return PyInt_FromLong(1);
2752 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2753 return PyInt_FromLong(0);
2754 }
2755
2756 makeDBError(err);
2757 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002758}
2759
2760
2761#define _KEYS_LIST 1
2762#define _VALUES_LIST 2
2763#define _ITEMS_LIST 3
2764
2765static PyObject*
2766_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2767{
2768 int err, dbtype;
2769 DBT key;
2770 DBT data;
2771 DBC *cursor;
2772 PyObject* list;
2773 PyObject* item = NULL;
2774
2775 CHECK_DB_NOT_CLOSED(self);
2776 CLEAR_DBT(key);
2777 CLEAR_DBT(data);
2778
2779 dbtype = _DB_get_type(self);
2780 if (dbtype == -1)
2781 return NULL;
2782
2783 list = PyList_New(0);
2784 if (list == NULL) {
2785 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2786 return NULL;
2787 }
2788
2789 /* get a cursor */
2790 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002791 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792 MYDB_END_ALLOW_THREADS;
2793 RETURN_IF_ERR();
2794
2795 if (CHECK_DBFLAG(self, DB_THREAD)) {
2796 key.flags = DB_DBT_REALLOC;
2797 data.flags = DB_DBT_REALLOC;
2798 }
2799
2800 while (1) { /* use the cursor to traverse the DB, collecting items */
2801 MYDB_BEGIN_ALLOW_THREADS;
2802 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2803 MYDB_END_ALLOW_THREADS;
2804
2805 if (err) {
2806 /* for any error, break out of the loop */
2807 break;
2808 }
2809
2810 switch (type) {
2811 case _KEYS_LIST:
2812 switch(dbtype) {
2813 case DB_BTREE:
2814 case DB_HASH:
2815 default:
2816 item = PyString_FromStringAndSize((char*)key.data, key.size);
2817 break;
2818 case DB_RECNO:
2819 case DB_QUEUE:
2820 item = PyInt_FromLong(*((db_recno_t*)key.data));
2821 break;
2822 }
2823 break;
2824
2825 case _VALUES_LIST:
2826 item = PyString_FromStringAndSize((char*)data.data, data.size);
2827 break;
2828
2829 case _ITEMS_LIST:
2830 switch(dbtype) {
2831 case DB_BTREE:
2832 case DB_HASH:
2833 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002834 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2835 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836 break;
2837 case DB_RECNO:
2838 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002839 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2840 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002841 break;
2842 }
2843 break;
2844 }
2845 if (item == NULL) {
2846 Py_DECREF(list);
2847 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2848 list = NULL;
2849 goto done;
2850 }
2851 PyList_Append(list, item);
2852 Py_DECREF(item);
2853 }
2854
Gregory P. Smithe9477062005-06-04 06:46:59 +00002855 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2856 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 Py_DECREF(list);
2858 list = NULL;
2859 }
2860
2861 done:
2862 FREE_DBT(key);
2863 FREE_DBT(data);
2864 MYDB_BEGIN_ALLOW_THREADS;
2865 cursor->c_close(cursor);
2866 MYDB_END_ALLOW_THREADS;
2867 return list;
2868}
2869
2870
2871static PyObject*
2872DB_keys(DBObject* self, PyObject* args)
2873{
2874 PyObject* txnobj = NULL;
2875 DB_TXN *txn = NULL;
2876
2877 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2878 return NULL;
2879 if (!checkTxnObj(txnobj, &txn))
2880 return NULL;
2881 return _DB_make_list(self, txn, _KEYS_LIST);
2882}
2883
2884
2885static PyObject*
2886DB_items(DBObject* self, PyObject* args)
2887{
2888 PyObject* txnobj = NULL;
2889 DB_TXN *txn = NULL;
2890
2891 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2892 return NULL;
2893 if (!checkTxnObj(txnobj, &txn))
2894 return NULL;
2895 return _DB_make_list(self, txn, _ITEMS_LIST);
2896}
2897
2898
2899static PyObject*
2900DB_values(DBObject* self, PyObject* args)
2901{
2902 PyObject* txnobj = NULL;
2903 DB_TXN *txn = NULL;
2904
2905 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2906 return NULL;
2907 if (!checkTxnObj(txnobj, &txn))
2908 return NULL;
2909 return _DB_make_list(self, txn, _VALUES_LIST);
2910}
2911
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002912/* --------------------------------------------------------------------- */
2913/* DBCursor methods */
2914
2915
2916static PyObject*
2917DBC_close(DBCursorObject* self, PyObject* args)
2918{
2919 int err = 0;
2920
2921 if (!PyArg_ParseTuple(args, ":close"))
2922 return NULL;
2923
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924 if (self->dbc != NULL) {
2925 MYDB_BEGIN_ALLOW_THREADS;
2926 err = self->dbc->c_close(self->dbc);
2927 self->dbc = NULL;
2928 MYDB_END_ALLOW_THREADS;
2929 }
2930 RETURN_IF_ERR();
2931 RETURN_NONE();
2932}
2933
2934
2935static PyObject*
2936DBC_count(DBCursorObject* self, PyObject* args)
2937{
2938 int err = 0;
2939 db_recno_t count;
2940 int flags = 0;
2941
2942 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2943 return NULL;
2944
2945 CHECK_CURSOR_NOT_CLOSED(self);
2946
2947 MYDB_BEGIN_ALLOW_THREADS;
2948 err = self->dbc->c_count(self->dbc, &count, flags);
2949 MYDB_END_ALLOW_THREADS;
2950 RETURN_IF_ERR();
2951
2952 return PyInt_FromLong(count);
2953}
2954
2955
2956static PyObject*
2957DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2958{
2959 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2960}
2961
2962
2963static PyObject*
2964DBC_delete(DBCursorObject* self, PyObject* args)
2965{
2966 int err, flags=0;
2967
2968 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2969 return NULL;
2970
2971 CHECK_CURSOR_NOT_CLOSED(self);
2972
2973 MYDB_BEGIN_ALLOW_THREADS;
2974 err = self->dbc->c_del(self->dbc, flags);
2975 MYDB_END_ALLOW_THREADS;
2976 RETURN_IF_ERR();
2977
2978 self->mydb->haveStat = 0;
2979 RETURN_NONE();
2980}
2981
2982
2983static PyObject*
2984DBC_dup(DBCursorObject* self, PyObject* args)
2985{
2986 int err, flags =0;
2987 DBC* dbc = NULL;
2988
2989 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2990 return NULL;
2991
2992 CHECK_CURSOR_NOT_CLOSED(self);
2993
2994 MYDB_BEGIN_ALLOW_THREADS;
2995 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2996 MYDB_END_ALLOW_THREADS;
2997 RETURN_IF_ERR();
2998
2999 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3000}
3001
3002static PyObject*
3003DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3004{
3005 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3006}
3007
3008
3009static PyObject*
3010DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3011{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003012 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003013 PyObject* keyobj = NULL;
3014 PyObject* dataobj = NULL;
3015 PyObject* retval = NULL;
3016 int dlen = -1;
3017 int doff = -1;
3018 DBT key, data;
3019 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
3020
3021 CLEAR_DBT(key);
3022 CLEAR_DBT(data);
3023 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003024 &flags, &dlen, &doff))
3025 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003026 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3028 &kwnames[1],
3029 &keyobj, &flags, &dlen, &doff))
3030 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003032 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3033 kwnames, &keyobj, &dataobj,
3034 &flags, &dlen, &doff))
3035 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036 return NULL;
3037 }
3038 }
3039 }
3040
3041 CHECK_CURSOR_NOT_CLOSED(self);
3042
3043 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3044 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003045 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3046 (!add_partial_dbt(&data, dlen, doff)) )
3047 {
3048 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003049 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003050 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051
3052 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3053 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003054 if (!(key.flags & DB_DBT_REALLOC)) {
3055 key.flags |= DB_DBT_MALLOC;
3056 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057 }
3058
3059 MYDB_BEGIN_ALLOW_THREADS;
3060 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3061 MYDB_END_ALLOW_THREADS;
3062
Gregory P. Smithe9477062005-06-04 06:46:59 +00003063 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3064 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065 Py_INCREF(Py_None);
3066 retval = Py_None;
3067 }
3068 else if (makeDBError(err)) {
3069 retval = NULL;
3070 }
3071 else {
3072 switch (_DB_get_type(self->mydb)) {
3073 case -1:
3074 retval = NULL;
3075 break;
3076 case DB_BTREE:
3077 case DB_HASH:
3078 default:
3079 retval = Py_BuildValue("s#s#", key.data, key.size,
3080 data.data, data.size);
3081 break;
3082 case DB_RECNO:
3083 case DB_QUEUE:
3084 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3085 data.data, data.size);
3086 break;
3087 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003088 FREE_DBT(data);
3089 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003090 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003091 return retval;
3092}
3093
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003094#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003095static PyObject*
3096DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3097{
3098 int err, flags=0;
3099 PyObject* keyobj = NULL;
3100 PyObject* dataobj = NULL;
3101 PyObject* retval = NULL;
3102 int dlen = -1;
3103 int doff = -1;
3104 DBT key, pkey, data;
3105 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
3106
3107 CLEAR_DBT(key);
3108 CLEAR_DBT(data);
3109 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3110 &flags, &dlen, &doff))
3111 {
3112 PyErr_Clear();
3113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3114 &kwnames[1],
3115 &keyobj, &flags, &dlen, &doff))
3116 {
3117 PyErr_Clear();
3118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3119 kwnames, &keyobj, &dataobj,
3120 &flags, &dlen, &doff))
3121 {
3122 return NULL;
3123 }
3124 }
3125 }
3126
3127 CHECK_CURSOR_NOT_CLOSED(self);
3128
3129 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3130 return NULL;
3131 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3132 (!add_partial_dbt(&data, dlen, doff)) ) {
3133 FREE_DBT(key);
3134 return NULL;
3135 }
3136
3137 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3138 data.flags = DB_DBT_MALLOC;
3139 if (!(key.flags & DB_DBT_REALLOC)) {
3140 key.flags |= DB_DBT_MALLOC;
3141 }
3142 }
3143
3144 CLEAR_DBT(pkey);
3145 pkey.flags = DB_DBT_MALLOC;
3146
3147 MYDB_BEGIN_ALLOW_THREADS;
3148 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3149 MYDB_END_ALLOW_THREADS;
3150
Gregory P. Smithe9477062005-06-04 06:46:59 +00003151 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3152 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003153 Py_INCREF(Py_None);
3154 retval = Py_None;
3155 }
3156 else if (makeDBError(err)) {
3157 retval = NULL;
3158 }
3159 else {
3160 PyObject *pkeyObj;
3161 PyObject *dataObj;
3162 dataObj = PyString_FromStringAndSize(data.data, data.size);
3163
3164 if (self->mydb->primaryDBType == DB_RECNO ||
3165 self->mydb->primaryDBType == DB_QUEUE)
3166 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
3167 else
3168 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3169
3170 if (flags & DB_SET_RECNO) /* return key, pkey and data */
3171 {
3172 PyObject *keyObj;
3173 int type = _DB_get_type(self->mydb);
3174 if (type == DB_RECNO || type == DB_QUEUE)
3175 keyObj = PyInt_FromLong(*(long *)key.data);
3176 else
3177 keyObj = PyString_FromStringAndSize(key.data, key.size);
3178 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3179 FREE_DBT(key);
3180 }
3181 else /* return just the pkey and data */
3182 {
3183 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3184 }
3185 FREE_DBT(pkey);
3186 FREE_DBT(data);
3187 }
3188 /* the only time REALLOC should be set is if we used an integer
3189 * key that make_key_dbt malloc'd for us. always free these. */
3190 if (key.flags & DB_DBT_REALLOC) {
3191 FREE_DBT(key);
3192 }
3193 return retval;
3194}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003195#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003196
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003197
3198static PyObject*
3199DBC_get_recno(DBCursorObject* self, PyObject* args)
3200{
3201 int err;
3202 db_recno_t recno;
3203 DBT key;
3204 DBT data;
3205
3206 if (!PyArg_ParseTuple(args, ":get_recno"))
3207 return NULL;
3208
3209 CHECK_CURSOR_NOT_CLOSED(self);
3210
3211 CLEAR_DBT(key);
3212 CLEAR_DBT(data);
3213 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3214 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3215 data.flags = DB_DBT_MALLOC;
3216 key.flags = DB_DBT_MALLOC;
3217 }
3218
3219 MYDB_BEGIN_ALLOW_THREADS;
3220 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3221 MYDB_END_ALLOW_THREADS;
3222 RETURN_IF_ERR();
3223
3224 recno = *((db_recno_t*)data.data);
3225 FREE_DBT(key);
3226 FREE_DBT(data);
3227 return PyInt_FromLong(recno);
3228}
3229
3230
3231static PyObject*
3232DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3233{
3234 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3235}
3236
3237
3238static PyObject*
3239DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3240{
3241 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3242}
3243
3244
3245static PyObject*
3246DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3247{
3248 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3249}
3250
3251
3252static PyObject*
3253DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3254{
3255 int err, flags = 0;
3256 PyObject* keyobj, *dataobj;
3257 DBT key, data;
3258 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3259 int dlen = -1;
3260 int doff = -1;
3261
3262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3263 &keyobj, &dataobj, &flags, &dlen, &doff))
3264 return NULL;
3265
3266 CHECK_CURSOR_NOT_CLOSED(self);
3267
3268 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3269 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003270 if (!make_dbt(dataobj, &data) ||
3271 !add_partial_dbt(&data, dlen, doff) )
3272 {
3273 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003274 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003275 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003276
3277 MYDB_BEGIN_ALLOW_THREADS;
3278 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3279 MYDB_END_ALLOW_THREADS;
3280 FREE_DBT(key);
3281 RETURN_IF_ERR();
3282 self->mydb->haveStat = 0;
3283 RETURN_NONE();
3284}
3285
3286
3287static PyObject*
3288DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3289{
3290 int err, flags = 0;
3291 DBT key, data;
3292 PyObject* retval, *keyobj;
3293 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3294 int dlen = -1;
3295 int doff = -1;
3296
3297 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3298 &keyobj, &flags, &dlen, &doff))
3299 return NULL;
3300
3301 CHECK_CURSOR_NOT_CLOSED(self);
3302
3303 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3304 return NULL;
3305
3306 CLEAR_DBT(data);
3307 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3308 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3309 data.flags = DB_DBT_MALLOC;
3310 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003311 if (!add_partial_dbt(&data, dlen, doff)) {
3312 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003313 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003314 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003315
3316 MYDB_BEGIN_ALLOW_THREADS;
3317 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3318 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003319 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3320 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003321 Py_INCREF(Py_None);
3322 retval = Py_None;
3323 }
3324 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003325 retval = NULL;
3326 }
3327 else {
3328 switch (_DB_get_type(self->mydb)) {
3329 case -1:
3330 retval = NULL;
3331 break;
3332 case DB_BTREE:
3333 case DB_HASH:
3334 default:
3335 retval = Py_BuildValue("s#s#", key.data, key.size,
3336 data.data, data.size);
3337 break;
3338 case DB_RECNO:
3339 case DB_QUEUE:
3340 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3341 data.data, data.size);
3342 break;
3343 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003344 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003345 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003347 /* the only time REALLOC should be set is if we used an integer
3348 * key that make_key_dbt malloc'd for us. always free these. */
3349 if (key.flags & DB_DBT_REALLOC) {
3350 FREE_DBT(key);
3351 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003352
3353 return retval;
3354}
3355
3356
3357static PyObject*
3358DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3359{
3360 int err, flags = 0;
3361 DBT key, data;
3362 PyObject* retval, *keyobj;
3363 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3364 int dlen = -1;
3365 int doff = -1;
3366
3367 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3368 &keyobj, &flags, &dlen, &doff))
3369 return NULL;
3370
3371 CHECK_CURSOR_NOT_CLOSED(self);
3372
3373 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3374 return NULL;
3375
3376 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003377 if (!add_partial_dbt(&data, dlen, doff)) {
3378 FREE_DBT(key);
3379 return NULL;
3380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003381 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3382 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003383 data.flags |= DB_DBT_MALLOC;
3384 /* only BTREE databases will return anything in the key */
3385 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3386 key.flags |= DB_DBT_MALLOC;
3387 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003388 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003389 MYDB_BEGIN_ALLOW_THREADS;
3390 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3391 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003392 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3393 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003394 Py_INCREF(Py_None);
3395 retval = Py_None;
3396 }
3397 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003398 retval = NULL;
3399 }
3400 else {
3401 switch (_DB_get_type(self->mydb)) {
3402 case -1:
3403 retval = NULL;
3404 break;
3405 case DB_BTREE:
3406 case DB_HASH:
3407 default:
3408 retval = Py_BuildValue("s#s#", key.data, key.size,
3409 data.data, data.size);
3410 break;
3411 case DB_RECNO:
3412 case DB_QUEUE:
3413 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3414 data.data, data.size);
3415 break;
3416 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003417 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 FREE_DBT(data);
3419 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003420 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003421 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003422 if (key.flags & DB_DBT_REALLOC) {
3423 FREE_DBT(key);
3424 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003425
3426 return retval;
3427}
3428
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003429static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003430_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3431 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003433 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003434 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003435 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003436
Gregory P. Smith7441e652003-11-03 21:35:31 +00003437 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003438 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3439 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003440 if (!make_dbt(dataobj, &data)) {
3441 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003443 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444
3445 MYDB_BEGIN_ALLOW_THREADS;
3446 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3447 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003448 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003449 Py_INCREF(Py_None);
3450 retval = Py_None;
3451 }
3452 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003453 retval = NULL;
3454 }
3455 else {
3456 switch (_DB_get_type(self->mydb)) {
3457 case -1:
3458 retval = NULL;
3459 break;
3460 case DB_BTREE:
3461 case DB_HASH:
3462 default:
3463 retval = Py_BuildValue("s#s#", key.data, key.size,
3464 data.data, data.size);
3465 break;
3466 case DB_RECNO:
3467 case DB_QUEUE:
3468 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3469 data.data, data.size);
3470 break;
3471 }
3472 }
3473
3474 FREE_DBT(key);
3475 return retval;
3476}
3477
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003478static PyObject*
3479DBC_get_both(DBCursorObject* self, PyObject* args)
3480{
3481 int flags=0;
3482 PyObject *keyobj, *dataobj;
3483
3484 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3485 return NULL;
3486
Gregory P. Smith7441e652003-11-03 21:35:31 +00003487 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003488 CHECK_CURSOR_NOT_CLOSED(self);
3489
3490 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3491 self->mydb->moduleFlags.getReturnsNone);
3492}
3493
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003494/* Return size of entry */
3495static PyObject*
3496DBC_get_current_size(DBCursorObject* self, PyObject* args)
3497{
3498 int err, flags=DB_CURRENT;
3499 PyObject* retval = NULL;
3500 DBT key, data;
3501
3502 if (!PyArg_ParseTuple(args, ":get_current_size"))
3503 return NULL;
3504 CHECK_CURSOR_NOT_CLOSED(self);
3505 CLEAR_DBT(key);
3506 CLEAR_DBT(data);
3507
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003508 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003509 getting the record size. */
3510 data.flags = DB_DBT_USERMEM;
3511 data.ulen = 0;
3512 MYDB_BEGIN_ALLOW_THREADS;
3513 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3514 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003515 if (err == DB_BUFFER_SMALL || !err) {
3516 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003517 retval = PyInt_FromLong((long)data.size);
3518 err = 0;
3519 }
3520
3521 FREE_DBT(key);
3522 FREE_DBT(data);
3523 RETURN_IF_ERR();
3524 return retval;
3525}
3526
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003527static PyObject*
3528DBC_set_both(DBCursorObject* self, PyObject* args)
3529{
3530 int flags=0;
3531 PyObject *keyobj, *dataobj;
3532
3533 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3534 return NULL;
3535
Gregory P. Smith7441e652003-11-03 21:35:31 +00003536 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003537 CHECK_CURSOR_NOT_CLOSED(self);
3538
3539 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3540 self->mydb->moduleFlags.cursorSetReturnsNone);
3541}
3542
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543
3544static PyObject*
3545DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3546{
3547 int err, irecno, flags=0;
3548 db_recno_t recno;
3549 DBT key, data;
3550 PyObject* retval;
3551 int dlen = -1;
3552 int doff = -1;
3553 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3554
3555 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3556 &irecno, &flags, &dlen, &doff))
3557 return NULL;
3558
3559 CHECK_CURSOR_NOT_CLOSED(self);
3560
3561 CLEAR_DBT(key);
3562 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003563 /* use allocated space so DB will be able to realloc room for the real
3564 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565 key.data = malloc(sizeof(db_recno_t));
3566 if (key.data == NULL) {
3567 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3568 return NULL;
3569 }
3570 key.size = sizeof(db_recno_t);
3571 key.ulen = key.size;
3572 memcpy(key.data, &recno, sizeof(db_recno_t));
3573 key.flags = DB_DBT_REALLOC;
3574
3575 CLEAR_DBT(data);
3576 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3577 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3578 data.flags = DB_DBT_MALLOC;
3579 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003580 if (!add_partial_dbt(&data, dlen, doff)) {
3581 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003583 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584
3585 MYDB_BEGIN_ALLOW_THREADS;
3586 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3587 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3589 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003590 Py_INCREF(Py_None);
3591 retval = Py_None;
3592 }
3593 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 retval = NULL;
3595 }
3596 else { /* Can only be used for BTrees, so no need to return int key */
3597 retval = Py_BuildValue("s#s#", key.data, key.size,
3598 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599 FREE_DBT(data);
3600 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003601 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602
3603 return retval;
3604}
3605
3606
3607static PyObject*
3608DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3609{
3610 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3611}
3612
3613
3614static PyObject*
3615DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3616{
3617 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3618}
3619
3620
3621static PyObject*
3622DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3623{
3624 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3625}
3626
3627
3628static PyObject*
3629DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3630{
3631 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3632}
3633
3634
3635static PyObject*
3636DBC_join_item(DBCursorObject* self, PyObject* args)
3637{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003638 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003639 DBT key, data;
3640 PyObject* retval;
3641
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003643 return NULL;
3644
3645 CHECK_CURSOR_NOT_CLOSED(self);
3646
3647 CLEAR_DBT(key);
3648 CLEAR_DBT(data);
3649 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3650 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3651 key.flags = DB_DBT_MALLOC;
3652 }
3653
3654 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003655 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003656 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003657 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3658 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003659 Py_INCREF(Py_None);
3660 retval = Py_None;
3661 }
3662 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003663 retval = NULL;
3664 }
3665 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003666 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003667 FREE_DBT(key);
3668 }
3669
3670 return retval;
3671}
3672
3673
3674
3675/* --------------------------------------------------------------------- */
3676/* DBEnv methods */
3677
3678
3679static PyObject*
3680DBEnv_close(DBEnvObject* self, PyObject* args)
3681{
3682 int err, flags = 0;
3683
3684 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3685 return NULL;
3686 if (!self->closed) { /* Don't close more than once */
3687 MYDB_BEGIN_ALLOW_THREADS;
3688 err = self->db_env->close(self->db_env, flags);
3689 MYDB_END_ALLOW_THREADS;
3690 /* after calling DBEnv->close, regardless of error, this DBEnv
3691 * may not be accessed again (BerkeleyDB docs). */
3692 self->closed = 1;
3693 self->db_env = NULL;
3694 RETURN_IF_ERR();
3695 }
3696 RETURN_NONE();
3697}
3698
3699
3700static PyObject*
3701DBEnv_open(DBEnvObject* self, PyObject* args)
3702{
3703 int err, flags=0, mode=0660;
3704 char *db_home;
3705
3706 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3707 return NULL;
3708
3709 CHECK_ENV_NOT_CLOSED(self);
3710
3711 MYDB_BEGIN_ALLOW_THREADS;
3712 err = self->db_env->open(self->db_env, db_home, flags, mode);
3713 MYDB_END_ALLOW_THREADS;
3714 RETURN_IF_ERR();
3715 self->closed = 0;
3716 self->flags = flags;
3717 RETURN_NONE();
3718}
3719
3720
3721static PyObject*
3722DBEnv_remove(DBEnvObject* self, PyObject* args)
3723{
3724 int err, flags=0;
3725 char *db_home;
3726
3727 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3728 return NULL;
3729 CHECK_ENV_NOT_CLOSED(self);
3730 MYDB_BEGIN_ALLOW_THREADS;
3731 err = self->db_env->remove(self->db_env, db_home, flags);
3732 MYDB_END_ALLOW_THREADS;
3733 RETURN_IF_ERR();
3734 RETURN_NONE();
3735}
3736
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003737#if (DBVER >= 41)
3738static PyObject*
3739DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3740{
3741 int err;
3742 u_int32_t flags=0;
3743 char *file = NULL;
3744 char *database = NULL;
3745 PyObject *txnobj = NULL;
3746 DB_TXN *txn = NULL;
3747 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3748
3749 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3750 &file, &database, &txnobj, &flags)) {
3751 return NULL;
3752 }
3753 if (!checkTxnObj(txnobj, &txn)) {
3754 return NULL;
3755 }
3756 CHECK_ENV_NOT_CLOSED(self);
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3759 MYDB_END_ALLOW_THREADS;
3760 RETURN_IF_ERR();
3761 RETURN_NONE();
3762}
3763
3764static PyObject*
3765DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3766{
3767 int err;
3768 u_int32_t flags=0;
3769 char *file = NULL;
3770 char *database = NULL;
3771 char *newname = NULL;
3772 PyObject *txnobj = NULL;
3773 DB_TXN *txn = NULL;
3774 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3775
3776 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3777 &file, &database, &newname, &txnobj, &flags)) {
3778 return NULL;
3779 }
3780 if (!checkTxnObj(txnobj, &txn)) {
3781 return NULL;
3782 }
3783 CHECK_ENV_NOT_CLOSED(self);
3784 MYDB_BEGIN_ALLOW_THREADS;
3785 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3786 flags);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3790}
3791
3792static PyObject*
3793DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3794{
3795 int err;
3796 u_int32_t flags=0;
3797 char *passwd = NULL;
3798 char* kwnames[] = { "passwd", "flags", NULL };
3799
3800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3801 &passwd, &flags)) {
3802 return NULL;
3803 }
3804
3805 MYDB_BEGIN_ALLOW_THREADS;
3806 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3807 MYDB_END_ALLOW_THREADS;
3808
3809 RETURN_IF_ERR();
3810 RETURN_NONE();
3811}
3812#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003814#if (DBVER >= 40)
3815static PyObject*
3816DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3817{
3818 int err;
3819 u_int32_t flags=0;
3820 u_int32_t timeout = 0;
3821 char* kwnames[] = { "timeout", "flags", NULL };
3822
3823 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3824 &timeout, &flags)) {
3825 return NULL;
3826 }
3827
3828 MYDB_BEGIN_ALLOW_THREADS;
3829 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3830 MYDB_END_ALLOW_THREADS;
3831
3832 RETURN_IF_ERR();
3833 RETURN_NONE();
3834}
3835#endif /* DBVER >= 40 */
3836
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003837static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003838DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3839{
3840 int err;
3841 long shm_key = 0;
3842
3843 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3844 return NULL;
3845 CHECK_ENV_NOT_CLOSED(self);
3846
3847 err = self->db_env->set_shm_key(self->db_env, shm_key);
3848 RETURN_IF_ERR();
3849 RETURN_NONE();
3850}
3851
3852static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003853DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3854{
3855 int err, gbytes=0, bytes=0, ncache=0;
3856
3857 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3858 &gbytes, &bytes, &ncache))
3859 return NULL;
3860 CHECK_ENV_NOT_CLOSED(self);
3861
3862 MYDB_BEGIN_ALLOW_THREADS;
3863 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3864 MYDB_END_ALLOW_THREADS;
3865 RETURN_IF_ERR();
3866 RETURN_NONE();
3867}
3868
3869
3870#if (DBVER >= 32)
3871static PyObject*
3872DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3873{
3874 int err, flags=0, onoff=0;
3875
3876 if (!PyArg_ParseTuple(args, "ii:set_flags",
3877 &flags, &onoff))
3878 return NULL;
3879 CHECK_ENV_NOT_CLOSED(self);
3880
3881 MYDB_BEGIN_ALLOW_THREADS;
3882 err = self->db_env->set_flags(self->db_env, flags, onoff);
3883 MYDB_END_ALLOW_THREADS;
3884 RETURN_IF_ERR();
3885 RETURN_NONE();
3886}
3887#endif
3888
3889
3890static PyObject*
3891DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3892{
3893 int err;
3894 char *dir;
3895
3896 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3897 return NULL;
3898 CHECK_ENV_NOT_CLOSED(self);
3899
3900 MYDB_BEGIN_ALLOW_THREADS;
3901 err = self->db_env->set_data_dir(self->db_env, dir);
3902 MYDB_END_ALLOW_THREADS;
3903 RETURN_IF_ERR();
3904 RETURN_NONE();
3905}
3906
3907
3908static PyObject*
3909DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3910{
3911 int err, lg_bsize;
3912
3913 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3914 return NULL;
3915 CHECK_ENV_NOT_CLOSED(self);
3916
3917 MYDB_BEGIN_ALLOW_THREADS;
3918 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3919 MYDB_END_ALLOW_THREADS;
3920 RETURN_IF_ERR();
3921 RETURN_NONE();
3922}
3923
3924
3925static PyObject*
3926DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3927{
3928 int err;
3929 char *dir;
3930
3931 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3932 return NULL;
3933 CHECK_ENV_NOT_CLOSED(self);
3934
3935 MYDB_BEGIN_ALLOW_THREADS;
3936 err = self->db_env->set_lg_dir(self->db_env, dir);
3937 MYDB_END_ALLOW_THREADS;
3938 RETURN_IF_ERR();
3939 RETURN_NONE();
3940}
3941
3942static PyObject*
3943DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3944{
3945 int err, lg_max;
3946
3947 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3948 return NULL;
3949 CHECK_ENV_NOT_CLOSED(self);
3950
3951 MYDB_BEGIN_ALLOW_THREADS;
3952 err = self->db_env->set_lg_max(self->db_env, lg_max);
3953 MYDB_END_ALLOW_THREADS;
3954 RETURN_IF_ERR();
3955 RETURN_NONE();
3956}
3957
3958
3959static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003960DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3961{
3962 int err, lg_max;
3963
3964 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3965 return NULL;
3966 CHECK_ENV_NOT_CLOSED(self);
3967
3968 MYDB_BEGIN_ALLOW_THREADS;
3969 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3970 MYDB_END_ALLOW_THREADS;
3971 RETURN_IF_ERR();
3972 RETURN_NONE();
3973}
3974
3975
3976static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003977DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3978{
3979 int err, lk_detect;
3980
3981 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3982 return NULL;
3983 CHECK_ENV_NOT_CLOSED(self);
3984
3985 MYDB_BEGIN_ALLOW_THREADS;
3986 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3987 MYDB_END_ALLOW_THREADS;
3988 RETURN_IF_ERR();
3989 RETURN_NONE();
3990}
3991
3992
3993static PyObject*
3994DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3995{
3996 int err, max;
3997
3998 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3999 return NULL;
4000 CHECK_ENV_NOT_CLOSED(self);
4001
4002 MYDB_BEGIN_ALLOW_THREADS;
4003 err = self->db_env->set_lk_max(self->db_env, max);
4004 MYDB_END_ALLOW_THREADS;
4005 RETURN_IF_ERR();
4006 RETURN_NONE();
4007}
4008
4009
4010#if (DBVER >= 32)
4011
4012static PyObject*
4013DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4014{
4015 int err, max;
4016
4017 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4018 return NULL;
4019 CHECK_ENV_NOT_CLOSED(self);
4020
4021 MYDB_BEGIN_ALLOW_THREADS;
4022 err = self->db_env->set_lk_max_locks(self->db_env, max);
4023 MYDB_END_ALLOW_THREADS;
4024 RETURN_IF_ERR();
4025 RETURN_NONE();
4026}
4027
4028
4029static PyObject*
4030DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4031{
4032 int err, max;
4033
4034 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4035 return NULL;
4036 CHECK_ENV_NOT_CLOSED(self);
4037
4038 MYDB_BEGIN_ALLOW_THREADS;
4039 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4040 MYDB_END_ALLOW_THREADS;
4041 RETURN_IF_ERR();
4042 RETURN_NONE();
4043}
4044
4045
4046static PyObject*
4047DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4048{
4049 int err, max;
4050
4051 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4052 return NULL;
4053 CHECK_ENV_NOT_CLOSED(self);
4054
4055 MYDB_BEGIN_ALLOW_THREADS;
4056 err = self->db_env->set_lk_max_objects(self->db_env, max);
4057 MYDB_END_ALLOW_THREADS;
4058 RETURN_IF_ERR();
4059 RETURN_NONE();
4060}
4061
4062#endif
4063
4064
4065static PyObject*
4066DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4067{
4068 int err, mp_mmapsize;
4069
4070 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4071 return NULL;
4072 CHECK_ENV_NOT_CLOSED(self);
4073
4074 MYDB_BEGIN_ALLOW_THREADS;
4075 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4076 MYDB_END_ALLOW_THREADS;
4077 RETURN_IF_ERR();
4078 RETURN_NONE();
4079}
4080
4081
4082static PyObject*
4083DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4084{
4085 int err;
4086 char *dir;
4087
4088 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4089 return NULL;
4090 CHECK_ENV_NOT_CLOSED(self);
4091
4092 MYDB_BEGIN_ALLOW_THREADS;
4093 err = self->db_env->set_tmp_dir(self->db_env, dir);
4094 MYDB_END_ALLOW_THREADS;
4095 RETURN_IF_ERR();
4096 RETURN_NONE();
4097}
4098
4099
4100static PyObject*
4101DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4102{
4103 int flags = 0;
4104 PyObject* txnobj = NULL;
4105 DB_TXN *txn = NULL;
4106 char* kwnames[] = { "parent", "flags", NULL };
4107
4108 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4109 &txnobj, &flags))
4110 return NULL;
4111
4112 if (!checkTxnObj(txnobj, &txn))
4113 return NULL;
4114 CHECK_ENV_NOT_CLOSED(self);
4115
4116 return (PyObject*)newDBTxnObject(self, txn, flags);
4117}
4118
4119
4120static PyObject*
4121DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4122{
4123 int err, kbyte=0, min=0, flags=0;
4124
4125 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4126 return NULL;
4127 CHECK_ENV_NOT_CLOSED(self);
4128
4129 MYDB_BEGIN_ALLOW_THREADS;
4130#if (DBVER >= 40)
4131 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4132#else
4133 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4134#endif
4135 MYDB_END_ALLOW_THREADS;
4136 RETURN_IF_ERR();
4137 RETURN_NONE();
4138}
4139
4140
4141static PyObject*
4142DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4143{
4144 int err, max;
4145
4146 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4147 return NULL;
4148 CHECK_ENV_NOT_CLOSED(self);
4149
4150 MYDB_BEGIN_ALLOW_THREADS;
4151 err = self->db_env->set_tx_max(self->db_env, max);
4152 MYDB_END_ALLOW_THREADS;
4153 RETURN_IF_ERR();
4154 RETURN_NONE();
4155}
4156
4157
4158static PyObject*
4159DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4160{
4161 int err, atype, flags=0;
4162 int aborted = 0;
4163
4164 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4165 return NULL;
4166 CHECK_ENV_NOT_CLOSED(self);
4167
4168 MYDB_BEGIN_ALLOW_THREADS;
4169#if (DBVER >= 40)
4170 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4171#else
4172 err = lock_detect(self->db_env, flags, atype, &aborted);
4173#endif
4174 MYDB_END_ALLOW_THREADS;
4175 RETURN_IF_ERR();
4176 return PyInt_FromLong(aborted);
4177}
4178
4179
4180static PyObject*
4181DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4182{
4183 int flags=0;
4184 int locker, lock_mode;
4185 DBT obj;
4186 PyObject* objobj;
4187
4188 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4189 return NULL;
4190
4191
4192 if (!make_dbt(objobj, &obj))
4193 return NULL;
4194
4195 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4196}
4197
4198
4199static PyObject*
4200DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4201{
4202 int err;
4203 u_int32_t theID;
4204
4205 if (!PyArg_ParseTuple(args, ":lock_id"))
4206 return NULL;
4207
4208 CHECK_ENV_NOT_CLOSED(self);
4209 MYDB_BEGIN_ALLOW_THREADS;
4210#if (DBVER >= 40)
4211 err = self->db_env->lock_id(self->db_env, &theID);
4212#else
4213 err = lock_id(self->db_env, &theID);
4214#endif
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217
4218 return PyInt_FromLong((long)theID);
4219}
4220
4221
4222static PyObject*
4223DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4224{
4225 int err;
4226 DBLockObject* dblockobj;
4227
4228 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4229 return NULL;
4230
4231 CHECK_ENV_NOT_CLOSED(self);
4232 MYDB_BEGIN_ALLOW_THREADS;
4233#if (DBVER >= 40)
4234 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4235#else
4236 err = lock_put(self->db_env, &dblockobj->lock);
4237#endif
4238 MYDB_END_ALLOW_THREADS;
4239 RETURN_IF_ERR();
4240 RETURN_NONE();
4241}
4242
4243
4244static PyObject*
4245DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4246{
4247 int err;
4248 DB_LOCK_STAT* sp;
4249 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004250 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004251
4252 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4253 return NULL;
4254 CHECK_ENV_NOT_CLOSED(self);
4255
4256 MYDB_BEGIN_ALLOW_THREADS;
4257#if (DBVER >= 40)
4258 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4259#else
4260#if (DBVER >= 33)
4261 err = lock_stat(self->db_env, &sp);
4262#else
4263 err = lock_stat(self->db_env, &sp, NULL);
4264#endif
4265#endif
4266 MYDB_END_ALLOW_THREADS;
4267 RETURN_IF_ERR();
4268
4269 /* Turn the stat structure into a dictionary */
4270 d = PyDict_New();
4271 if (d == NULL) {
4272 free(sp);
4273 return NULL;
4274 }
4275
4276#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4277
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004278#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004279 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004280#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004281 MAKE_ENTRY(nmodes);
4282#if (DBVER >= 32)
4283 MAKE_ENTRY(maxlocks);
4284 MAKE_ENTRY(maxlockers);
4285 MAKE_ENTRY(maxobjects);
4286 MAKE_ENTRY(nlocks);
4287 MAKE_ENTRY(maxnlocks);
4288#endif
4289 MAKE_ENTRY(nlockers);
4290 MAKE_ENTRY(maxnlockers);
4291#if (DBVER >= 32)
4292 MAKE_ENTRY(nobjects);
4293 MAKE_ENTRY(maxnobjects);
4294#endif
4295 MAKE_ENTRY(nrequests);
4296 MAKE_ENTRY(nreleases);
4297 MAKE_ENTRY(nnowaits);
4298 MAKE_ENTRY(nconflicts);
4299 MAKE_ENTRY(ndeadlocks);
4300 MAKE_ENTRY(regsize);
4301 MAKE_ENTRY(region_wait);
4302 MAKE_ENTRY(region_nowait);
4303
4304#undef MAKE_ENTRY
4305 free(sp);
4306 return d;
4307}
4308
4309
4310static PyObject*
4311DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4312{
4313 int flags=0;
4314 int err;
4315 char **log_list_start, **log_list;
4316 PyObject* list;
4317 PyObject* item = NULL;
4318
4319 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4320 return NULL;
4321
4322 CHECK_ENV_NOT_CLOSED(self);
4323 MYDB_BEGIN_ALLOW_THREADS;
4324#if (DBVER >= 40)
4325 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4326#elif (DBVER == 33)
4327 err = log_archive(self->db_env, &log_list, flags);
4328#else
4329 err = log_archive(self->db_env, &log_list, flags, NULL);
4330#endif
4331 MYDB_END_ALLOW_THREADS;
4332 RETURN_IF_ERR();
4333
4334 list = PyList_New(0);
4335 if (list == NULL) {
4336 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4337 return NULL;
4338 }
4339
4340 if (log_list) {
4341 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4342 item = PyString_FromString (*log_list);
4343 if (item == NULL) {
4344 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004345 PyErr_SetString(PyExc_MemoryError,
4346 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004347 list = NULL;
4348 break;
4349 }
4350 PyList_Append(list, item);
4351 Py_DECREF(item);
4352 }
4353 free(log_list_start);
4354 }
4355 return list;
4356}
4357
4358
4359static PyObject*
4360DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4361{
4362 int err;
4363 DB_TXN_STAT* sp;
4364 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004365 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004366
4367 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4368 return NULL;
4369 CHECK_ENV_NOT_CLOSED(self);
4370
4371 MYDB_BEGIN_ALLOW_THREADS;
4372#if (DBVER >= 40)
4373 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4374#elif (DBVER == 33)
4375 err = txn_stat(self->db_env, &sp);
4376#else
4377 err = txn_stat(self->db_env, &sp, NULL);
4378#endif
4379 MYDB_END_ALLOW_THREADS;
4380 RETURN_IF_ERR();
4381
4382 /* Turn the stat structure into a dictionary */
4383 d = PyDict_New();
4384 if (d == NULL) {
4385 free(sp);
4386 return NULL;
4387 }
4388
4389#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4390
4391 MAKE_ENTRY(time_ckp);
4392 MAKE_ENTRY(last_txnid);
4393 MAKE_ENTRY(maxtxns);
4394 MAKE_ENTRY(nactive);
4395 MAKE_ENTRY(maxnactive);
4396 MAKE_ENTRY(nbegins);
4397 MAKE_ENTRY(naborts);
4398 MAKE_ENTRY(ncommits);
4399 MAKE_ENTRY(regsize);
4400 MAKE_ENTRY(region_wait);
4401 MAKE_ENTRY(region_nowait);
4402
4403#undef MAKE_ENTRY
4404 free(sp);
4405 return d;
4406}
4407
4408
4409static PyObject*
4410DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4411{
4412 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004413 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004414
4415 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4416 return NULL;
4417 CHECK_ENV_NOT_CLOSED(self);
4418
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004419 if (self->moduleFlags.getReturnsNone)
4420 ++oldValue;
4421 if (self->moduleFlags.cursorSetReturnsNone)
4422 ++oldValue;
4423 self->moduleFlags.getReturnsNone = (flags >= 1);
4424 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004425 return PyInt_FromLong(oldValue);
4426}
4427
4428
4429/* --------------------------------------------------------------------- */
4430/* DBTxn methods */
4431
4432
4433static PyObject*
4434DBTxn_commit(DBTxnObject* self, PyObject* args)
4435{
4436 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004437 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004438
4439 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4440 return NULL;
4441
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004442 if (!self->txn) {
4443 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4444 "DBTxn must not be used after txn_commit or txn_abort"));
4445 return NULL;
4446 }
4447 txn = self->txn;
4448 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004449 MYDB_BEGIN_ALLOW_THREADS;
4450#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004451 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004452#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004453 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004454#endif
4455 MYDB_END_ALLOW_THREADS;
4456 RETURN_IF_ERR();
4457 RETURN_NONE();
4458}
4459
4460static PyObject*
4461DBTxn_prepare(DBTxnObject* self, PyObject* args)
4462{
4463#if (DBVER >= 33)
4464 int err;
4465 char* gid=NULL;
4466 int gid_size=0;
4467
4468 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4469 return NULL;
4470
4471 if (gid_size != DB_XIDDATASIZE) {
4472 PyErr_SetString(PyExc_TypeError,
4473 "gid must be DB_XIDDATASIZE bytes long");
4474 return NULL;
4475 }
4476
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004477 if (!self->txn) {
4478 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4479 "DBTxn must not be used after txn_commit or txn_abort"));
4480 return NULL;
4481 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004482 MYDB_BEGIN_ALLOW_THREADS;
4483#if (DBVER >= 40)
4484 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4485#else
4486 err = txn_prepare(self->txn, (u_int8_t*)gid);
4487#endif
4488 MYDB_END_ALLOW_THREADS;
4489 RETURN_IF_ERR();
4490 RETURN_NONE();
4491#else
4492 int err;
4493
4494 if (!PyArg_ParseTuple(args, ":prepare"))
4495 return NULL;
4496
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004497 if (!self->txn) {
4498 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4499 "DBTxn must not be used after txn_commit or txn_abort"));
4500 return NULL;
4501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502 MYDB_BEGIN_ALLOW_THREADS;
4503 err = txn_prepare(self->txn);
4504 MYDB_END_ALLOW_THREADS;
4505 RETURN_IF_ERR();
4506 RETURN_NONE();
4507#endif
4508}
4509
4510
4511static PyObject*
4512DBTxn_abort(DBTxnObject* self, PyObject* args)
4513{
4514 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004515 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004516
4517 if (!PyArg_ParseTuple(args, ":abort"))
4518 return NULL;
4519
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004520 if (!self->txn) {
4521 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4522 "DBTxn must not be used after txn_commit or txn_abort"));
4523 return NULL;
4524 }
4525 txn = self->txn;
4526 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004527 MYDB_BEGIN_ALLOW_THREADS;
4528#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004529 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004530#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004531 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004532#endif
4533 MYDB_END_ALLOW_THREADS;
4534 RETURN_IF_ERR();
4535 RETURN_NONE();
4536}
4537
4538
4539static PyObject*
4540DBTxn_id(DBTxnObject* self, PyObject* args)
4541{
4542 int id;
4543
4544 if (!PyArg_ParseTuple(args, ":id"))
4545 return NULL;
4546
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004547 if (!self->txn) {
4548 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4549 "DBTxn must not be used after txn_commit or txn_abort"));
4550 return NULL;
4551 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004552 MYDB_BEGIN_ALLOW_THREADS;
4553#if (DBVER >= 40)
4554 id = self->txn->id(self->txn);
4555#else
4556 id = txn_id(self->txn);
4557#endif
4558 MYDB_END_ALLOW_THREADS;
4559 return PyInt_FromLong(id);
4560}
4561
4562/* --------------------------------------------------------------------- */
4563/* Method definition tables and type objects */
4564
4565static PyMethodDef DB_methods[] = {
4566 {"append", (PyCFunction)DB_append, METH_VARARGS},
4567#if (DBVER >= 33)
4568 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4569#endif
4570 {"close", (PyCFunction)DB_close, METH_VARARGS},
4571#if (DBVER >= 32)
4572 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4573 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4574#endif
4575 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4576 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4577 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4578 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004579#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004580 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004582 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4583 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4584 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4585 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4586 {"join", (PyCFunction)DB_join, METH_VARARGS},
4587 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4588 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4589 {"items", (PyCFunction)DB_items, METH_VARARGS},
4590 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4591 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4592 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4593 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4594 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4595 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004596 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004597 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004598#if (DBVER >= 41)
4599 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4600#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004601 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4602 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4603 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4604 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4605 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4606 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4607 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4608 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4609 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4610#if (DBVER >= 32)
4611 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4612#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004613 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4615#if (DBVER >= 33)
4616 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4617#endif
4618 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4619 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4620 {"values", (PyCFunction)DB_values, METH_VARARGS},
4621 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4622 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4623 {NULL, NULL} /* sentinel */
4624};
4625
4626
4627static PyMappingMethods DB_mapping = {
4628 (inquiry)DB_length, /*mp_length*/
4629 (binaryfunc)DB_subscript, /*mp_subscript*/
4630 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4631};
4632
4633
4634static PyMethodDef DBCursor_methods[] = {
4635 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4636 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4637 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4638 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4639 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4640 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4641 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004642#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004643 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004644#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004645 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4646 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4647 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4648 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4649 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4650 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4651 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4652 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004653 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004654 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004655 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4656 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4657 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4658 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4659 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4660 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4661 {NULL, NULL} /* sentinel */
4662};
4663
4664
4665static PyMethodDef DBEnv_methods[] = {
4666 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4667 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4668 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004669#if (DBVER >= 41)
4670 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4671 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4672 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4673#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004674#if (DBVER >= 40)
4675 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4676#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004677 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004678 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4679 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4680#if (DBVER >= 32)
4681 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4682#endif
4683 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4684 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4685 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Gregory P. Smithe9477062005-06-04 06:46:59 +00004686 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4688 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4689#if (DBVER >= 32)
4690 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4691 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4692 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4693#endif
4694 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4695 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4696 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4697 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4698 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4699 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4700 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4701 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4702 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4703 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4704 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4705 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4706 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4707 {NULL, NULL} /* sentinel */
4708};
4709
4710
4711static PyMethodDef DBTxn_methods[] = {
4712 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4713 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4714 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4715 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4716 {NULL, NULL} /* sentinel */
4717};
4718
4719
4720static PyObject*
4721DB_getattr(DBObject* self, char *name)
4722{
4723 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4724}
4725
4726
4727static PyObject*
4728DBEnv_getattr(DBEnvObject* self, char *name)
4729{
4730 if (!strcmp(name, "db_home")) {
4731 CHECK_ENV_NOT_CLOSED(self);
4732 if (self->db_env->db_home == NULL) {
4733 RETURN_NONE();
4734 }
4735 return PyString_FromString(self->db_env->db_home);
4736 }
4737
4738 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4739}
4740
4741
4742static PyObject*
4743DBCursor_getattr(DBCursorObject* self, char *name)
4744{
4745 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4746}
4747
4748static PyObject*
4749DBTxn_getattr(DBTxnObject* self, char *name)
4750{
4751 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4752}
4753
4754static PyObject*
4755DBLock_getattr(DBLockObject* self, char *name)
4756{
4757 return NULL;
4758}
4759
4760statichere PyTypeObject DB_Type = {
4761 PyObject_HEAD_INIT(NULL)
4762 0, /*ob_size*/
4763 "DB", /*tp_name*/
4764 sizeof(DBObject), /*tp_basicsize*/
4765 0, /*tp_itemsize*/
4766 /* methods */
4767 (destructor)DB_dealloc, /*tp_dealloc*/
4768 0, /*tp_print*/
4769 (getattrfunc)DB_getattr, /*tp_getattr*/
4770 0, /*tp_setattr*/
4771 0, /*tp_compare*/
4772 0, /*tp_repr*/
4773 0, /*tp_as_number*/
4774 0, /*tp_as_sequence*/
4775 &DB_mapping,/*tp_as_mapping*/
4776 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004777#ifdef HAVE_WEAKREF
4778 0, /* tp_call */
4779 0, /* tp_str */
4780 0, /* tp_getattro */
4781 0, /* tp_setattro */
4782 0, /* tp_as_buffer */
4783 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4784 0, /* tp_doc */
4785 0, /* tp_traverse */
4786 0, /* tp_clear */
4787 0, /* tp_richcompare */
4788 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4789#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004790};
4791
4792
4793statichere PyTypeObject DBCursor_Type = {
4794 PyObject_HEAD_INIT(NULL)
4795 0, /*ob_size*/
4796 "DBCursor", /*tp_name*/
4797 sizeof(DBCursorObject), /*tp_basicsize*/
4798 0, /*tp_itemsize*/
4799 /* methods */
4800 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4801 0, /*tp_print*/
4802 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4803 0, /*tp_setattr*/
4804 0, /*tp_compare*/
4805 0, /*tp_repr*/
4806 0, /*tp_as_number*/
4807 0, /*tp_as_sequence*/
4808 0, /*tp_as_mapping*/
4809 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004810#ifdef HAVE_WEAKREF
4811 0, /* tp_call */
4812 0, /* tp_str */
4813 0, /* tp_getattro */
4814 0, /* tp_setattro */
4815 0, /* tp_as_buffer */
4816 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4817 0, /* tp_doc */
4818 0, /* tp_traverse */
4819 0, /* tp_clear */
4820 0, /* tp_richcompare */
4821 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4822#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004823};
4824
4825
4826statichere PyTypeObject DBEnv_Type = {
4827 PyObject_HEAD_INIT(NULL)
4828 0, /*ob_size*/
4829 "DBEnv", /*tp_name*/
4830 sizeof(DBEnvObject), /*tp_basicsize*/
4831 0, /*tp_itemsize*/
4832 /* methods */
4833 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4834 0, /*tp_print*/
4835 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4836 0, /*tp_setattr*/
4837 0, /*tp_compare*/
4838 0, /*tp_repr*/
4839 0, /*tp_as_number*/
4840 0, /*tp_as_sequence*/
4841 0, /*tp_as_mapping*/
4842 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004843#ifdef HAVE_WEAKREF
4844 0, /* tp_call */
4845 0, /* tp_str */
4846 0, /* tp_getattro */
4847 0, /* tp_setattro */
4848 0, /* tp_as_buffer */
4849 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4850 0, /* tp_doc */
4851 0, /* tp_traverse */
4852 0, /* tp_clear */
4853 0, /* tp_richcompare */
4854 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4855#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004856};
4857
4858statichere PyTypeObject DBTxn_Type = {
4859 PyObject_HEAD_INIT(NULL)
4860 0, /*ob_size*/
4861 "DBTxn", /*tp_name*/
4862 sizeof(DBTxnObject), /*tp_basicsize*/
4863 0, /*tp_itemsize*/
4864 /* methods */
4865 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4866 0, /*tp_print*/
4867 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4868 0, /*tp_setattr*/
4869 0, /*tp_compare*/
4870 0, /*tp_repr*/
4871 0, /*tp_as_number*/
4872 0, /*tp_as_sequence*/
4873 0, /*tp_as_mapping*/
4874 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004875#ifdef HAVE_WEAKREF
4876 0, /* tp_call */
4877 0, /* tp_str */
4878 0, /* tp_getattro */
4879 0, /* tp_setattro */
4880 0, /* tp_as_buffer */
4881 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4882 0, /* tp_doc */
4883 0, /* tp_traverse */
4884 0, /* tp_clear */
4885 0, /* tp_richcompare */
4886 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4887#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004888};
4889
4890
4891statichere PyTypeObject DBLock_Type = {
4892 PyObject_HEAD_INIT(NULL)
4893 0, /*ob_size*/
4894 "DBLock", /*tp_name*/
4895 sizeof(DBLockObject), /*tp_basicsize*/
4896 0, /*tp_itemsize*/
4897 /* methods */
4898 (destructor)DBLock_dealloc, /*tp_dealloc*/
4899 0, /*tp_print*/
4900 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4901 0, /*tp_setattr*/
4902 0, /*tp_compare*/
4903 0, /*tp_repr*/
4904 0, /*tp_as_number*/
4905 0, /*tp_as_sequence*/
4906 0, /*tp_as_mapping*/
4907 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004908#ifdef HAVE_WEAKREF
4909 0, /* tp_call */
4910 0, /* tp_str */
4911 0, /* tp_getattro */
4912 0, /* tp_setattro */
4913 0, /* tp_as_buffer */
4914 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4915 0, /* tp_doc */
4916 0, /* tp_traverse */
4917 0, /* tp_clear */
4918 0, /* tp_richcompare */
4919 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4920#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004921};
4922
4923
4924/* --------------------------------------------------------------------- */
4925/* Module-level functions */
4926
4927static PyObject*
4928DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4929{
4930 PyObject* dbenvobj = NULL;
4931 int flags = 0;
4932 char* kwnames[] = { "dbEnv", "flags", NULL};
4933
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004934 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4935 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004936 return NULL;
4937 if (dbenvobj == Py_None)
4938 dbenvobj = NULL;
4939 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4940 makeTypeError("DBEnv", dbenvobj);
4941 return NULL;
4942 }
4943
4944 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4945}
4946
4947
4948static PyObject*
4949DBEnv_construct(PyObject* self, PyObject* args)
4950{
4951 int flags = 0;
4952 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4953 return (PyObject* )newDBEnvObject(flags);
4954}
4955
4956
4957static char bsddb_version_doc[] =
4958"Returns a tuple of major, minor, and patch release numbers of the\n\
4959underlying DB library.";
4960
4961static PyObject*
4962bsddb_version(PyObject* self, PyObject* args)
4963{
4964 int major, minor, patch;
4965
4966 if (!PyArg_ParseTuple(args, ":version"))
4967 return NULL;
4968 db_version(&major, &minor, &patch);
4969 return Py_BuildValue("(iii)", major, minor, patch);
4970}
4971
4972
4973/* List of functions defined in the module */
4974
4975static PyMethodDef bsddb_methods[] = {
4976 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4977 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4978 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4979 {NULL, NULL} /* sentinel */
4980};
4981
4982
4983/* --------------------------------------------------------------------- */
4984/* Module initialization */
4985
4986
4987/* Convenience routine to export an integer value.
4988 * Errors are silently ignored, for better or for worse...
4989 */
4990#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4991
Gregory P. Smith41631e82003-09-21 00:08:14 +00004992#define MODULE_NAME_MAX_LEN 11
4993static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004994
4995DL_EXPORT(void) init_bsddb(void)
4996{
4997 PyObject* m;
4998 PyObject* d;
4999 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5000 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5001 PyObject* cvsid_s = PyString_FromString( rcs_id );
5002
5003 /* Initialize the type of the new type objects here; doing it here
5004 is required for portability to Windows without requiring C++. */
5005 DB_Type.ob_type = &PyType_Type;
5006 DBCursor_Type.ob_type = &PyType_Type;
5007 DBEnv_Type.ob_type = &PyType_Type;
5008 DBTxn_Type.ob_type = &PyType_Type;
5009 DBLock_Type.ob_type = &PyType_Type;
5010
5011
Mark Hammonda69d4092003-04-22 23:13:27 +00005012#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005013 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005014 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005015#endif
5016
5017 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005018 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005019
5020 /* Add some symbolic constants to the module */
5021 d = PyModule_GetDict(m);
5022 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5023 PyDict_SetItemString(d, "cvsid", cvsid_s);
5024 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5025 Py_DECREF(pybsddb_version_s);
5026 pybsddb_version_s = NULL;
5027 Py_DECREF(cvsid_s);
5028 cvsid_s = NULL;
5029 Py_DECREF(db_version_s);
5030 db_version_s = NULL;
5031
5032 ADD_INT(d, DB_VERSION_MAJOR);
5033 ADD_INT(d, DB_VERSION_MINOR);
5034 ADD_INT(d, DB_VERSION_PATCH);
5035
5036 ADD_INT(d, DB_MAX_PAGES);
5037 ADD_INT(d, DB_MAX_RECORDS);
5038
Gregory P. Smith41631e82003-09-21 00:08:14 +00005039#if (DBVER >= 42)
5040 ADD_INT(d, DB_RPCCLIENT);
5041#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005042 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005043 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5044 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5045#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005046 ADD_INT(d, DB_XA_CREATE);
5047
5048 ADD_INT(d, DB_CREATE);
5049 ADD_INT(d, DB_NOMMAP);
5050 ADD_INT(d, DB_THREAD);
5051
5052 ADD_INT(d, DB_FORCE);
5053 ADD_INT(d, DB_INIT_CDB);
5054 ADD_INT(d, DB_INIT_LOCK);
5055 ADD_INT(d, DB_INIT_LOG);
5056 ADD_INT(d, DB_INIT_MPOOL);
5057 ADD_INT(d, DB_INIT_TXN);
5058#if (DBVER >= 32)
5059 ADD_INT(d, DB_JOINENV);
5060#endif
5061
5062 ADD_INT(d, DB_RECOVER);
5063 ADD_INT(d, DB_RECOVER_FATAL);
5064 ADD_INT(d, DB_TXN_NOSYNC);
5065 ADD_INT(d, DB_USE_ENVIRON);
5066 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5067
5068 ADD_INT(d, DB_LOCKDOWN);
5069 ADD_INT(d, DB_PRIVATE);
5070 ADD_INT(d, DB_SYSTEM_MEM);
5071
5072 ADD_INT(d, DB_TXN_SYNC);
5073 ADD_INT(d, DB_TXN_NOWAIT);
5074
5075 ADD_INT(d, DB_EXCL);
5076 ADD_INT(d, DB_FCNTL_LOCKING);
5077 ADD_INT(d, DB_ODDFILESIZE);
5078 ADD_INT(d, DB_RDWRMASTER);
5079 ADD_INT(d, DB_RDONLY);
5080 ADD_INT(d, DB_TRUNCATE);
5081#if (DBVER >= 32)
5082 ADD_INT(d, DB_EXTENT);
5083 ADD_INT(d, DB_CDB_ALLDB);
5084 ADD_INT(d, DB_VERIFY);
5085#endif
5086 ADD_INT(d, DB_UPGRADE);
5087
5088 ADD_INT(d, DB_AGGRESSIVE);
5089 ADD_INT(d, DB_NOORDERCHK);
5090 ADD_INT(d, DB_ORDERCHKONLY);
5091 ADD_INT(d, DB_PR_PAGE);
5092#if ! (DBVER >= 33)
5093 ADD_INT(d, DB_VRFY_FLAGMASK);
5094 ADD_INT(d, DB_PR_HEADERS);
5095#endif
5096 ADD_INT(d, DB_PR_RECOVERYTEST);
5097 ADD_INT(d, DB_SALVAGE);
5098
5099 ADD_INT(d, DB_LOCK_NORUN);
5100 ADD_INT(d, DB_LOCK_DEFAULT);
5101 ADD_INT(d, DB_LOCK_OLDEST);
5102 ADD_INT(d, DB_LOCK_RANDOM);
5103 ADD_INT(d, DB_LOCK_YOUNGEST);
5104#if (DBVER >= 33)
5105 ADD_INT(d, DB_LOCK_MAXLOCKS);
5106 ADD_INT(d, DB_LOCK_MINLOCKS);
5107 ADD_INT(d, DB_LOCK_MINWRITE);
5108#endif
5109
5110
5111#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005112 /* docs say to use zero instead */
5113 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005114#else
5115 ADD_INT(d, DB_LOCK_CONFLICT);
5116#endif
5117
5118 ADD_INT(d, DB_LOCK_DUMP);
5119 ADD_INT(d, DB_LOCK_GET);
5120 ADD_INT(d, DB_LOCK_INHERIT);
5121 ADD_INT(d, DB_LOCK_PUT);
5122 ADD_INT(d, DB_LOCK_PUT_ALL);
5123 ADD_INT(d, DB_LOCK_PUT_OBJ);
5124
5125 ADD_INT(d, DB_LOCK_NG);
5126 ADD_INT(d, DB_LOCK_READ);
5127 ADD_INT(d, DB_LOCK_WRITE);
5128 ADD_INT(d, DB_LOCK_NOWAIT);
5129#if (DBVER >= 32)
5130 ADD_INT(d, DB_LOCK_WAIT);
5131#endif
5132 ADD_INT(d, DB_LOCK_IWRITE);
5133 ADD_INT(d, DB_LOCK_IREAD);
5134 ADD_INT(d, DB_LOCK_IWR);
5135#if (DBVER >= 33)
5136 ADD_INT(d, DB_LOCK_DIRTY);
5137 ADD_INT(d, DB_LOCK_WWRITE);
5138#endif
5139
5140 ADD_INT(d, DB_LOCK_RECORD);
5141 ADD_INT(d, DB_LOCK_UPGRADE);
5142#if (DBVER >= 32)
5143 ADD_INT(d, DB_LOCK_SWITCH);
5144#endif
5145#if (DBVER >= 33)
5146 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5147#endif
5148
5149 ADD_INT(d, DB_LOCK_NOWAIT);
5150 ADD_INT(d, DB_LOCK_RECORD);
5151 ADD_INT(d, DB_LOCK_UPGRADE);
5152
5153#if (DBVER >= 33)
5154 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005155#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005156 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005157#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 ADD_INT(d, DB_LSTAT_FREE);
5159 ADD_INT(d, DB_LSTAT_HELD);
5160#if (DBVER == 33)
5161 ADD_INT(d, DB_LSTAT_NOGRANT);
5162#endif
5163 ADD_INT(d, DB_LSTAT_PENDING);
5164 ADD_INT(d, DB_LSTAT_WAITING);
5165#endif
5166
5167 ADD_INT(d, DB_ARCH_ABS);
5168 ADD_INT(d, DB_ARCH_DATA);
5169 ADD_INT(d, DB_ARCH_LOG);
5170
5171 ADD_INT(d, DB_BTREE);
5172 ADD_INT(d, DB_HASH);
5173 ADD_INT(d, DB_RECNO);
5174 ADD_INT(d, DB_QUEUE);
5175 ADD_INT(d, DB_UNKNOWN);
5176
5177 ADD_INT(d, DB_DUP);
5178 ADD_INT(d, DB_DUPSORT);
5179 ADD_INT(d, DB_RECNUM);
5180 ADD_INT(d, DB_RENUMBER);
5181 ADD_INT(d, DB_REVSPLITOFF);
5182 ADD_INT(d, DB_SNAPSHOT);
5183
5184 ADD_INT(d, DB_JOIN_NOSORT);
5185
5186 ADD_INT(d, DB_AFTER);
5187 ADD_INT(d, DB_APPEND);
5188 ADD_INT(d, DB_BEFORE);
5189 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005190#if (DBVER >= 41)
5191 _addIntToDict(d, "DB_CHECKPOINT", 0);
5192#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005193 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005194 ADD_INT(d, DB_CURLSN);
5195#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005196#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005197 ADD_INT(d, DB_COMMIT);
5198#endif
5199 ADD_INT(d, DB_CONSUME);
5200#if (DBVER >= 32)
5201 ADD_INT(d, DB_CONSUME_WAIT);
5202#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005203 ADD_INT(d, DB_CURRENT);
5204#if (DBVER >= 33)
5205 ADD_INT(d, DB_FAST_STAT);
5206#endif
5207 ADD_INT(d, DB_FIRST);
5208 ADD_INT(d, DB_FLUSH);
5209 ADD_INT(d, DB_GET_BOTH);
5210 ADD_INT(d, DB_GET_RECNO);
5211 ADD_INT(d, DB_JOIN_ITEM);
5212 ADD_INT(d, DB_KEYFIRST);
5213 ADD_INT(d, DB_KEYLAST);
5214 ADD_INT(d, DB_LAST);
5215 ADD_INT(d, DB_NEXT);
5216 ADD_INT(d, DB_NEXT_DUP);
5217 ADD_INT(d, DB_NEXT_NODUP);
5218 ADD_INT(d, DB_NODUPDATA);
5219 ADD_INT(d, DB_NOOVERWRITE);
5220 ADD_INT(d, DB_NOSYNC);
5221 ADD_INT(d, DB_POSITION);
5222 ADD_INT(d, DB_PREV);
5223 ADD_INT(d, DB_PREV_NODUP);
5224 ADD_INT(d, DB_RECORDCOUNT);
5225 ADD_INT(d, DB_SET);
5226 ADD_INT(d, DB_SET_RANGE);
5227 ADD_INT(d, DB_SET_RECNO);
5228 ADD_INT(d, DB_WRITECURSOR);
5229
5230 ADD_INT(d, DB_OPFLAGS_MASK);
5231 ADD_INT(d, DB_RMW);
5232#if (DBVER >= 33)
5233 ADD_INT(d, DB_DIRTY_READ);
5234 ADD_INT(d, DB_MULTIPLE);
5235 ADD_INT(d, DB_MULTIPLE_KEY);
5236#endif
5237
5238#if (DBVER >= 33)
5239 ADD_INT(d, DB_DONOTINDEX);
5240#endif
5241
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005242#if (DBVER >= 41)
5243 _addIntToDict(d, "DB_INCOMPLETE", 0);
5244#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005245 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005246#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005247 ADD_INT(d, DB_KEYEMPTY);
5248 ADD_INT(d, DB_KEYEXIST);
5249 ADD_INT(d, DB_LOCK_DEADLOCK);
5250 ADD_INT(d, DB_LOCK_NOTGRANTED);
5251 ADD_INT(d, DB_NOSERVER);
5252 ADD_INT(d, DB_NOSERVER_HOME);
5253 ADD_INT(d, DB_NOSERVER_ID);
5254 ADD_INT(d, DB_NOTFOUND);
5255 ADD_INT(d, DB_OLD_VERSION);
5256 ADD_INT(d, DB_RUNRECOVERY);
5257 ADD_INT(d, DB_VERIFY_BAD);
5258#if (DBVER >= 33)
5259 ADD_INT(d, DB_PAGE_NOTFOUND);
5260 ADD_INT(d, DB_SECONDARY_BAD);
5261#endif
5262#if (DBVER >= 40)
5263 ADD_INT(d, DB_STAT_CLEAR);
5264 ADD_INT(d, DB_REGION_INIT);
5265 ADD_INT(d, DB_NOLOCKING);
5266 ADD_INT(d, DB_YIELDCPU);
5267 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5268 ADD_INT(d, DB_NOPANIC);
5269#endif
5270
Gregory P. Smith41631e82003-09-21 00:08:14 +00005271#if (DBVER >= 42)
5272 ADD_INT(d, DB_TIME_NOTGRANTED);
5273 ADD_INT(d, DB_TXN_NOT_DURABLE);
5274 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5275 ADD_INT(d, DB_LOG_AUTOREMOVE);
5276 ADD_INT(d, DB_DIRECT_LOG);
5277 ADD_INT(d, DB_DIRECT_DB);
5278 ADD_INT(d, DB_INIT_REP);
5279 ADD_INT(d, DB_ENCRYPT);
5280 ADD_INT(d, DB_CHKSUM);
5281#endif
5282
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005283#if (DBVER >= 43)
5284 ADD_INT(d, DB_LOG_INMEMORY);
5285 ADD_INT(d, DB_BUFFER_SMALL);
5286#endif
5287
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005288#if (DBVER >= 41)
5289 ADD_INT(d, DB_ENCRYPT_AES);
5290 ADD_INT(d, DB_AUTO_COMMIT);
5291#else
5292 /* allow berkeleydb 4.1 aware apps to run on older versions */
5293 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5294#endif
5295
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005296 ADD_INT(d, EINVAL);
5297 ADD_INT(d, EACCES);
5298 ADD_INT(d, ENOSPC);
5299 ADD_INT(d, ENOMEM);
5300 ADD_INT(d, EAGAIN);
5301 ADD_INT(d, EBUSY);
5302 ADD_INT(d, EEXIST);
5303 ADD_INT(d, ENOENT);
5304 ADD_INT(d, EPERM);
5305
Barry Warsaw1baa9822003-03-31 19:51:29 +00005306#if (DBVER >= 40)
5307 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5308 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5309#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005310
5311 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005312 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005313 PyDict_SetItemString(d, "DBError", DBError);
5314
Gregory P. Smithe9477062005-06-04 06:46:59 +00005315 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5316 * from both DBError and KeyError, since the API only supports
5317 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005318 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005319 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5320 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005321 Py_file_input, d, d);
5322 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005323 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005324 PyDict_DelItemString(d, "KeyError");
5325
5326
5327 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005328#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005329 PyDict_SetItemString(d, #name, name)
5330
5331#if !INCOMPLETE_IS_WARNING
5332 MAKE_EX(DBIncompleteError);
5333#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005334 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005335 MAKE_EX(DBKeyEmptyError);
5336 MAKE_EX(DBKeyExistError);
5337 MAKE_EX(DBLockDeadlockError);
5338 MAKE_EX(DBLockNotGrantedError);
5339 MAKE_EX(DBOldVersionError);
5340 MAKE_EX(DBRunRecoveryError);
5341 MAKE_EX(DBVerifyBadError);
5342 MAKE_EX(DBNoServerError);
5343 MAKE_EX(DBNoServerHomeError);
5344 MAKE_EX(DBNoServerIDError);
5345#if (DBVER >= 33)
5346 MAKE_EX(DBPageNotFoundError);
5347 MAKE_EX(DBSecondaryBadError);
5348#endif
5349
5350 MAKE_EX(DBInvalidArgError);
5351 MAKE_EX(DBAccessError);
5352 MAKE_EX(DBNoSpaceError);
5353 MAKE_EX(DBNoMemoryError);
5354 MAKE_EX(DBAgainError);
5355 MAKE_EX(DBBusyError);
5356 MAKE_EX(DBFileExistsError);
5357 MAKE_EX(DBNoSuchFileError);
5358 MAKE_EX(DBPermissionsError);
5359
5360#undef MAKE_EX
5361
5362 /* Check for errors */
5363 if (PyErr_Occurred()) {
5364 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005365 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005366 }
5367}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005368
5369/* allow this module to be named _pybsddb so that it can be installed
5370 * and imported on top of python >= 2.3 that includes its own older
5371 * copy of the library named _bsddb without importing the old version. */
5372DL_EXPORT(void) init_pybsddb(void)
5373{
5374 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5375 init_bsddb();
5376}