blob: 6f4da7ee61615ebd9dc070a8cb1a31f731fb3278 [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;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000653 static const char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000654
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;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001150 static const char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1151 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001152#else
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001153 static const char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001154#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001155
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001156#if (DBVER >= 41)
1157 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1158 &secondaryDB, &callback, &flags,
1159 &txnobj)) {
1160#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001162 &secondaryDB, &callback, &flags)) {
1163#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001164 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001165 }
1166
1167#if (DBVER >= 41)
1168 if (!checkTxnObj(txnobj, &txn)) return NULL;
1169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170
1171 CHECK_DB_NOT_CLOSED(self);
1172 if (!DBObject_Check(secondaryDB)) {
1173 makeTypeError("DB", (PyObject*)secondaryDB);
1174 return NULL;
1175 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001176 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177 if (callback == Py_None) {
1178 callback = NULL;
1179 }
1180 else if (!PyCallable_Check(callback)) {
1181 makeTypeError("Callable", callback);
1182 return NULL;
1183 }
1184
1185 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001186 Py_XDECREF(secondaryDB->associateCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001187 Py_INCREF(callback);
1188 secondaryDB->associateCallback = callback;
1189 secondaryDB->primaryDBType = _DB_get_type(self);
1190
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001191 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1192 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1193 * The global interepreter lock is not initialized until the first
1194 * thread is created using thread.start_new_thread() or fork() is
1195 * called. that would cause the ALLOW_THREADS here to segfault due
1196 * to a null pointer reference if no threads or child processes
1197 * have been created. This works around that and is a no-op if
1198 * threads have already been initialized.
1199 * (see pybsddb-users mailing list post on 2002-08-07)
1200 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001201#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001202 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001203#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001204 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001205#if (DBVER >= 41)
1206 err = self->db->associate(self->db,
1207 txn,
1208 secondaryDB->db,
1209 _db_associateCallback,
1210 flags);
1211#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001212 err = self->db->associate(self->db,
1213 secondaryDB->db,
1214 _db_associateCallback,
1215 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001216#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001217 MYDB_END_ALLOW_THREADS;
1218
1219 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001220 Py_XDECREF(secondaryDB->associateCallback);
1221 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001222 secondaryDB->primaryDBType = 0;
1223 }
1224
1225 RETURN_IF_ERR();
1226 RETURN_NONE();
1227}
1228
1229
1230#endif
1231
1232
1233static PyObject*
1234DB_close(DBObject* self, PyObject* args)
1235{
1236 int err, flags=0;
1237 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1238 return NULL;
1239 if (self->db != NULL) {
1240 if (self->myenvobj)
1241 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001243 self->db = NULL;
1244 RETURN_IF_ERR();
1245 }
1246 RETURN_NONE();
1247}
1248
1249
1250#if (DBVER >= 32)
1251static PyObject*
1252_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1253{
1254 int err, flags=0, type;
1255 PyObject* txnobj = NULL;
1256 PyObject* retval = NULL;
1257 DBT key, data;
1258 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001259 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260
1261 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1262 &txnobj, &flags))
1263 return NULL;
1264
1265 CHECK_DB_NOT_CLOSED(self);
1266 type = _DB_get_type(self);
1267 if (type == -1)
1268 return NULL;
1269 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001270 PyErr_SetString(PyExc_TypeError,
1271 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 return NULL;
1273 }
1274 if (!checkTxnObj(txnobj, &txn))
1275 return NULL;
1276
1277 CLEAR_DBT(key);
1278 CLEAR_DBT(data);
1279 if (CHECK_DBFLAG(self, DB_THREAD)) {
1280 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1281 data.flags = DB_DBT_MALLOC;
1282 key.flags = DB_DBT_MALLOC;
1283 }
1284
1285 MYDB_BEGIN_ALLOW_THREADS;
1286 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1287 MYDB_END_ALLOW_THREADS;
1288
Gregory P. Smithe9477062005-06-04 06:46:59 +00001289 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1290 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291 err = 0;
1292 Py_INCREF(Py_None);
1293 retval = Py_None;
1294 }
1295 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001296 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1297 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 FREE_DBT(key);
1299 FREE_DBT(data);
1300 }
1301
1302 RETURN_IF_ERR();
1303 return retval;
1304}
1305
1306static PyObject*
1307DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1308{
1309 return _DB_consume(self, args, kwargs, DB_CONSUME);
1310}
1311
1312static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001313DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1314 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315{
1316 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1317}
1318#endif
1319
1320
1321
1322static PyObject*
1323DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1324{
1325 int err, flags=0;
1326 DBC* dbc;
1327 PyObject* txnobj = NULL;
1328 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001329 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001330
1331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1332 &txnobj, &flags))
1333 return NULL;
1334 CHECK_DB_NOT_CLOSED(self);
1335 if (!checkTxnObj(txnobj, &txn))
1336 return NULL;
1337
1338 MYDB_BEGIN_ALLOW_THREADS;
1339 err = self->db->cursor(self->db, txn, &dbc, flags);
1340 MYDB_END_ALLOW_THREADS;
1341 RETURN_IF_ERR();
1342 return (PyObject*) newDBCursorObject(dbc, self);
1343}
1344
1345
1346static PyObject*
1347DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1348{
1349 PyObject* txnobj = NULL;
1350 int flags = 0;
1351 PyObject* keyobj;
1352 DBT key;
1353 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001354 static const char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001355
1356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1357 &keyobj, &txnobj, &flags))
1358 return NULL;
1359 CHECK_DB_NOT_CLOSED(self);
1360 if (!make_key_dbt(self, keyobj, &key, NULL))
1361 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001362 if (!checkTxnObj(txnobj, &txn)) {
1363 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001365 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001367 if (-1 == _DB_delete(self, txn, &key, 0)) {
1368 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001370 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371
1372 FREE_DBT(key);
1373 RETURN_NONE();
1374}
1375
1376
1377static PyObject*
1378DB_fd(DBObject* self, PyObject* args)
1379{
1380 int err, the_fd;
1381
1382 if (!PyArg_ParseTuple(args,":fd"))
1383 return NULL;
1384 CHECK_DB_NOT_CLOSED(self);
1385
1386 MYDB_BEGIN_ALLOW_THREADS;
1387 err = self->db->fd(self->db, &the_fd);
1388 MYDB_END_ALLOW_THREADS;
1389 RETURN_IF_ERR();
1390 return PyInt_FromLong(the_fd);
1391}
1392
1393
1394static PyObject*
1395DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1396{
1397 int err, flags=0;
1398 PyObject* txnobj = NULL;
1399 PyObject* keyobj;
1400 PyObject* dfltobj = NULL;
1401 PyObject* retval = NULL;
1402 int dlen = -1;
1403 int doff = -1;
1404 DBT key, data;
1405 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001406 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1407 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001408
1409 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001410 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1411 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412 return NULL;
1413
1414 CHECK_DB_NOT_CLOSED(self);
1415 if (!make_key_dbt(self, keyobj, &key, &flags))
1416 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001417 if (!checkTxnObj(txnobj, &txn)) {
1418 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001420 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421
1422 CLEAR_DBT(data);
1423 if (CHECK_DBFLAG(self, DB_THREAD)) {
1424 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1425 data.flags = DB_DBT_MALLOC;
1426 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001427 if (!add_partial_dbt(&data, dlen, doff)) {
1428 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001430 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431
1432 MYDB_BEGIN_ALLOW_THREADS;
1433 err = self->db->get(self->db, txn, &key, &data, flags);
1434 MYDB_END_ALLOW_THREADS;
1435
Gregory P. Smithe9477062005-06-04 06:46:59 +00001436 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437 err = 0;
1438 Py_INCREF(dfltobj);
1439 retval = dfltobj;
1440 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001441 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1442 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443 err = 0;
1444 Py_INCREF(Py_None);
1445 retval = Py_None;
1446 }
1447 else if (!err) {
1448 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001449 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1450 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001451 else /* return just the data */
1452 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001453 FREE_DBT(data);
1454 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001455 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456
1457 RETURN_IF_ERR();
1458 return retval;
1459}
1460
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001461#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001462static PyObject*
1463DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1464{
1465 int err, flags=0;
1466 PyObject* txnobj = NULL;
1467 PyObject* keyobj;
1468 PyObject* dfltobj = NULL;
1469 PyObject* retval = NULL;
1470 int dlen = -1;
1471 int doff = -1;
1472 DBT key, pkey, data;
1473 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001474 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1475 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001476
1477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1478 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1479 &doff))
1480 return NULL;
1481
1482 CHECK_DB_NOT_CLOSED(self);
1483 if (!make_key_dbt(self, keyobj, &key, &flags))
1484 return NULL;
1485 if (!checkTxnObj(txnobj, &txn)) {
1486 FREE_DBT(key);
1487 return NULL;
1488 }
1489
1490 CLEAR_DBT(data);
1491 if (CHECK_DBFLAG(self, DB_THREAD)) {
1492 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1493 data.flags = DB_DBT_MALLOC;
1494 }
1495 if (!add_partial_dbt(&data, dlen, doff)) {
1496 FREE_DBT(key);
1497 return NULL;
1498 }
1499
1500 CLEAR_DBT(pkey);
1501 pkey.flags = DB_DBT_MALLOC;
1502
1503 MYDB_BEGIN_ALLOW_THREADS;
1504 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1505 MYDB_END_ALLOW_THREADS;
1506
Gregory P. Smithe9477062005-06-04 06:46:59 +00001507 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001508 err = 0;
1509 Py_INCREF(dfltobj);
1510 retval = dfltobj;
1511 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001512 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1513 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001514 err = 0;
1515 Py_INCREF(Py_None);
1516 retval = Py_None;
1517 }
1518 else if (!err) {
1519 PyObject *pkeyObj;
1520 PyObject *dataObj;
1521 dataObj = PyString_FromStringAndSize(data.data, data.size);
1522
1523 if (self->primaryDBType == DB_RECNO ||
1524 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001525 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001526 else
1527 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1528
1529 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1530 {
1531 PyObject *keyObj;
1532 int type = _DB_get_type(self);
1533 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001534 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001535 else
1536 keyObj = PyString_FromStringAndSize(key.data, key.size);
1537 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1538 }
1539 else /* return just the pkey and data */
1540 {
1541 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1542 }
1543 FREE_DBT(pkey);
1544 FREE_DBT(data);
1545 }
1546 FREE_DBT(key);
1547
1548 RETURN_IF_ERR();
1549 return retval;
1550}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001551#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001552
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001553
1554/* Return size of entry */
1555static PyObject*
1556DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1557{
1558 int err, flags=0;
1559 PyObject* txnobj = NULL;
1560 PyObject* keyobj;
1561 PyObject* retval = NULL;
1562 DBT key, data;
1563 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001564 static const char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001565
1566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1567 &keyobj, &txnobj))
1568 return NULL;
1569 CHECK_DB_NOT_CLOSED(self);
1570 if (!make_key_dbt(self, keyobj, &key, &flags))
1571 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001572 if (!checkTxnObj(txnobj, &txn)) {
1573 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001574 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001575 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001576 CLEAR_DBT(data);
1577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001578 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1579 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001580 data.flags = DB_DBT_USERMEM;
1581 data.ulen = 0;
1582 MYDB_BEGIN_ALLOW_THREADS;
1583 err = self->db->get(self->db, txn, &key, &data, flags);
1584 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001585 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001586 retval = PyInt_FromLong((long)data.size);
1587 err = 0;
1588 }
1589
1590 FREE_DBT(key);
1591 FREE_DBT(data);
1592 RETURN_IF_ERR();
1593 return retval;
1594}
1595
1596
1597static PyObject*
1598DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1599{
1600 int err, flags=0;
1601 PyObject* txnobj = NULL;
1602 PyObject* keyobj;
1603 PyObject* dataobj;
1604 PyObject* retval = NULL;
1605 DBT key, data;
1606 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001607 static const char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001608
1609
1610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1611 &keyobj, &dataobj, &txnobj, &flags))
1612 return NULL;
1613
1614 CHECK_DB_NOT_CLOSED(self);
1615 if (!make_key_dbt(self, keyobj, &key, NULL))
1616 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001617 if ( !make_dbt(dataobj, &data) ||
1618 !checkTxnObj(txnobj, &txn) )
1619 {
1620 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001621 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001622 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001623
1624 flags |= DB_GET_BOTH;
1625
1626 if (CHECK_DBFLAG(self, DB_THREAD)) {
1627 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1628 data.flags = DB_DBT_MALLOC;
1629 /* TODO: Is this flag needed? We're passing a data object that should
1630 match what's in the DB, so there should be no need to malloc.
1631 We run the risk of freeing something twice! Check this. */
1632 }
1633
1634 MYDB_BEGIN_ALLOW_THREADS;
1635 err = self->db->get(self->db, txn, &key, &data, flags);
1636 MYDB_END_ALLOW_THREADS;
1637
Gregory P. Smithe9477062005-06-04 06:46:59 +00001638 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1639 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 err = 0;
1641 Py_INCREF(Py_None);
1642 retval = Py_None;
1643 }
1644 else if (!err) {
1645 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1646 FREE_DBT(data); /* Only if retrieval was successful */
1647 }
1648
1649 FREE_DBT(key);
1650 RETURN_IF_ERR();
1651 return retval;
1652}
1653
1654
1655static PyObject*
1656DB_get_byteswapped(DBObject* self, PyObject* args)
1657{
1658#if (DBVER >= 33)
1659 int err = 0;
1660#endif
1661 int retval = -1;
1662
1663 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1664 return NULL;
1665 CHECK_DB_NOT_CLOSED(self);
1666
1667#if (DBVER >= 33)
1668 MYDB_BEGIN_ALLOW_THREADS;
1669 err = self->db->get_byteswapped(self->db, &retval);
1670 MYDB_END_ALLOW_THREADS;
1671 RETURN_IF_ERR();
1672#else
1673 MYDB_BEGIN_ALLOW_THREADS;
1674 retval = self->db->get_byteswapped(self->db);
1675 MYDB_END_ALLOW_THREADS;
1676#endif
1677 return PyInt_FromLong(retval);
1678}
1679
1680
1681static PyObject*
1682DB_get_type(DBObject* self, PyObject* args)
1683{
1684 int type;
1685
1686 if (!PyArg_ParseTuple(args,":get_type"))
1687 return NULL;
1688 CHECK_DB_NOT_CLOSED(self);
1689
1690 MYDB_BEGIN_ALLOW_THREADS;
1691 type = _DB_get_type(self);
1692 MYDB_END_ALLOW_THREADS;
1693 if (type == -1)
1694 return NULL;
1695 return PyInt_FromLong(type);
1696}
1697
1698
1699static PyObject*
1700DB_join(DBObject* self, PyObject* args)
1701{
1702 int err, flags=0;
1703 int length, x;
1704 PyObject* cursorsObj;
1705 DBC** cursors;
1706 DBC* dbc;
1707
1708
1709 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1710 return NULL;
1711
1712 CHECK_DB_NOT_CLOSED(self);
1713
1714 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001715 PyErr_SetString(PyExc_TypeError,
1716 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717 return NULL;
1718 }
1719
1720 length = PyObject_Length(cursorsObj);
1721 cursors = malloc((length+1) * sizeof(DBC*));
1722 cursors[length] = NULL;
1723 for (x=0; x<length; x++) {
1724 PyObject* item = PySequence_GetItem(cursorsObj, x);
1725 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001726 PyErr_SetString(PyExc_TypeError,
1727 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728 free(cursors);
1729 return NULL;
1730 }
1731 cursors[x] = ((DBCursorObject*)item)->dbc;
1732 }
1733
1734 MYDB_BEGIN_ALLOW_THREADS;
1735 err = self->db->join(self->db, cursors, &dbc, flags);
1736 MYDB_END_ALLOW_THREADS;
1737 free(cursors);
1738 RETURN_IF_ERR();
1739
Gregory P. Smith7441e652003-11-03 21:35:31 +00001740 /* FIXME: this is a buggy interface. The returned cursor
1741 contains internal references to the passed in cursors
1742 but does not hold python references to them or prevent
1743 them from being closed prematurely. This can cause
1744 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 return (PyObject*) newDBCursorObject(dbc, self);
1746}
1747
1748
1749static PyObject*
1750DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1751{
1752 int err, flags=0;
1753 PyObject* txnobj = NULL;
1754 PyObject* keyobj;
1755 DBT key;
1756 DB_TXN *txn = NULL;
1757 DB_KEY_RANGE range;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001758 static const char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001759
1760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1761 &keyobj, &txnobj, &flags))
1762 return NULL;
1763 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001764 if (!make_dbt(keyobj, &key))
1765 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001766 return NULL;
1767 if (!checkTxnObj(txnobj, &txn))
1768 return NULL;
1769
1770 MYDB_BEGIN_ALLOW_THREADS;
1771 err = self->db->key_range(self->db, txn, &key, &range, flags);
1772 MYDB_END_ALLOW_THREADS;
1773
1774 RETURN_IF_ERR();
1775 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1776}
1777
1778
1779static PyObject*
1780DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1781{
1782 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1783 char* filename = NULL;
1784 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001785#if (DBVER >= 41)
1786 PyObject *txnobj = NULL;
1787 DB_TXN *txn = NULL;
1788 /* with dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001789 static const char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001790 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1791 /* without dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001792 static const char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001793 "filename", "dbtype", "flags", "mode", "txn", NULL};
1794#else
1795 /* with dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001796 static const char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001797 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1798 /* without dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001799 static const char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001800 "filename", "dbtype", "flags", "mode", NULL};
1801#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001803#if (DBVER >= 41)
1804 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1805 &filename, &dbname, &type, &flags, &mode,
1806 &txnobj))
1807#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001809 &filename, &dbname, &type, &flags,
1810 &mode))
1811#endif
1812 {
1813 PyErr_Clear();
1814 type = DB_UNKNOWN; flags = 0; mode = 0660;
1815 filename = NULL; dbname = NULL;
1816#if (DBVER >= 41)
1817 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1818 kwnames_basic,
1819 &filename, &type, &flags, &mode,
1820 &txnobj))
1821 return NULL;
1822#else
1823 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1824 kwnames_basic,
1825 &filename, &type, &flags, &mode))
1826 return NULL;
1827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 }
1829
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001830#if (DBVER >= 41)
1831 if (!checkTxnObj(txnobj, &txn)) return NULL;
1832#endif
1833
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 if (NULL == self->db) {
1835 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1836 "Cannot call open() twice for DB object"));
1837 return NULL;
1838 }
1839
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001840#if 0 && (DBVER >= 41)
1841 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1842 && (self->myenvobj->flags & DB_INIT_TXN))
1843 {
1844 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1845 * explicitly passed) but we are in a transaction ready environment:
1846 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1847 * to work on BerkeleyDB 4.1 without needing to modify their
1848 * DBEnv or DB open calls.
1849 * TODO make this behaviour of the library configurable.
1850 */
1851 flags |= DB_AUTO_COMMIT;
1852 }
1853#endif
1854
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001856#if (DBVER >= 41)
1857 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1858#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001860#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 MYDB_END_ALLOW_THREADS;
1862 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001863 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001864 self->db = NULL;
1865 return NULL;
1866 }
1867
1868 self->flags = flags;
1869 RETURN_NONE();
1870}
1871
1872
1873static PyObject*
1874DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1875{
1876 int flags=0;
1877 PyObject* txnobj = NULL;
1878 int dlen = -1;
1879 int doff = -1;
1880 PyObject* keyobj, *dataobj, *retval;
1881 DBT key, data;
1882 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001883 static const char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1884 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001885
1886 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1887 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1888 return NULL;
1889
1890 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001891 if (!make_key_dbt(self, keyobj, &key, NULL))
1892 return NULL;
1893 if ( !make_dbt(dataobj, &data) ||
1894 !add_partial_dbt(&data, dlen, doff) ||
1895 !checkTxnObj(txnobj, &txn) )
1896 {
1897 FREE_DBT(key);
1898 return NULL;
1899 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001900
1901 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1902 FREE_DBT(key);
1903 return NULL;
1904 }
1905
1906 if (flags & DB_APPEND)
1907 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1908 else {
1909 retval = Py_None;
1910 Py_INCREF(retval);
1911 }
1912 FREE_DBT(key);
1913 return retval;
1914}
1915
1916
1917
1918static PyObject*
1919DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1920{
1921 char* filename;
1922 char* database = NULL;
1923 int err, flags=0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001924 static const char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001925
1926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1927 &filename, &database, &flags))
1928 return NULL;
1929 CHECK_DB_NOT_CLOSED(self);
1930
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001931 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001932 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001933 RETURN_IF_ERR();
1934 RETURN_NONE();
1935}
1936
1937
1938
1939static PyObject*
1940DB_rename(DBObject* self, PyObject* args)
1941{
1942 char* filename;
1943 char* database;
1944 char* newname;
1945 int err, flags=0;
1946
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001947 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1948 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 return NULL;
1950 CHECK_DB_NOT_CLOSED(self);
1951
1952 MYDB_BEGIN_ALLOW_THREADS;
1953 err = self->db->rename(self->db, filename, database, newname, flags);
1954 MYDB_END_ALLOW_THREADS;
1955 RETURN_IF_ERR();
1956 RETURN_NONE();
1957}
1958
1959
1960static PyObject*
1961DB_set_bt_minkey(DBObject* self, PyObject* args)
1962{
1963 int err, minkey;
1964
1965 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1966 return NULL;
1967 CHECK_DB_NOT_CLOSED(self);
1968
1969 MYDB_BEGIN_ALLOW_THREADS;
1970 err = self->db->set_bt_minkey(self->db, minkey);
1971 MYDB_END_ALLOW_THREADS;
1972 RETURN_IF_ERR();
1973 RETURN_NONE();
1974}
1975
Neal Norwitz84562352005-10-20 04:30:15 +00001976#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001977static int
1978_default_cmp (const DBT *leftKey,
1979 const DBT *rightKey)
1980{
1981 int res;
1982 int lsize = leftKey->size, rsize = rightKey->size;
1983
1984 res = memcmp (leftKey->data, rightKey->data,
1985 lsize < rsize ? lsize : rsize);
1986
1987 if (res == 0) {
1988 if (lsize < rsize) {
1989 res = -1;
1990 }
1991 else if (lsize > rsize) {
1992 res = 1;
1993 }
1994 }
1995 return res;
1996}
1997
1998static int
1999_db_compareCallback (DB* db,
2000 const DBT *leftKey,
2001 const DBT *rightKey)
2002{
2003 int res = 0;
2004 PyObject *args;
2005 PyObject *result;
2006 PyObject *leftObject;
2007 PyObject *rightObject;
2008 DBObject *self = (DBObject *) db->app_private;
2009
2010 if (self == NULL || self->btCompareCallback == NULL) {
2011 MYDB_BEGIN_BLOCK_THREADS;
2012 PyErr_SetString (PyExc_TypeError,
2013 (self == 0
2014 ? "DB_bt_compare db is NULL."
2015 : "DB_bt_compare callback is NULL."));
2016 /* we're in a callback within the DB code, we can't raise */
2017 PyErr_Print ();
2018 res = _default_cmp (leftKey, rightKey);
2019 MYDB_END_BLOCK_THREADS;
2020 }
2021 else {
2022 MYDB_BEGIN_BLOCK_THREADS;
2023
2024 leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size);
2025 rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size);
2026
Gregory P. Smithac741c52005-06-06 17:31:32 +00002027 args = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002028 Py_INCREF (self);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002029 PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */
2030 PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002031
2032 result = PyEval_CallObject (self->btCompareCallback, args);
2033 if (result == 0) {
2034 /* we're in a callback within the DB code, we can't raise */
Gregory P. Smith8966d3d2005-06-16 19:01:42 +00002035 PyErr_Print ();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002036 res = _default_cmp (leftKey, rightKey);
2037 }
2038 else if (PyInt_Check (result)) {
2039 res = PyInt_AsLong (result);
2040 }
2041 else {
2042 PyErr_SetString (PyExc_TypeError,
2043 "DB_bt_compare callback MUST return an int.");
2044 /* we're in a callback within the DB code, we can't raise */
2045 PyErr_Print ();
2046 res = _default_cmp (leftKey, rightKey);
2047 }
2048
2049 Py_DECREF (args);
2050 Py_XDECREF (result);
2051
2052 MYDB_END_BLOCK_THREADS;
2053 }
2054 return res;
2055}
2056
2057static PyObject*
2058DB_set_bt_compare (DBObject* self, PyObject* args)
2059{
2060 int err;
2061 PyObject *comparator;
2062 PyObject *tuple, *emptyStr, *result;
2063
2064 if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator ))
2065 return NULL;
2066
2067 CHECK_DB_NOT_CLOSED (self);
2068
2069 if (! PyCallable_Check (comparator)) {
2070 makeTypeError ("Callable", comparator);
2071 return NULL;
2072 }
2073
2074 /*
2075 * Perform a test call of the comparator function with two empty
2076 * string objects here. verify that it returns an int (0).
2077 * err if not.
2078 */
Gregory P. Smithac741c52005-06-06 17:31:32 +00002079 tuple = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080
2081 emptyStr = PyString_FromStringAndSize (NULL, 0);
2082 Py_INCREF(emptyStr);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002083 PyTuple_SET_ITEM (tuple, 0, emptyStr);
2084 PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002085 result = PyEval_CallObject (comparator, tuple);
2086 Py_DECREF (tuple);
2087 if (result == 0 || !PyInt_Check(result)) {
2088 PyErr_SetString (PyExc_TypeError,
2089 "callback MUST return an int");
2090 return NULL;
2091 }
2092 else if (PyInt_AsLong(result) != 0) {
2093 PyErr_SetString (PyExc_TypeError,
2094 "callback failed to return 0 on two empty strings");
2095 return NULL;
2096 }
2097
2098 /* We don't accept multiple set_bt_compare operations, in order to
2099 * simplify the code. This would have no real use, as one cannot
2100 * change the function once the db is opened anyway */
2101 if (self->btCompareCallback != NULL) {
2102 PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once");
2103 return NULL;
2104 }
2105
2106 Py_INCREF (comparator);
2107 self->btCompareCallback = comparator;
2108
2109 /* This is to workaround a problem with un-initialized threads (see
2110 comment in DB_associate) */
2111#ifdef WITH_THREAD
2112 PyEval_InitThreads();
2113#endif
2114
2115 err = self->db->set_bt_compare (self->db,
2116 (comparator != NULL ?
2117 _db_compareCallback : NULL));
2118
2119 if (err) {
2120 /* restore the old state in case of error */
2121 Py_DECREF (comparator);
2122 self->btCompareCallback = NULL;
2123 }
2124
2125 RETURN_IF_ERR ();
2126 RETURN_NONE ();
2127}
Neal Norwitz84562352005-10-20 04:30:15 +00002128#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002129
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002130
2131static PyObject*
2132DB_set_cachesize(DBObject* self, PyObject* args)
2133{
2134 int err;
2135 int gbytes = 0, bytes = 0, ncache = 0;
2136
2137 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2138 &gbytes,&bytes,&ncache))
2139 return NULL;
2140 CHECK_DB_NOT_CLOSED(self);
2141
2142 MYDB_BEGIN_ALLOW_THREADS;
2143 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2144 MYDB_END_ALLOW_THREADS;
2145 RETURN_IF_ERR();
2146 RETURN_NONE();
2147}
2148
2149
2150static PyObject*
2151DB_set_flags(DBObject* self, PyObject* args)
2152{
2153 int err, flags;
2154
2155 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2156 return NULL;
2157 CHECK_DB_NOT_CLOSED(self);
2158
2159 MYDB_BEGIN_ALLOW_THREADS;
2160 err = self->db->set_flags(self->db, flags);
2161 MYDB_END_ALLOW_THREADS;
2162 RETURN_IF_ERR();
2163
2164 self->setflags |= flags;
2165 RETURN_NONE();
2166}
2167
2168
2169static PyObject*
2170DB_set_h_ffactor(DBObject* self, PyObject* args)
2171{
2172 int err, ffactor;
2173
2174 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2175 return NULL;
2176 CHECK_DB_NOT_CLOSED(self);
2177
2178 MYDB_BEGIN_ALLOW_THREADS;
2179 err = self->db->set_h_ffactor(self->db, ffactor);
2180 MYDB_END_ALLOW_THREADS;
2181 RETURN_IF_ERR();
2182 RETURN_NONE();
2183}
2184
2185
2186static PyObject*
2187DB_set_h_nelem(DBObject* self, PyObject* args)
2188{
2189 int err, nelem;
2190
2191 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2192 return NULL;
2193 CHECK_DB_NOT_CLOSED(self);
2194
2195 MYDB_BEGIN_ALLOW_THREADS;
2196 err = self->db->set_h_nelem(self->db, nelem);
2197 MYDB_END_ALLOW_THREADS;
2198 RETURN_IF_ERR();
2199 RETURN_NONE();
2200}
2201
2202
2203static PyObject*
2204DB_set_lorder(DBObject* self, PyObject* args)
2205{
2206 int err, lorder;
2207
2208 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2209 return NULL;
2210 CHECK_DB_NOT_CLOSED(self);
2211
2212 MYDB_BEGIN_ALLOW_THREADS;
2213 err = self->db->set_lorder(self->db, lorder);
2214 MYDB_END_ALLOW_THREADS;
2215 RETURN_IF_ERR();
2216 RETURN_NONE();
2217}
2218
2219
2220static PyObject*
2221DB_set_pagesize(DBObject* self, PyObject* args)
2222{
2223 int err, pagesize;
2224
2225 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2226 return NULL;
2227 CHECK_DB_NOT_CLOSED(self);
2228
2229 MYDB_BEGIN_ALLOW_THREADS;
2230 err = self->db->set_pagesize(self->db, pagesize);
2231 MYDB_END_ALLOW_THREADS;
2232 RETURN_IF_ERR();
2233 RETURN_NONE();
2234}
2235
2236
2237static PyObject*
2238DB_set_re_delim(DBObject* self, PyObject* args)
2239{
2240 int err;
2241 char delim;
2242
2243 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2244 PyErr_Clear();
2245 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2246 return NULL;
2247 }
2248
2249 CHECK_DB_NOT_CLOSED(self);
2250
2251 MYDB_BEGIN_ALLOW_THREADS;
2252 err = self->db->set_re_delim(self->db, delim);
2253 MYDB_END_ALLOW_THREADS;
2254 RETURN_IF_ERR();
2255 RETURN_NONE();
2256}
2257
2258static PyObject*
2259DB_set_re_len(DBObject* self, PyObject* args)
2260{
2261 int err, len;
2262
2263 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2266
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_re_len(self->db, len);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
2276DB_set_re_pad(DBObject* self, PyObject* args)
2277{
2278 int err;
2279 char pad;
2280
2281 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2282 PyErr_Clear();
2283 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2284 return NULL;
2285 }
2286 CHECK_DB_NOT_CLOSED(self);
2287
2288 MYDB_BEGIN_ALLOW_THREADS;
2289 err = self->db->set_re_pad(self->db, pad);
2290 MYDB_END_ALLOW_THREADS;
2291 RETURN_IF_ERR();
2292 RETURN_NONE();
2293}
2294
2295
2296static PyObject*
2297DB_set_re_source(DBObject* self, PyObject* args)
2298{
2299 int err;
2300 char *re_source;
2301
2302 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2303 return NULL;
2304 CHECK_DB_NOT_CLOSED(self);
2305
2306 MYDB_BEGIN_ALLOW_THREADS;
2307 err = self->db->set_re_source(self->db, re_source);
2308 MYDB_END_ALLOW_THREADS;
2309 RETURN_IF_ERR();
2310 RETURN_NONE();
2311}
2312
2313
2314#if (DBVER >= 32)
2315static PyObject*
2316DB_set_q_extentsize(DBObject* self, PyObject* args)
2317{
2318 int err;
2319 int extentsize;
2320
2321 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2322 return NULL;
2323 CHECK_DB_NOT_CLOSED(self);
2324
2325 MYDB_BEGIN_ALLOW_THREADS;
2326 err = self->db->set_q_extentsize(self->db, extentsize);
2327 MYDB_END_ALLOW_THREADS;
2328 RETURN_IF_ERR();
2329 RETURN_NONE();
2330}
2331#endif
2332
2333static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002334DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002335{
2336 int err, flags = 0, type;
2337 void* sp;
2338 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002339#if (DBVER >= 43)
2340 PyObject* txnobj = NULL;
2341 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002342 static const char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002343#else
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002344 static const char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002345#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002346
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002347#if (DBVER >= 43)
2348 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2349 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002350 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002351 if (!checkTxnObj(txnobj, &txn))
2352 return NULL;
2353#else
2354 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2355 return NULL;
2356#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002357 CHECK_DB_NOT_CLOSED(self);
2358
2359 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002360#if (DBVER >= 43)
2361 err = self->db->stat(self->db, txn, &sp, flags);
2362#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002363 err = self->db->stat(self->db, &sp, flags);
2364#else
2365 err = self->db->stat(self->db, &sp, NULL, flags);
2366#endif
2367 MYDB_END_ALLOW_THREADS;
2368 RETURN_IF_ERR();
2369
2370 self->haveStat = 1;
2371
2372 /* Turn the stat structure into a dictionary */
2373 type = _DB_get_type(self);
2374 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2375 free(sp);
2376 return NULL;
2377 }
2378
2379#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2380#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2381#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2382
2383 switch (type) {
2384 case DB_HASH:
2385 MAKE_HASH_ENTRY(magic);
2386 MAKE_HASH_ENTRY(version);
2387 MAKE_HASH_ENTRY(nkeys);
2388 MAKE_HASH_ENTRY(ndata);
2389 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002390#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002391 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002392#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002393 MAKE_HASH_ENTRY(ffactor);
2394 MAKE_HASH_ENTRY(buckets);
2395 MAKE_HASH_ENTRY(free);
2396 MAKE_HASH_ENTRY(bfree);
2397 MAKE_HASH_ENTRY(bigpages);
2398 MAKE_HASH_ENTRY(big_bfree);
2399 MAKE_HASH_ENTRY(overflows);
2400 MAKE_HASH_ENTRY(ovfl_free);
2401 MAKE_HASH_ENTRY(dup);
2402 MAKE_HASH_ENTRY(dup_free);
2403 break;
2404
2405 case DB_BTREE:
2406 case DB_RECNO:
2407 MAKE_BT_ENTRY(magic);
2408 MAKE_BT_ENTRY(version);
2409 MAKE_BT_ENTRY(nkeys);
2410 MAKE_BT_ENTRY(ndata);
2411 MAKE_BT_ENTRY(pagesize);
2412 MAKE_BT_ENTRY(minkey);
2413 MAKE_BT_ENTRY(re_len);
2414 MAKE_BT_ENTRY(re_pad);
2415 MAKE_BT_ENTRY(levels);
2416 MAKE_BT_ENTRY(int_pg);
2417 MAKE_BT_ENTRY(leaf_pg);
2418 MAKE_BT_ENTRY(dup_pg);
2419 MAKE_BT_ENTRY(over_pg);
2420 MAKE_BT_ENTRY(free);
2421 MAKE_BT_ENTRY(int_pgfree);
2422 MAKE_BT_ENTRY(leaf_pgfree);
2423 MAKE_BT_ENTRY(dup_pgfree);
2424 MAKE_BT_ENTRY(over_pgfree);
2425 break;
2426
2427 case DB_QUEUE:
2428 MAKE_QUEUE_ENTRY(magic);
2429 MAKE_QUEUE_ENTRY(version);
2430 MAKE_QUEUE_ENTRY(nkeys);
2431 MAKE_QUEUE_ENTRY(ndata);
2432 MAKE_QUEUE_ENTRY(pagesize);
2433 MAKE_QUEUE_ENTRY(pages);
2434 MAKE_QUEUE_ENTRY(re_len);
2435 MAKE_QUEUE_ENTRY(re_pad);
2436 MAKE_QUEUE_ENTRY(pgfree);
2437#if (DBVER == 31)
2438 MAKE_QUEUE_ENTRY(start);
2439#endif
2440 MAKE_QUEUE_ENTRY(first_recno);
2441 MAKE_QUEUE_ENTRY(cur_recno);
2442 break;
2443
2444 default:
2445 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2446 Py_DECREF(d);
2447 d = NULL;
2448 }
2449
2450#undef MAKE_HASH_ENTRY
2451#undef MAKE_BT_ENTRY
2452#undef MAKE_QUEUE_ENTRY
2453
2454 free(sp);
2455 return d;
2456}
2457
2458static PyObject*
2459DB_sync(DBObject* self, PyObject* args)
2460{
2461 int err;
2462 int flags = 0;
2463
2464 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2465 return NULL;
2466 CHECK_DB_NOT_CLOSED(self);
2467
2468 MYDB_BEGIN_ALLOW_THREADS;
2469 err = self->db->sync(self->db, flags);
2470 MYDB_END_ALLOW_THREADS;
2471 RETURN_IF_ERR();
2472 RETURN_NONE();
2473}
2474
2475
2476#if (DBVER >= 33)
2477static PyObject*
2478DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2479{
2480 int err, flags=0;
2481 u_int32_t count=0;
2482 PyObject* txnobj = NULL;
2483 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002484 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002485
2486 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2487 &txnobj, &flags))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2490 if (!checkTxnObj(txnobj, &txn))
2491 return NULL;
2492
2493 MYDB_BEGIN_ALLOW_THREADS;
2494 err = self->db->truncate(self->db, txn, &count, flags);
2495 MYDB_END_ALLOW_THREADS;
2496 RETURN_IF_ERR();
2497 return PyInt_FromLong(count);
2498}
2499#endif
2500
2501
2502static PyObject*
2503DB_upgrade(DBObject* self, PyObject* args)
2504{
2505 int err, flags=0;
2506 char *filename;
2507
2508 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2509 return NULL;
2510 CHECK_DB_NOT_CLOSED(self);
2511
2512 MYDB_BEGIN_ALLOW_THREADS;
2513 err = self->db->upgrade(self->db, filename, flags);
2514 MYDB_END_ALLOW_THREADS;
2515 RETURN_IF_ERR();
2516 RETURN_NONE();
2517}
2518
2519
2520static PyObject*
2521DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2522{
2523 int err, flags=0;
2524 char* fileName;
2525 char* dbName=NULL;
2526 char* outFileName=NULL;
2527 FILE* outFile=NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002528 static const char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2529 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002530
2531 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2532 &fileName, &dbName, &outFileName, &flags))
2533 return NULL;
2534
2535 CHECK_DB_NOT_CLOSED(self);
2536 if (outFileName)
2537 outFile = fopen(outFileName, "w");
2538
2539 MYDB_BEGIN_ALLOW_THREADS;
2540 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2541 MYDB_END_ALLOW_THREADS;
2542 if (outFileName)
2543 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002544
2545 /* DB.verify acts as a DB handle destructor (like close); this was
2546 * documented in BerkeleyDB 4.2 but had the undocumented effect
2547 * of not being safe in prior versions while still requiring an explicit
2548 * DB.close call afterwards. Lets call close for the user to emulate
2549 * the safe 4.2 behaviour. */
2550#if (DBVER <= 41)
2551 self->db->close(self->db, 0);
2552#endif
2553 self->db = NULL;
2554
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002555 RETURN_IF_ERR();
2556 RETURN_NONE();
2557}
2558
2559
2560static PyObject*
2561DB_set_get_returns_none(DBObject* self, PyObject* args)
2562{
2563 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002564 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002565
2566 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2567 return NULL;
2568 CHECK_DB_NOT_CLOSED(self);
2569
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002570 if (self->moduleFlags.getReturnsNone)
2571 ++oldValue;
2572 if (self->moduleFlags.cursorSetReturnsNone)
2573 ++oldValue;
2574 self->moduleFlags.getReturnsNone = (flags >= 1);
2575 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002576 return PyInt_FromLong(oldValue);
2577}
2578
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002579#if (DBVER >= 41)
2580static PyObject*
2581DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2582{
2583 int err;
2584 u_int32_t flags=0;
2585 char *passwd = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002586 static const char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002587
2588 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2589 &passwd, &flags)) {
2590 return NULL;
2591 }
2592
2593 MYDB_BEGIN_ALLOW_THREADS;
2594 err = self->db->set_encrypt(self->db, passwd, flags);
2595 MYDB_END_ALLOW_THREADS;
2596
2597 RETURN_IF_ERR();
2598 RETURN_NONE();
2599}
2600#endif /* DBVER >= 41 */
2601
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002602
2603/*-------------------------------------------------------------- */
2604/* Mapping and Dictionary-like access routines */
2605
2606int DB_length(DBObject* self)
2607{
2608 int err;
2609 long size = 0;
2610 int flags = 0;
2611 void* sp;
2612
2613 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002614 PyErr_SetObject(DBError,
2615 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 return -1;
2617 }
2618
2619 if (self->haveStat) { /* Has the stat function been called recently? If
2620 so, we can use the cached value. */
2621 flags = DB_CACHED_COUNTS;
2622 }
2623
2624 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002625#if (DBVER >= 43)
2626 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2627#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002628 err = self->db->stat(self->db, &sp, flags);
2629#else
2630 err = self->db->stat(self->db, &sp, NULL, flags);
2631#endif
2632 MYDB_END_ALLOW_THREADS;
2633
2634 if (err)
2635 return -1;
2636
2637 self->haveStat = 1;
2638
2639 /* All the stat structures have matching fields upto the ndata field,
2640 so we can use any of them for the type cast */
2641 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2642 free(sp);
2643 return size;
2644}
2645
2646
2647PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2648{
2649 int err;
2650 PyObject* retval;
2651 DBT key;
2652 DBT data;
2653
2654 CHECK_DB_NOT_CLOSED(self);
2655 if (!make_key_dbt(self, keyobj, &key, NULL))
2656 return NULL;
2657
2658 CLEAR_DBT(data);
2659 if (CHECK_DBFLAG(self, DB_THREAD)) {
2660 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2661 data.flags = DB_DBT_MALLOC;
2662 }
2663 MYDB_BEGIN_ALLOW_THREADS;
2664 err = self->db->get(self->db, NULL, &key, &data, 0);
2665 MYDB_END_ALLOW_THREADS;
2666 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2667 PyErr_SetObject(PyExc_KeyError, keyobj);
2668 retval = NULL;
2669 }
2670 else if (makeDBError(err)) {
2671 retval = NULL;
2672 }
2673 else {
2674 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2675 FREE_DBT(data);
2676 }
2677
2678 FREE_DBT(key);
2679 return retval;
2680}
2681
2682
2683static int
2684DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2685{
2686 DBT key, data;
2687 int retval;
2688 int flags = 0;
2689
2690 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002691 PyErr_SetObject(DBError,
2692 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002693 return -1;
2694 }
2695
2696 if (!make_key_dbt(self, keyobj, &key, NULL))
2697 return -1;
2698
2699 if (dataobj != NULL) {
2700 if (!make_dbt(dataobj, &data))
2701 retval = -1;
2702 else {
2703 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002704 /* dictionaries shouldn't have duplicate keys */
2705 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 retval = _DB_put(self, NULL, &key, &data, flags);
2707
2708 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002709 /* try deleting any old record that matches and then PUT it
2710 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002711 _DB_delete(self, NULL, &key, 0);
2712 PyErr_Clear();
2713 retval = _DB_put(self, NULL, &key, &data, flags);
2714 }
2715 }
2716 }
2717 else {
2718 /* dataobj == NULL, so delete the key */
2719 retval = _DB_delete(self, NULL, &key, 0);
2720 }
2721 FREE_DBT(key);
2722 return retval;
2723}
2724
2725
2726static PyObject*
2727DB_has_key(DBObject* self, PyObject* args)
2728{
2729 int err;
2730 PyObject* keyobj;
2731 DBT key, data;
2732 PyObject* txnobj = NULL;
2733 DB_TXN *txn = NULL;
2734
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002735 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 return NULL;
2737 CHECK_DB_NOT_CLOSED(self);
2738 if (!make_key_dbt(self, keyobj, &key, NULL))
2739 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002740 if (!checkTxnObj(txnobj, &txn)) {
2741 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002742 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002743 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002745 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746 it has a record but can't allocate a buffer for the data. This saves
2747 having to deal with data we won't be using.
2748 */
2749 CLEAR_DBT(data);
2750 data.flags = DB_DBT_USERMEM;
2751
2752 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002753 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754 MYDB_END_ALLOW_THREADS;
2755 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002756
2757 if (err == DB_BUFFER_SMALL || err == 0) {
2758 return PyInt_FromLong(1);
2759 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2760 return PyInt_FromLong(0);
2761 }
2762
2763 makeDBError(err);
2764 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002765}
2766
2767
2768#define _KEYS_LIST 1
2769#define _VALUES_LIST 2
2770#define _ITEMS_LIST 3
2771
2772static PyObject*
2773_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2774{
2775 int err, dbtype;
2776 DBT key;
2777 DBT data;
2778 DBC *cursor;
2779 PyObject* list;
2780 PyObject* item = NULL;
2781
2782 CHECK_DB_NOT_CLOSED(self);
2783 CLEAR_DBT(key);
2784 CLEAR_DBT(data);
2785
2786 dbtype = _DB_get_type(self);
2787 if (dbtype == -1)
2788 return NULL;
2789
2790 list = PyList_New(0);
2791 if (list == NULL) {
2792 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2793 return NULL;
2794 }
2795
2796 /* get a cursor */
2797 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002798 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 MYDB_END_ALLOW_THREADS;
2800 RETURN_IF_ERR();
2801
2802 if (CHECK_DBFLAG(self, DB_THREAD)) {
2803 key.flags = DB_DBT_REALLOC;
2804 data.flags = DB_DBT_REALLOC;
2805 }
2806
2807 while (1) { /* use the cursor to traverse the DB, collecting items */
2808 MYDB_BEGIN_ALLOW_THREADS;
2809 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2810 MYDB_END_ALLOW_THREADS;
2811
2812 if (err) {
2813 /* for any error, break out of the loop */
2814 break;
2815 }
2816
2817 switch (type) {
2818 case _KEYS_LIST:
2819 switch(dbtype) {
2820 case DB_BTREE:
2821 case DB_HASH:
2822 default:
2823 item = PyString_FromStringAndSize((char*)key.data, key.size);
2824 break;
2825 case DB_RECNO:
2826 case DB_QUEUE:
2827 item = PyInt_FromLong(*((db_recno_t*)key.data));
2828 break;
2829 }
2830 break;
2831
2832 case _VALUES_LIST:
2833 item = PyString_FromStringAndSize((char*)data.data, data.size);
2834 break;
2835
2836 case _ITEMS_LIST:
2837 switch(dbtype) {
2838 case DB_BTREE:
2839 case DB_HASH:
2840 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002841 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2842 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 break;
2844 case DB_RECNO:
2845 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002846 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2847 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848 break;
2849 }
2850 break;
2851 }
2852 if (item == NULL) {
2853 Py_DECREF(list);
2854 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2855 list = NULL;
2856 goto done;
2857 }
2858 PyList_Append(list, item);
2859 Py_DECREF(item);
2860 }
2861
Gregory P. Smithe9477062005-06-04 06:46:59 +00002862 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2863 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002864 Py_DECREF(list);
2865 list = NULL;
2866 }
2867
2868 done:
2869 FREE_DBT(key);
2870 FREE_DBT(data);
2871 MYDB_BEGIN_ALLOW_THREADS;
2872 cursor->c_close(cursor);
2873 MYDB_END_ALLOW_THREADS;
2874 return list;
2875}
2876
2877
2878static PyObject*
2879DB_keys(DBObject* self, PyObject* args)
2880{
2881 PyObject* txnobj = NULL;
2882 DB_TXN *txn = NULL;
2883
2884 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2885 return NULL;
2886 if (!checkTxnObj(txnobj, &txn))
2887 return NULL;
2888 return _DB_make_list(self, txn, _KEYS_LIST);
2889}
2890
2891
2892static PyObject*
2893DB_items(DBObject* self, PyObject* args)
2894{
2895 PyObject* txnobj = NULL;
2896 DB_TXN *txn = NULL;
2897
2898 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2899 return NULL;
2900 if (!checkTxnObj(txnobj, &txn))
2901 return NULL;
2902 return _DB_make_list(self, txn, _ITEMS_LIST);
2903}
2904
2905
2906static PyObject*
2907DB_values(DBObject* self, PyObject* args)
2908{
2909 PyObject* txnobj = NULL;
2910 DB_TXN *txn = NULL;
2911
2912 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2913 return NULL;
2914 if (!checkTxnObj(txnobj, &txn))
2915 return NULL;
2916 return _DB_make_list(self, txn, _VALUES_LIST);
2917}
2918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919/* --------------------------------------------------------------------- */
2920/* DBCursor methods */
2921
2922
2923static PyObject*
2924DBC_close(DBCursorObject* self, PyObject* args)
2925{
2926 int err = 0;
2927
2928 if (!PyArg_ParseTuple(args, ":close"))
2929 return NULL;
2930
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002931 if (self->dbc != NULL) {
2932 MYDB_BEGIN_ALLOW_THREADS;
2933 err = self->dbc->c_close(self->dbc);
2934 self->dbc = NULL;
2935 MYDB_END_ALLOW_THREADS;
2936 }
2937 RETURN_IF_ERR();
2938 RETURN_NONE();
2939}
2940
2941
2942static PyObject*
2943DBC_count(DBCursorObject* self, PyObject* args)
2944{
2945 int err = 0;
2946 db_recno_t count;
2947 int flags = 0;
2948
2949 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2950 return NULL;
2951
2952 CHECK_CURSOR_NOT_CLOSED(self);
2953
2954 MYDB_BEGIN_ALLOW_THREADS;
2955 err = self->dbc->c_count(self->dbc, &count, flags);
2956 MYDB_END_ALLOW_THREADS;
2957 RETURN_IF_ERR();
2958
2959 return PyInt_FromLong(count);
2960}
2961
2962
2963static PyObject*
2964DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2965{
2966 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2967}
2968
2969
2970static PyObject*
2971DBC_delete(DBCursorObject* self, PyObject* args)
2972{
2973 int err, flags=0;
2974
2975 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2976 return NULL;
2977
2978 CHECK_CURSOR_NOT_CLOSED(self);
2979
2980 MYDB_BEGIN_ALLOW_THREADS;
2981 err = self->dbc->c_del(self->dbc, flags);
2982 MYDB_END_ALLOW_THREADS;
2983 RETURN_IF_ERR();
2984
2985 self->mydb->haveStat = 0;
2986 RETURN_NONE();
2987}
2988
2989
2990static PyObject*
2991DBC_dup(DBCursorObject* self, PyObject* args)
2992{
2993 int err, flags =0;
2994 DBC* dbc = NULL;
2995
2996 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2997 return NULL;
2998
2999 CHECK_CURSOR_NOT_CLOSED(self);
3000
3001 MYDB_BEGIN_ALLOW_THREADS;
3002 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3003 MYDB_END_ALLOW_THREADS;
3004 RETURN_IF_ERR();
3005
3006 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3007}
3008
3009static PyObject*
3010DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3011{
3012 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3013}
3014
3015
3016static PyObject*
3017DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3018{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003019 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003020 PyObject* keyobj = NULL;
3021 PyObject* dataobj = NULL;
3022 PyObject* retval = NULL;
3023 int dlen = -1;
3024 int doff = -1;
3025 DBT key, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003026 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3027 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028
3029 CLEAR_DBT(key);
3030 CLEAR_DBT(data);
3031 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003032 &flags, &dlen, &doff))
3033 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003035 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3036 &kwnames[1],
3037 &keyobj, &flags, &dlen, &doff))
3038 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003039 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003040 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3041 kwnames, &keyobj, &dataobj,
3042 &flags, &dlen, &doff))
3043 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 return NULL;
3045 }
3046 }
3047 }
3048
3049 CHECK_CURSOR_NOT_CLOSED(self);
3050
3051 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3052 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003053 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3054 (!add_partial_dbt(&data, dlen, doff)) )
3055 {
3056 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003058 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059
3060 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3061 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003062 if (!(key.flags & DB_DBT_REALLOC)) {
3063 key.flags |= DB_DBT_MALLOC;
3064 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065 }
3066
3067 MYDB_BEGIN_ALLOW_THREADS;
3068 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3069 MYDB_END_ALLOW_THREADS;
3070
Gregory P. Smithe9477062005-06-04 06:46:59 +00003071 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3072 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003073 Py_INCREF(Py_None);
3074 retval = Py_None;
3075 }
3076 else if (makeDBError(err)) {
3077 retval = NULL;
3078 }
3079 else {
3080 switch (_DB_get_type(self->mydb)) {
3081 case -1:
3082 retval = NULL;
3083 break;
3084 case DB_BTREE:
3085 case DB_HASH:
3086 default:
3087 retval = Py_BuildValue("s#s#", key.data, key.size,
3088 data.data, data.size);
3089 break;
3090 case DB_RECNO:
3091 case DB_QUEUE:
3092 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3093 data.data, data.size);
3094 break;
3095 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003096 FREE_DBT(data);
3097 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003098 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003099 return retval;
3100}
3101
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003102#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003103static PyObject*
3104DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3105{
3106 int err, flags=0;
3107 PyObject* keyobj = NULL;
3108 PyObject* dataobj = NULL;
3109 PyObject* retval = NULL;
3110 int dlen = -1;
3111 int doff = -1;
3112 DBT key, pkey, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003113 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3114 NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003115
3116 CLEAR_DBT(key);
3117 CLEAR_DBT(data);
3118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3119 &flags, &dlen, &doff))
3120 {
3121 PyErr_Clear();
3122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3123 &kwnames[1],
3124 &keyobj, &flags, &dlen, &doff))
3125 {
3126 PyErr_Clear();
3127 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3128 kwnames, &keyobj, &dataobj,
3129 &flags, &dlen, &doff))
3130 {
3131 return NULL;
3132 }
3133 }
3134 }
3135
3136 CHECK_CURSOR_NOT_CLOSED(self);
3137
3138 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3139 return NULL;
3140 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3141 (!add_partial_dbt(&data, dlen, doff)) ) {
3142 FREE_DBT(key);
3143 return NULL;
3144 }
3145
3146 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3147 data.flags = DB_DBT_MALLOC;
3148 if (!(key.flags & DB_DBT_REALLOC)) {
3149 key.flags |= DB_DBT_MALLOC;
3150 }
3151 }
3152
3153 CLEAR_DBT(pkey);
3154 pkey.flags = DB_DBT_MALLOC;
3155
3156 MYDB_BEGIN_ALLOW_THREADS;
3157 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3158 MYDB_END_ALLOW_THREADS;
3159
Gregory P. Smithe9477062005-06-04 06:46:59 +00003160 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3161 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003162 Py_INCREF(Py_None);
3163 retval = Py_None;
3164 }
3165 else if (makeDBError(err)) {
3166 retval = NULL;
3167 }
3168 else {
3169 PyObject *pkeyObj;
3170 PyObject *dataObj;
3171 dataObj = PyString_FromStringAndSize(data.data, data.size);
3172
3173 if (self->mydb->primaryDBType == DB_RECNO ||
3174 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003175 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003176 else
3177 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3178
3179 if (flags & DB_SET_RECNO) /* return key, pkey and data */
3180 {
3181 PyObject *keyObj;
3182 int type = _DB_get_type(self->mydb);
3183 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003184 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003185 else
3186 keyObj = PyString_FromStringAndSize(key.data, key.size);
3187 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3188 FREE_DBT(key);
3189 }
3190 else /* return just the pkey and data */
3191 {
3192 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3193 }
3194 FREE_DBT(pkey);
3195 FREE_DBT(data);
3196 }
3197 /* the only time REALLOC should be set is if we used an integer
3198 * key that make_key_dbt malloc'd for us. always free these. */
3199 if (key.flags & DB_DBT_REALLOC) {
3200 FREE_DBT(key);
3201 }
3202 return retval;
3203}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003204#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003205
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003206
3207static PyObject*
3208DBC_get_recno(DBCursorObject* self, PyObject* args)
3209{
3210 int err;
3211 db_recno_t recno;
3212 DBT key;
3213 DBT data;
3214
3215 if (!PyArg_ParseTuple(args, ":get_recno"))
3216 return NULL;
3217
3218 CHECK_CURSOR_NOT_CLOSED(self);
3219
3220 CLEAR_DBT(key);
3221 CLEAR_DBT(data);
3222 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3223 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3224 data.flags = DB_DBT_MALLOC;
3225 key.flags = DB_DBT_MALLOC;
3226 }
3227
3228 MYDB_BEGIN_ALLOW_THREADS;
3229 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3230 MYDB_END_ALLOW_THREADS;
3231 RETURN_IF_ERR();
3232
3233 recno = *((db_recno_t*)data.data);
3234 FREE_DBT(key);
3235 FREE_DBT(data);
3236 return PyInt_FromLong(recno);
3237}
3238
3239
3240static PyObject*
3241DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3242{
3243 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3244}
3245
3246
3247static PyObject*
3248DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3249{
3250 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3251}
3252
3253
3254static PyObject*
3255DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3256{
3257 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3258}
3259
3260
3261static PyObject*
3262DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3263{
3264 int err, flags = 0;
3265 PyObject* keyobj, *dataobj;
3266 DBT key, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003267 static const char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3268 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003269 int dlen = -1;
3270 int doff = -1;
3271
3272 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3273 &keyobj, &dataobj, &flags, &dlen, &doff))
3274 return NULL;
3275
3276 CHECK_CURSOR_NOT_CLOSED(self);
3277
3278 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3279 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003280 if (!make_dbt(dataobj, &data) ||
3281 !add_partial_dbt(&data, dlen, doff) )
3282 {
3283 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003284 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003285 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003286
3287 MYDB_BEGIN_ALLOW_THREADS;
3288 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3289 MYDB_END_ALLOW_THREADS;
3290 FREE_DBT(key);
3291 RETURN_IF_ERR();
3292 self->mydb->haveStat = 0;
3293 RETURN_NONE();
3294}
3295
3296
3297static PyObject*
3298DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3299{
3300 int err, flags = 0;
3301 DBT key, data;
3302 PyObject* retval, *keyobj;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003303 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003304 int dlen = -1;
3305 int doff = -1;
3306
3307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3308 &keyobj, &flags, &dlen, &doff))
3309 return NULL;
3310
3311 CHECK_CURSOR_NOT_CLOSED(self);
3312
3313 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3314 return NULL;
3315
3316 CLEAR_DBT(data);
3317 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3318 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3319 data.flags = DB_DBT_MALLOC;
3320 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003321 if (!add_partial_dbt(&data, dlen, doff)) {
3322 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003323 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003324 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003325
3326 MYDB_BEGIN_ALLOW_THREADS;
3327 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3328 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003329 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3330 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003331 Py_INCREF(Py_None);
3332 retval = Py_None;
3333 }
3334 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003335 retval = NULL;
3336 }
3337 else {
3338 switch (_DB_get_type(self->mydb)) {
3339 case -1:
3340 retval = NULL;
3341 break;
3342 case DB_BTREE:
3343 case DB_HASH:
3344 default:
3345 retval = Py_BuildValue("s#s#", key.data, key.size,
3346 data.data, data.size);
3347 break;
3348 case DB_RECNO:
3349 case DB_QUEUE:
3350 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3351 data.data, data.size);
3352 break;
3353 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003355 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003356 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003357 /* the only time REALLOC should be set is if we used an integer
3358 * key that make_key_dbt malloc'd for us. always free these. */
3359 if (key.flags & DB_DBT_REALLOC) {
3360 FREE_DBT(key);
3361 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362
3363 return retval;
3364}
3365
3366
3367static PyObject*
3368DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3369{
3370 int err, flags = 0;
3371 DBT key, data;
3372 PyObject* retval, *keyobj;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003373 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003374 int dlen = -1;
3375 int doff = -1;
3376
3377 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3378 &keyobj, &flags, &dlen, &doff))
3379 return NULL;
3380
3381 CHECK_CURSOR_NOT_CLOSED(self);
3382
3383 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3384 return NULL;
3385
3386 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003387 if (!add_partial_dbt(&data, dlen, doff)) {
3388 FREE_DBT(key);
3389 return NULL;
3390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3392 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003393 data.flags |= DB_DBT_MALLOC;
3394 /* only BTREE databases will return anything in the key */
3395 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3396 key.flags |= DB_DBT_MALLOC;
3397 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003398 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003399 MYDB_BEGIN_ALLOW_THREADS;
3400 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3401 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003402 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3403 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003404 Py_INCREF(Py_None);
3405 retval = Py_None;
3406 }
3407 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 retval = NULL;
3409 }
3410 else {
3411 switch (_DB_get_type(self->mydb)) {
3412 case -1:
3413 retval = NULL;
3414 break;
3415 case DB_BTREE:
3416 case DB_HASH:
3417 default:
3418 retval = Py_BuildValue("s#s#", key.data, key.size,
3419 data.data, data.size);
3420 break;
3421 case DB_RECNO:
3422 case DB_QUEUE:
3423 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3424 data.data, data.size);
3425 break;
3426 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003427 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 FREE_DBT(data);
3429 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003430 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003431 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003432 if (key.flags & DB_DBT_REALLOC) {
3433 FREE_DBT(key);
3434 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003435
3436 return retval;
3437}
3438
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003439static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003440_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3441 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003443 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003445 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446
Gregory P. Smith7441e652003-11-03 21:35:31 +00003447 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3449 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003450 if (!make_dbt(dataobj, &data)) {
3451 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003453 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454
3455 MYDB_BEGIN_ALLOW_THREADS;
3456 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3457 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003458 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003459 Py_INCREF(Py_None);
3460 retval = Py_None;
3461 }
3462 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 retval = NULL;
3464 }
3465 else {
3466 switch (_DB_get_type(self->mydb)) {
3467 case -1:
3468 retval = NULL;
3469 break;
3470 case DB_BTREE:
3471 case DB_HASH:
3472 default:
3473 retval = Py_BuildValue("s#s#", key.data, key.size,
3474 data.data, data.size);
3475 break;
3476 case DB_RECNO:
3477 case DB_QUEUE:
3478 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3479 data.data, data.size);
3480 break;
3481 }
3482 }
3483
3484 FREE_DBT(key);
3485 return retval;
3486}
3487
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003488static PyObject*
3489DBC_get_both(DBCursorObject* self, PyObject* args)
3490{
3491 int flags=0;
3492 PyObject *keyobj, *dataobj;
3493
3494 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3495 return NULL;
3496
Gregory P. Smith7441e652003-11-03 21:35:31 +00003497 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003498 CHECK_CURSOR_NOT_CLOSED(self);
3499
3500 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3501 self->mydb->moduleFlags.getReturnsNone);
3502}
3503
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003504/* Return size of entry */
3505static PyObject*
3506DBC_get_current_size(DBCursorObject* self, PyObject* args)
3507{
3508 int err, flags=DB_CURRENT;
3509 PyObject* retval = NULL;
3510 DBT key, data;
3511
3512 if (!PyArg_ParseTuple(args, ":get_current_size"))
3513 return NULL;
3514 CHECK_CURSOR_NOT_CLOSED(self);
3515 CLEAR_DBT(key);
3516 CLEAR_DBT(data);
3517
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003518 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003519 getting the record size. */
3520 data.flags = DB_DBT_USERMEM;
3521 data.ulen = 0;
3522 MYDB_BEGIN_ALLOW_THREADS;
3523 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3524 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003525 if (err == DB_BUFFER_SMALL || !err) {
3526 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003527 retval = PyInt_FromLong((long)data.size);
3528 err = 0;
3529 }
3530
3531 FREE_DBT(key);
3532 FREE_DBT(data);
3533 RETURN_IF_ERR();
3534 return retval;
3535}
3536
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003537static PyObject*
3538DBC_set_both(DBCursorObject* self, PyObject* args)
3539{
3540 int flags=0;
3541 PyObject *keyobj, *dataobj;
3542
3543 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3544 return NULL;
3545
Gregory P. Smith7441e652003-11-03 21:35:31 +00003546 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003547 CHECK_CURSOR_NOT_CLOSED(self);
3548
3549 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3550 self->mydb->moduleFlags.cursorSetReturnsNone);
3551}
3552
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553
3554static PyObject*
3555DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3556{
3557 int err, irecno, flags=0;
3558 db_recno_t recno;
3559 DBT key, data;
3560 PyObject* retval;
3561 int dlen = -1;
3562 int doff = -1;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003563 static const char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003564
3565 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3566 &irecno, &flags, &dlen, &doff))
3567 return NULL;
3568
3569 CHECK_CURSOR_NOT_CLOSED(self);
3570
3571 CLEAR_DBT(key);
3572 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003573 /* use allocated space so DB will be able to realloc room for the real
3574 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575 key.data = malloc(sizeof(db_recno_t));
3576 if (key.data == NULL) {
3577 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3578 return NULL;
3579 }
3580 key.size = sizeof(db_recno_t);
3581 key.ulen = key.size;
3582 memcpy(key.data, &recno, sizeof(db_recno_t));
3583 key.flags = DB_DBT_REALLOC;
3584
3585 CLEAR_DBT(data);
3586 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3587 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3588 data.flags = DB_DBT_MALLOC;
3589 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003590 if (!add_partial_dbt(&data, dlen, doff)) {
3591 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594
3595 MYDB_BEGIN_ALLOW_THREADS;
3596 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3597 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003598 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3599 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003600 Py_INCREF(Py_None);
3601 retval = Py_None;
3602 }
3603 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604 retval = NULL;
3605 }
3606 else { /* Can only be used for BTrees, so no need to return int key */
3607 retval = Py_BuildValue("s#s#", key.data, key.size,
3608 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003609 FREE_DBT(data);
3610 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003611 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003612
3613 return retval;
3614}
3615
3616
3617static PyObject*
3618DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3619{
3620 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3621}
3622
3623
3624static PyObject*
3625DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3626{
3627 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3628}
3629
3630
3631static PyObject*
3632DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3633{
3634 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3635}
3636
3637
3638static PyObject*
3639DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3640{
3641 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3642}
3643
3644
3645static PyObject*
3646DBC_join_item(DBCursorObject* self, PyObject* args)
3647{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003648 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003649 DBT key, data;
3650 PyObject* retval;
3651
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003652 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003653 return NULL;
3654
3655 CHECK_CURSOR_NOT_CLOSED(self);
3656
3657 CLEAR_DBT(key);
3658 CLEAR_DBT(data);
3659 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3660 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3661 key.flags = DB_DBT_MALLOC;
3662 }
3663
3664 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003666 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003667 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3668 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669 Py_INCREF(Py_None);
3670 retval = Py_None;
3671 }
3672 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003673 retval = NULL;
3674 }
3675 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003676 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677 FREE_DBT(key);
3678 }
3679
3680 return retval;
3681}
3682
3683
3684
3685/* --------------------------------------------------------------------- */
3686/* DBEnv methods */
3687
3688
3689static PyObject*
3690DBEnv_close(DBEnvObject* self, PyObject* args)
3691{
3692 int err, flags = 0;
3693
3694 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3695 return NULL;
3696 if (!self->closed) { /* Don't close more than once */
3697 MYDB_BEGIN_ALLOW_THREADS;
3698 err = self->db_env->close(self->db_env, flags);
3699 MYDB_END_ALLOW_THREADS;
3700 /* after calling DBEnv->close, regardless of error, this DBEnv
3701 * may not be accessed again (BerkeleyDB docs). */
3702 self->closed = 1;
3703 self->db_env = NULL;
3704 RETURN_IF_ERR();
3705 }
3706 RETURN_NONE();
3707}
3708
3709
3710static PyObject*
3711DBEnv_open(DBEnvObject* self, PyObject* args)
3712{
3713 int err, flags=0, mode=0660;
3714 char *db_home;
3715
3716 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3717 return NULL;
3718
3719 CHECK_ENV_NOT_CLOSED(self);
3720
3721 MYDB_BEGIN_ALLOW_THREADS;
3722 err = self->db_env->open(self->db_env, db_home, flags, mode);
3723 MYDB_END_ALLOW_THREADS;
3724 RETURN_IF_ERR();
3725 self->closed = 0;
3726 self->flags = flags;
3727 RETURN_NONE();
3728}
3729
3730
3731static PyObject*
3732DBEnv_remove(DBEnvObject* self, PyObject* args)
3733{
3734 int err, flags=0;
3735 char *db_home;
3736
3737 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3738 return NULL;
3739 CHECK_ENV_NOT_CLOSED(self);
3740 MYDB_BEGIN_ALLOW_THREADS;
3741 err = self->db_env->remove(self->db_env, db_home, flags);
3742 MYDB_END_ALLOW_THREADS;
3743 RETURN_IF_ERR();
3744 RETURN_NONE();
3745}
3746
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003747#if (DBVER >= 41)
3748static PyObject*
3749DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3750{
3751 int err;
3752 u_int32_t flags=0;
3753 char *file = NULL;
3754 char *database = NULL;
3755 PyObject *txnobj = NULL;
3756 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003757 static const char* kwnames[] = { "file", "database", "txn", "flags",
3758 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003759
3760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3761 &file, &database, &txnobj, &flags)) {
3762 return NULL;
3763 }
3764 if (!checkTxnObj(txnobj, &txn)) {
3765 return NULL;
3766 }
3767 CHECK_ENV_NOT_CLOSED(self);
3768 MYDB_BEGIN_ALLOW_THREADS;
3769 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3770 MYDB_END_ALLOW_THREADS;
3771 RETURN_IF_ERR();
3772 RETURN_NONE();
3773}
3774
3775static PyObject*
3776DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3777{
3778 int err;
3779 u_int32_t flags=0;
3780 char *file = NULL;
3781 char *database = NULL;
3782 char *newname = NULL;
3783 PyObject *txnobj = NULL;
3784 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003785 static const char* kwnames[] = { "file", "database", "newname", "txn",
3786 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003787
3788 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3789 &file, &database, &newname, &txnobj, &flags)) {
3790 return NULL;
3791 }
3792 if (!checkTxnObj(txnobj, &txn)) {
3793 return NULL;
3794 }
3795 CHECK_ENV_NOT_CLOSED(self);
3796 MYDB_BEGIN_ALLOW_THREADS;
3797 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3798 flags);
3799 MYDB_END_ALLOW_THREADS;
3800 RETURN_IF_ERR();
3801 RETURN_NONE();
3802}
3803
3804static PyObject*
3805DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3806{
3807 int err;
3808 u_int32_t flags=0;
3809 char *passwd = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003810 static const char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003811
3812 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3813 &passwd, &flags)) {
3814 return NULL;
3815 }
3816
3817 MYDB_BEGIN_ALLOW_THREADS;
3818 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3819 MYDB_END_ALLOW_THREADS;
3820
3821 RETURN_IF_ERR();
3822 RETURN_NONE();
3823}
3824#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003825
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003826#if (DBVER >= 40)
3827static PyObject*
3828DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3829{
3830 int err;
3831 u_int32_t flags=0;
3832 u_int32_t timeout = 0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003833 static const char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003834
3835 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3836 &timeout, &flags)) {
3837 return NULL;
3838 }
3839
3840 MYDB_BEGIN_ALLOW_THREADS;
3841 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3842 MYDB_END_ALLOW_THREADS;
3843
3844 RETURN_IF_ERR();
3845 RETURN_NONE();
3846}
3847#endif /* DBVER >= 40 */
3848
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003849static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003850DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3851{
3852 int err;
3853 long shm_key = 0;
3854
3855 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3856 return NULL;
3857 CHECK_ENV_NOT_CLOSED(self);
3858
3859 err = self->db_env->set_shm_key(self->db_env, shm_key);
3860 RETURN_IF_ERR();
3861 RETURN_NONE();
3862}
3863
3864static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003865DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3866{
3867 int err, gbytes=0, bytes=0, ncache=0;
3868
3869 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3870 &gbytes, &bytes, &ncache))
3871 return NULL;
3872 CHECK_ENV_NOT_CLOSED(self);
3873
3874 MYDB_BEGIN_ALLOW_THREADS;
3875 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3876 MYDB_END_ALLOW_THREADS;
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3879}
3880
3881
3882#if (DBVER >= 32)
3883static PyObject*
3884DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3885{
3886 int err, flags=0, onoff=0;
3887
3888 if (!PyArg_ParseTuple(args, "ii:set_flags",
3889 &flags, &onoff))
3890 return NULL;
3891 CHECK_ENV_NOT_CLOSED(self);
3892
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->set_flags(self->db_env, flags, onoff);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3898}
3899#endif
3900
3901
3902static PyObject*
3903DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3904{
3905 int err;
3906 char *dir;
3907
3908 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3909 return NULL;
3910 CHECK_ENV_NOT_CLOSED(self);
3911
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->set_data_dir(self->db_env, dir);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3917}
3918
3919
3920static PyObject*
3921DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3922{
3923 int err, lg_bsize;
3924
3925 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3926 return NULL;
3927 CHECK_ENV_NOT_CLOSED(self);
3928
3929 MYDB_BEGIN_ALLOW_THREADS;
3930 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3931 MYDB_END_ALLOW_THREADS;
3932 RETURN_IF_ERR();
3933 RETURN_NONE();
3934}
3935
3936
3937static PyObject*
3938DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3939{
3940 int err;
3941 char *dir;
3942
3943 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3944 return NULL;
3945 CHECK_ENV_NOT_CLOSED(self);
3946
3947 MYDB_BEGIN_ALLOW_THREADS;
3948 err = self->db_env->set_lg_dir(self->db_env, dir);
3949 MYDB_END_ALLOW_THREADS;
3950 RETURN_IF_ERR();
3951 RETURN_NONE();
3952}
3953
3954static PyObject*
3955DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3956{
3957 int err, lg_max;
3958
3959 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3960 return NULL;
3961 CHECK_ENV_NOT_CLOSED(self);
3962
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_lg_max(self->db_env, lg_max);
3965 MYDB_END_ALLOW_THREADS;
3966 RETURN_IF_ERR();
3967 RETURN_NONE();
3968}
3969
3970
Neal Norwitz84562352005-10-20 04:30:15 +00003971#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003972static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003973DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3974{
3975 int err, lg_max;
3976
3977 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3978 return NULL;
3979 CHECK_ENV_NOT_CLOSED(self);
3980
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3983 MYDB_END_ALLOW_THREADS;
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3986}
Neal Norwitz84562352005-10-20 04:30:15 +00003987#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00003988
3989
3990static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3992{
3993 int err, lk_detect;
3994
3995 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3998
3999 MYDB_BEGIN_ALLOW_THREADS;
4000 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4001 MYDB_END_ALLOW_THREADS;
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006
4007static PyObject*
4008DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4009{
4010 int err, max;
4011
4012 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4015
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_lk_max(self->db_env, max);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4021}
4022
4023
4024#if (DBVER >= 32)
4025
4026static PyObject*
4027DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4028{
4029 int err, max;
4030
4031 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4034
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_lk_max_locks(self->db_env, max);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4040}
4041
4042
4043static PyObject*
4044DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4045{
4046 int err, max;
4047
4048 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4051
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4057}
4058
4059
4060static PyObject*
4061DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4062{
4063 int err, max;
4064
4065 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4066 return NULL;
4067 CHECK_ENV_NOT_CLOSED(self);
4068
4069 MYDB_BEGIN_ALLOW_THREADS;
4070 err = self->db_env->set_lk_max_objects(self->db_env, max);
4071 MYDB_END_ALLOW_THREADS;
4072 RETURN_IF_ERR();
4073 RETURN_NONE();
4074}
4075
4076#endif
4077
4078
4079static PyObject*
4080DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4081{
4082 int err, mp_mmapsize;
4083
4084 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095
4096static PyObject*
4097DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4098{
4099 int err;
4100 char *dir;
4101
4102 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_tmp_dir(self->db_env, dir);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112
4113
4114static PyObject*
4115DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4116{
4117 int flags = 0;
4118 PyObject* txnobj = NULL;
4119 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004120 static const char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004121
4122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4123 &txnobj, &flags))
4124 return NULL;
4125
4126 if (!checkTxnObj(txnobj, &txn))
4127 return NULL;
4128 CHECK_ENV_NOT_CLOSED(self);
4129
4130 return (PyObject*)newDBTxnObject(self, txn, flags);
4131}
4132
4133
4134static PyObject*
4135DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4136{
4137 int err, kbyte=0, min=0, flags=0;
4138
4139 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4142
4143 MYDB_BEGIN_ALLOW_THREADS;
4144#if (DBVER >= 40)
4145 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4146#else
4147 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4148#endif
4149 MYDB_END_ALLOW_THREADS;
4150 RETURN_IF_ERR();
4151 RETURN_NONE();
4152}
4153
4154
4155static PyObject*
4156DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4157{
4158 int err, max;
4159
4160 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4161 return NULL;
4162 CHECK_ENV_NOT_CLOSED(self);
4163
4164 MYDB_BEGIN_ALLOW_THREADS;
4165 err = self->db_env->set_tx_max(self->db_env, max);
4166 MYDB_END_ALLOW_THREADS;
4167 RETURN_IF_ERR();
4168 RETURN_NONE();
4169}
4170
4171
4172static PyObject*
4173DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4174{
4175 int err, atype, flags=0;
4176 int aborted = 0;
4177
4178 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4179 return NULL;
4180 CHECK_ENV_NOT_CLOSED(self);
4181
4182 MYDB_BEGIN_ALLOW_THREADS;
4183#if (DBVER >= 40)
4184 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4185#else
4186 err = lock_detect(self->db_env, flags, atype, &aborted);
4187#endif
4188 MYDB_END_ALLOW_THREADS;
4189 RETURN_IF_ERR();
4190 return PyInt_FromLong(aborted);
4191}
4192
4193
4194static PyObject*
4195DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4196{
4197 int flags=0;
4198 int locker, lock_mode;
4199 DBT obj;
4200 PyObject* objobj;
4201
4202 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4203 return NULL;
4204
4205
4206 if (!make_dbt(objobj, &obj))
4207 return NULL;
4208
4209 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4210}
4211
4212
4213static PyObject*
4214DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4215{
4216 int err;
4217 u_int32_t theID;
4218
4219 if (!PyArg_ParseTuple(args, ":lock_id"))
4220 return NULL;
4221
4222 CHECK_ENV_NOT_CLOSED(self);
4223 MYDB_BEGIN_ALLOW_THREADS;
4224#if (DBVER >= 40)
4225 err = self->db_env->lock_id(self->db_env, &theID);
4226#else
4227 err = lock_id(self->db_env, &theID);
4228#endif
4229 MYDB_END_ALLOW_THREADS;
4230 RETURN_IF_ERR();
4231
4232 return PyInt_FromLong((long)theID);
4233}
4234
4235
4236static PyObject*
4237DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4238{
4239 int err;
4240 DBLockObject* dblockobj;
4241
4242 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4243 return NULL;
4244
4245 CHECK_ENV_NOT_CLOSED(self);
4246 MYDB_BEGIN_ALLOW_THREADS;
4247#if (DBVER >= 40)
4248 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4249#else
4250 err = lock_put(self->db_env, &dblockobj->lock);
4251#endif
4252 MYDB_END_ALLOW_THREADS;
4253 RETURN_IF_ERR();
4254 RETURN_NONE();
4255}
4256
4257
4258static PyObject*
4259DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4260{
4261 int err;
4262 DB_LOCK_STAT* sp;
4263 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004264 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004265
4266 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4267 return NULL;
4268 CHECK_ENV_NOT_CLOSED(self);
4269
4270 MYDB_BEGIN_ALLOW_THREADS;
4271#if (DBVER >= 40)
4272 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4273#else
4274#if (DBVER >= 33)
4275 err = lock_stat(self->db_env, &sp);
4276#else
4277 err = lock_stat(self->db_env, &sp, NULL);
4278#endif
4279#endif
4280 MYDB_END_ALLOW_THREADS;
4281 RETURN_IF_ERR();
4282
4283 /* Turn the stat structure into a dictionary */
4284 d = PyDict_New();
4285 if (d == NULL) {
4286 free(sp);
4287 return NULL;
4288 }
4289
4290#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4291
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004292#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004293 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004294#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004295 MAKE_ENTRY(nmodes);
4296#if (DBVER >= 32)
4297 MAKE_ENTRY(maxlocks);
4298 MAKE_ENTRY(maxlockers);
4299 MAKE_ENTRY(maxobjects);
4300 MAKE_ENTRY(nlocks);
4301 MAKE_ENTRY(maxnlocks);
4302#endif
4303 MAKE_ENTRY(nlockers);
4304 MAKE_ENTRY(maxnlockers);
4305#if (DBVER >= 32)
4306 MAKE_ENTRY(nobjects);
4307 MAKE_ENTRY(maxnobjects);
4308#endif
4309 MAKE_ENTRY(nrequests);
4310 MAKE_ENTRY(nreleases);
4311 MAKE_ENTRY(nnowaits);
4312 MAKE_ENTRY(nconflicts);
4313 MAKE_ENTRY(ndeadlocks);
4314 MAKE_ENTRY(regsize);
4315 MAKE_ENTRY(region_wait);
4316 MAKE_ENTRY(region_nowait);
4317
4318#undef MAKE_ENTRY
4319 free(sp);
4320 return d;
4321}
4322
4323
4324static PyObject*
4325DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4326{
4327 int flags=0;
4328 int err;
4329 char **log_list_start, **log_list;
4330 PyObject* list;
4331 PyObject* item = NULL;
4332
4333 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4334 return NULL;
4335
4336 CHECK_ENV_NOT_CLOSED(self);
4337 MYDB_BEGIN_ALLOW_THREADS;
4338#if (DBVER >= 40)
4339 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4340#elif (DBVER == 33)
4341 err = log_archive(self->db_env, &log_list, flags);
4342#else
4343 err = log_archive(self->db_env, &log_list, flags, NULL);
4344#endif
4345 MYDB_END_ALLOW_THREADS;
4346 RETURN_IF_ERR();
4347
4348 list = PyList_New(0);
4349 if (list == NULL) {
4350 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4351 return NULL;
4352 }
4353
4354 if (log_list) {
4355 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4356 item = PyString_FromString (*log_list);
4357 if (item == NULL) {
4358 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004359 PyErr_SetString(PyExc_MemoryError,
4360 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004361 list = NULL;
4362 break;
4363 }
4364 PyList_Append(list, item);
4365 Py_DECREF(item);
4366 }
4367 free(log_list_start);
4368 }
4369 return list;
4370}
4371
4372
4373static PyObject*
4374DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4375{
4376 int err;
4377 DB_TXN_STAT* sp;
4378 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004379 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004380
4381 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4382 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4384
4385 MYDB_BEGIN_ALLOW_THREADS;
4386#if (DBVER >= 40)
4387 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4388#elif (DBVER == 33)
4389 err = txn_stat(self->db_env, &sp);
4390#else
4391 err = txn_stat(self->db_env, &sp, NULL);
4392#endif
4393 MYDB_END_ALLOW_THREADS;
4394 RETURN_IF_ERR();
4395
4396 /* Turn the stat structure into a dictionary */
4397 d = PyDict_New();
4398 if (d == NULL) {
4399 free(sp);
4400 return NULL;
4401 }
4402
4403#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4404
4405 MAKE_ENTRY(time_ckp);
4406 MAKE_ENTRY(last_txnid);
4407 MAKE_ENTRY(maxtxns);
4408 MAKE_ENTRY(nactive);
4409 MAKE_ENTRY(maxnactive);
4410 MAKE_ENTRY(nbegins);
4411 MAKE_ENTRY(naborts);
4412 MAKE_ENTRY(ncommits);
4413 MAKE_ENTRY(regsize);
4414 MAKE_ENTRY(region_wait);
4415 MAKE_ENTRY(region_nowait);
4416
4417#undef MAKE_ENTRY
4418 free(sp);
4419 return d;
4420}
4421
4422
4423static PyObject*
4424DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4425{
4426 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004427 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004428
4429 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4430 return NULL;
4431 CHECK_ENV_NOT_CLOSED(self);
4432
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004433 if (self->moduleFlags.getReturnsNone)
4434 ++oldValue;
4435 if (self->moduleFlags.cursorSetReturnsNone)
4436 ++oldValue;
4437 self->moduleFlags.getReturnsNone = (flags >= 1);
4438 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004439 return PyInt_FromLong(oldValue);
4440}
4441
4442
4443/* --------------------------------------------------------------------- */
4444/* DBTxn methods */
4445
4446
4447static PyObject*
4448DBTxn_commit(DBTxnObject* self, PyObject* args)
4449{
4450 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004451 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004452
4453 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4454 return NULL;
4455
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004456 if (!self->txn) {
4457 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4458 "DBTxn must not be used after txn_commit or txn_abort"));
4459 return NULL;
4460 }
4461 txn = self->txn;
4462 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004463 MYDB_BEGIN_ALLOW_THREADS;
4464#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004465 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004466#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004467 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004468#endif
4469 MYDB_END_ALLOW_THREADS;
4470 RETURN_IF_ERR();
4471 RETURN_NONE();
4472}
4473
4474static PyObject*
4475DBTxn_prepare(DBTxnObject* self, PyObject* args)
4476{
4477#if (DBVER >= 33)
4478 int err;
4479 char* gid=NULL;
4480 int gid_size=0;
4481
4482 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4483 return NULL;
4484
4485 if (gid_size != DB_XIDDATASIZE) {
4486 PyErr_SetString(PyExc_TypeError,
4487 "gid must be DB_XIDDATASIZE bytes long");
4488 return NULL;
4489 }
4490
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004491 if (!self->txn) {
4492 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4493 "DBTxn must not be used after txn_commit or txn_abort"));
4494 return NULL;
4495 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004496 MYDB_BEGIN_ALLOW_THREADS;
4497#if (DBVER >= 40)
4498 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4499#else
4500 err = txn_prepare(self->txn, (u_int8_t*)gid);
4501#endif
4502 MYDB_END_ALLOW_THREADS;
4503 RETURN_IF_ERR();
4504 RETURN_NONE();
4505#else
4506 int err;
4507
4508 if (!PyArg_ParseTuple(args, ":prepare"))
4509 return NULL;
4510
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004511 if (!self->txn) {
4512 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4513 "DBTxn must not be used after txn_commit or txn_abort"));
4514 return NULL;
4515 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004516 MYDB_BEGIN_ALLOW_THREADS;
4517 err = txn_prepare(self->txn);
4518 MYDB_END_ALLOW_THREADS;
4519 RETURN_IF_ERR();
4520 RETURN_NONE();
4521#endif
4522}
4523
4524
4525static PyObject*
4526DBTxn_abort(DBTxnObject* self, PyObject* args)
4527{
4528 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004529 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004530
4531 if (!PyArg_ParseTuple(args, ":abort"))
4532 return NULL;
4533
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004534 if (!self->txn) {
4535 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4536 "DBTxn must not be used after txn_commit or txn_abort"));
4537 return NULL;
4538 }
4539 txn = self->txn;
4540 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MYDB_BEGIN_ALLOW_THREADS;
4542#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004543 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004544#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004545 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546#endif
4547 MYDB_END_ALLOW_THREADS;
4548 RETURN_IF_ERR();
4549 RETURN_NONE();
4550}
4551
4552
4553static PyObject*
4554DBTxn_id(DBTxnObject* self, PyObject* args)
4555{
4556 int id;
4557
4558 if (!PyArg_ParseTuple(args, ":id"))
4559 return NULL;
4560
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004561 if (!self->txn) {
4562 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4563 "DBTxn must not be used after txn_commit or txn_abort"));
4564 return NULL;
4565 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004566 MYDB_BEGIN_ALLOW_THREADS;
4567#if (DBVER >= 40)
4568 id = self->txn->id(self->txn);
4569#else
4570 id = txn_id(self->txn);
4571#endif
4572 MYDB_END_ALLOW_THREADS;
4573 return PyInt_FromLong(id);
4574}
4575
4576/* --------------------------------------------------------------------- */
4577/* Method definition tables and type objects */
4578
4579static PyMethodDef DB_methods[] = {
4580 {"append", (PyCFunction)DB_append, METH_VARARGS},
4581#if (DBVER >= 33)
4582 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4583#endif
4584 {"close", (PyCFunction)DB_close, METH_VARARGS},
4585#if (DBVER >= 32)
4586 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4587 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4588#endif
4589 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4590 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4591 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4592 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004593#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004594 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004595#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004596 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4597 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4598 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4599 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4600 {"join", (PyCFunction)DB_join, METH_VARARGS},
4601 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4602 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4603 {"items", (PyCFunction)DB_items, METH_VARARGS},
4604 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4605 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4606 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4607 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4608 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4609 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004610#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004611 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004612#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004614#if (DBVER >= 41)
4615 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4616#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004617 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4618 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4619 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4620 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4621 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4622 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4623 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4624 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4625 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4626#if (DBVER >= 32)
4627 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4628#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004629 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4631#if (DBVER >= 33)
4632 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4633#endif
4634 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4635 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4636 {"values", (PyCFunction)DB_values, METH_VARARGS},
4637 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4638 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4639 {NULL, NULL} /* sentinel */
4640};
4641
4642
4643static PyMappingMethods DB_mapping = {
4644 (inquiry)DB_length, /*mp_length*/
4645 (binaryfunc)DB_subscript, /*mp_subscript*/
4646 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4647};
4648
4649
4650static PyMethodDef DBCursor_methods[] = {
4651 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4652 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4653 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4654 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4655 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4656 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4657 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004658#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004659 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004660#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4662 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4663 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4664 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4665 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4666 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4667 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4668 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004669 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004670 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004671 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4672 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4673 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4674 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4675 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4676 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4677 {NULL, NULL} /* sentinel */
4678};
4679
4680
4681static PyMethodDef DBEnv_methods[] = {
4682 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4683 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4684 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004685#if (DBVER >= 41)
4686 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4687 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4688 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4689#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004690#if (DBVER >= 40)
4691 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4692#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004693 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004694 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4695 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4696#if (DBVER >= 32)
4697 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4698#endif
4699 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4700 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4701 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004702#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00004703 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004704#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004705 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4706 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4707#if (DBVER >= 32)
4708 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4709 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4710 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4711#endif
4712 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4713 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4714 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4715 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4716 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4717 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4718 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4719 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4720 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4721 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4722 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4723 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4724 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4725 {NULL, NULL} /* sentinel */
4726};
4727
4728
4729static PyMethodDef DBTxn_methods[] = {
4730 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4731 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4732 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4733 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4734 {NULL, NULL} /* sentinel */
4735};
4736
4737
4738static PyObject*
4739DB_getattr(DBObject* self, char *name)
4740{
4741 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4742}
4743
4744
4745static PyObject*
4746DBEnv_getattr(DBEnvObject* self, char *name)
4747{
4748 if (!strcmp(name, "db_home")) {
4749 CHECK_ENV_NOT_CLOSED(self);
4750 if (self->db_env->db_home == NULL) {
4751 RETURN_NONE();
4752 }
4753 return PyString_FromString(self->db_env->db_home);
4754 }
4755
4756 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4757}
4758
4759
4760static PyObject*
4761DBCursor_getattr(DBCursorObject* self, char *name)
4762{
4763 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4764}
4765
4766static PyObject*
4767DBTxn_getattr(DBTxnObject* self, char *name)
4768{
4769 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4770}
4771
4772static PyObject*
4773DBLock_getattr(DBLockObject* self, char *name)
4774{
4775 return NULL;
4776}
4777
4778statichere PyTypeObject DB_Type = {
4779 PyObject_HEAD_INIT(NULL)
4780 0, /*ob_size*/
4781 "DB", /*tp_name*/
4782 sizeof(DBObject), /*tp_basicsize*/
4783 0, /*tp_itemsize*/
4784 /* methods */
4785 (destructor)DB_dealloc, /*tp_dealloc*/
4786 0, /*tp_print*/
4787 (getattrfunc)DB_getattr, /*tp_getattr*/
4788 0, /*tp_setattr*/
4789 0, /*tp_compare*/
4790 0, /*tp_repr*/
4791 0, /*tp_as_number*/
4792 0, /*tp_as_sequence*/
4793 &DB_mapping,/*tp_as_mapping*/
4794 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004795#ifdef HAVE_WEAKREF
4796 0, /* tp_call */
4797 0, /* tp_str */
4798 0, /* tp_getattro */
4799 0, /* tp_setattro */
4800 0, /* tp_as_buffer */
4801 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4802 0, /* tp_doc */
4803 0, /* tp_traverse */
4804 0, /* tp_clear */
4805 0, /* tp_richcompare */
4806 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4807#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808};
4809
4810
4811statichere PyTypeObject DBCursor_Type = {
4812 PyObject_HEAD_INIT(NULL)
4813 0, /*ob_size*/
4814 "DBCursor", /*tp_name*/
4815 sizeof(DBCursorObject), /*tp_basicsize*/
4816 0, /*tp_itemsize*/
4817 /* methods */
4818 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4819 0, /*tp_print*/
4820 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4821 0, /*tp_setattr*/
4822 0, /*tp_compare*/
4823 0, /*tp_repr*/
4824 0, /*tp_as_number*/
4825 0, /*tp_as_sequence*/
4826 0, /*tp_as_mapping*/
4827 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004828#ifdef HAVE_WEAKREF
4829 0, /* tp_call */
4830 0, /* tp_str */
4831 0, /* tp_getattro */
4832 0, /* tp_setattro */
4833 0, /* tp_as_buffer */
4834 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4835 0, /* tp_doc */
4836 0, /* tp_traverse */
4837 0, /* tp_clear */
4838 0, /* tp_richcompare */
4839 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4840#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004841};
4842
4843
4844statichere PyTypeObject DBEnv_Type = {
4845 PyObject_HEAD_INIT(NULL)
4846 0, /*ob_size*/
4847 "DBEnv", /*tp_name*/
4848 sizeof(DBEnvObject), /*tp_basicsize*/
4849 0, /*tp_itemsize*/
4850 /* methods */
4851 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4852 0, /*tp_print*/
4853 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4854 0, /*tp_setattr*/
4855 0, /*tp_compare*/
4856 0, /*tp_repr*/
4857 0, /*tp_as_number*/
4858 0, /*tp_as_sequence*/
4859 0, /*tp_as_mapping*/
4860 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004861#ifdef HAVE_WEAKREF
4862 0, /* tp_call */
4863 0, /* tp_str */
4864 0, /* tp_getattro */
4865 0, /* tp_setattro */
4866 0, /* tp_as_buffer */
4867 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4868 0, /* tp_doc */
4869 0, /* tp_traverse */
4870 0, /* tp_clear */
4871 0, /* tp_richcompare */
4872 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4873#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004874};
4875
4876statichere PyTypeObject DBTxn_Type = {
4877 PyObject_HEAD_INIT(NULL)
4878 0, /*ob_size*/
4879 "DBTxn", /*tp_name*/
4880 sizeof(DBTxnObject), /*tp_basicsize*/
4881 0, /*tp_itemsize*/
4882 /* methods */
4883 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4884 0, /*tp_print*/
4885 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4886 0, /*tp_setattr*/
4887 0, /*tp_compare*/
4888 0, /*tp_repr*/
4889 0, /*tp_as_number*/
4890 0, /*tp_as_sequence*/
4891 0, /*tp_as_mapping*/
4892 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004893#ifdef HAVE_WEAKREF
4894 0, /* tp_call */
4895 0, /* tp_str */
4896 0, /* tp_getattro */
4897 0, /* tp_setattro */
4898 0, /* tp_as_buffer */
4899 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4900 0, /* tp_doc */
4901 0, /* tp_traverse */
4902 0, /* tp_clear */
4903 0, /* tp_richcompare */
4904 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4905#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004906};
4907
4908
4909statichere PyTypeObject DBLock_Type = {
4910 PyObject_HEAD_INIT(NULL)
4911 0, /*ob_size*/
4912 "DBLock", /*tp_name*/
4913 sizeof(DBLockObject), /*tp_basicsize*/
4914 0, /*tp_itemsize*/
4915 /* methods */
4916 (destructor)DBLock_dealloc, /*tp_dealloc*/
4917 0, /*tp_print*/
4918 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4919 0, /*tp_setattr*/
4920 0, /*tp_compare*/
4921 0, /*tp_repr*/
4922 0, /*tp_as_number*/
4923 0, /*tp_as_sequence*/
4924 0, /*tp_as_mapping*/
4925 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004926#ifdef HAVE_WEAKREF
4927 0, /* tp_call */
4928 0, /* tp_str */
4929 0, /* tp_getattro */
4930 0, /* tp_setattro */
4931 0, /* tp_as_buffer */
4932 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4933 0, /* tp_doc */
4934 0, /* tp_traverse */
4935 0, /* tp_clear */
4936 0, /* tp_richcompare */
4937 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4938#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004939};
4940
4941
4942/* --------------------------------------------------------------------- */
4943/* Module-level functions */
4944
4945static PyObject*
4946DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4947{
4948 PyObject* dbenvobj = NULL;
4949 int flags = 0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004950 static const char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004951
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004952 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4953 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004954 return NULL;
4955 if (dbenvobj == Py_None)
4956 dbenvobj = NULL;
4957 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4958 makeTypeError("DBEnv", dbenvobj);
4959 return NULL;
4960 }
4961
4962 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4963}
4964
4965
4966static PyObject*
4967DBEnv_construct(PyObject* self, PyObject* args)
4968{
4969 int flags = 0;
4970 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4971 return (PyObject* )newDBEnvObject(flags);
4972}
4973
4974
4975static char bsddb_version_doc[] =
4976"Returns a tuple of major, minor, and patch release numbers of the\n\
4977underlying DB library.";
4978
4979static PyObject*
4980bsddb_version(PyObject* self, PyObject* args)
4981{
4982 int major, minor, patch;
4983
4984 if (!PyArg_ParseTuple(args, ":version"))
4985 return NULL;
4986 db_version(&major, &minor, &patch);
4987 return Py_BuildValue("(iii)", major, minor, patch);
4988}
4989
4990
4991/* List of functions defined in the module */
4992
4993static PyMethodDef bsddb_methods[] = {
4994 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4995 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4996 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4997 {NULL, NULL} /* sentinel */
4998};
4999
5000
5001/* --------------------------------------------------------------------- */
5002/* Module initialization */
5003
5004
5005/* Convenience routine to export an integer value.
5006 * Errors are silently ignored, for better or for worse...
5007 */
5008#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5009
Gregory P. Smith41631e82003-09-21 00:08:14 +00005010#define MODULE_NAME_MAX_LEN 11
5011static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005012
5013DL_EXPORT(void) init_bsddb(void)
5014{
5015 PyObject* m;
5016 PyObject* d;
5017 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5018 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5019 PyObject* cvsid_s = PyString_FromString( rcs_id );
5020
5021 /* Initialize the type of the new type objects here; doing it here
5022 is required for portability to Windows without requiring C++. */
5023 DB_Type.ob_type = &PyType_Type;
5024 DBCursor_Type.ob_type = &PyType_Type;
5025 DBEnv_Type.ob_type = &PyType_Type;
5026 DBTxn_Type.ob_type = &PyType_Type;
5027 DBLock_Type.ob_type = &PyType_Type;
5028
5029
Mark Hammonda69d4092003-04-22 23:13:27 +00005030#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005031 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005032 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005033#endif
5034
5035 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005036 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005037
5038 /* Add some symbolic constants to the module */
5039 d = PyModule_GetDict(m);
5040 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5041 PyDict_SetItemString(d, "cvsid", cvsid_s);
5042 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5043 Py_DECREF(pybsddb_version_s);
5044 pybsddb_version_s = NULL;
5045 Py_DECREF(cvsid_s);
5046 cvsid_s = NULL;
5047 Py_DECREF(db_version_s);
5048 db_version_s = NULL;
5049
5050 ADD_INT(d, DB_VERSION_MAJOR);
5051 ADD_INT(d, DB_VERSION_MINOR);
5052 ADD_INT(d, DB_VERSION_PATCH);
5053
5054 ADD_INT(d, DB_MAX_PAGES);
5055 ADD_INT(d, DB_MAX_RECORDS);
5056
Gregory P. Smith41631e82003-09-21 00:08:14 +00005057#if (DBVER >= 42)
5058 ADD_INT(d, DB_RPCCLIENT);
5059#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005060 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005061 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5062 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5063#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005064 ADD_INT(d, DB_XA_CREATE);
5065
5066 ADD_INT(d, DB_CREATE);
5067 ADD_INT(d, DB_NOMMAP);
5068 ADD_INT(d, DB_THREAD);
5069
5070 ADD_INT(d, DB_FORCE);
5071 ADD_INT(d, DB_INIT_CDB);
5072 ADD_INT(d, DB_INIT_LOCK);
5073 ADD_INT(d, DB_INIT_LOG);
5074 ADD_INT(d, DB_INIT_MPOOL);
5075 ADD_INT(d, DB_INIT_TXN);
5076#if (DBVER >= 32)
5077 ADD_INT(d, DB_JOINENV);
5078#endif
5079
5080 ADD_INT(d, DB_RECOVER);
5081 ADD_INT(d, DB_RECOVER_FATAL);
5082 ADD_INT(d, DB_TXN_NOSYNC);
5083 ADD_INT(d, DB_USE_ENVIRON);
5084 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5085
5086 ADD_INT(d, DB_LOCKDOWN);
5087 ADD_INT(d, DB_PRIVATE);
5088 ADD_INT(d, DB_SYSTEM_MEM);
5089
5090 ADD_INT(d, DB_TXN_SYNC);
5091 ADD_INT(d, DB_TXN_NOWAIT);
5092
5093 ADD_INT(d, DB_EXCL);
5094 ADD_INT(d, DB_FCNTL_LOCKING);
5095 ADD_INT(d, DB_ODDFILESIZE);
5096 ADD_INT(d, DB_RDWRMASTER);
5097 ADD_INT(d, DB_RDONLY);
5098 ADD_INT(d, DB_TRUNCATE);
5099#if (DBVER >= 32)
5100 ADD_INT(d, DB_EXTENT);
5101 ADD_INT(d, DB_CDB_ALLDB);
5102 ADD_INT(d, DB_VERIFY);
5103#endif
5104 ADD_INT(d, DB_UPGRADE);
5105
5106 ADD_INT(d, DB_AGGRESSIVE);
5107 ADD_INT(d, DB_NOORDERCHK);
5108 ADD_INT(d, DB_ORDERCHKONLY);
5109 ADD_INT(d, DB_PR_PAGE);
5110#if ! (DBVER >= 33)
5111 ADD_INT(d, DB_VRFY_FLAGMASK);
5112 ADD_INT(d, DB_PR_HEADERS);
5113#endif
5114 ADD_INT(d, DB_PR_RECOVERYTEST);
5115 ADD_INT(d, DB_SALVAGE);
5116
5117 ADD_INT(d, DB_LOCK_NORUN);
5118 ADD_INT(d, DB_LOCK_DEFAULT);
5119 ADD_INT(d, DB_LOCK_OLDEST);
5120 ADD_INT(d, DB_LOCK_RANDOM);
5121 ADD_INT(d, DB_LOCK_YOUNGEST);
5122#if (DBVER >= 33)
5123 ADD_INT(d, DB_LOCK_MAXLOCKS);
5124 ADD_INT(d, DB_LOCK_MINLOCKS);
5125 ADD_INT(d, DB_LOCK_MINWRITE);
5126#endif
5127
5128
5129#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005130 /* docs say to use zero instead */
5131 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005132#else
5133 ADD_INT(d, DB_LOCK_CONFLICT);
5134#endif
5135
5136 ADD_INT(d, DB_LOCK_DUMP);
5137 ADD_INT(d, DB_LOCK_GET);
5138 ADD_INT(d, DB_LOCK_INHERIT);
5139 ADD_INT(d, DB_LOCK_PUT);
5140 ADD_INT(d, DB_LOCK_PUT_ALL);
5141 ADD_INT(d, DB_LOCK_PUT_OBJ);
5142
5143 ADD_INT(d, DB_LOCK_NG);
5144 ADD_INT(d, DB_LOCK_READ);
5145 ADD_INT(d, DB_LOCK_WRITE);
5146 ADD_INT(d, DB_LOCK_NOWAIT);
5147#if (DBVER >= 32)
5148 ADD_INT(d, DB_LOCK_WAIT);
5149#endif
5150 ADD_INT(d, DB_LOCK_IWRITE);
5151 ADD_INT(d, DB_LOCK_IREAD);
5152 ADD_INT(d, DB_LOCK_IWR);
5153#if (DBVER >= 33)
5154 ADD_INT(d, DB_LOCK_DIRTY);
5155 ADD_INT(d, DB_LOCK_WWRITE);
5156#endif
5157
5158 ADD_INT(d, DB_LOCK_RECORD);
5159 ADD_INT(d, DB_LOCK_UPGRADE);
5160#if (DBVER >= 32)
5161 ADD_INT(d, DB_LOCK_SWITCH);
5162#endif
5163#if (DBVER >= 33)
5164 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5165#endif
5166
5167 ADD_INT(d, DB_LOCK_NOWAIT);
5168 ADD_INT(d, DB_LOCK_RECORD);
5169 ADD_INT(d, DB_LOCK_UPGRADE);
5170
5171#if (DBVER >= 33)
5172 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005173#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005174 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005175#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 ADD_INT(d, DB_LSTAT_FREE);
5177 ADD_INT(d, DB_LSTAT_HELD);
5178#if (DBVER == 33)
5179 ADD_INT(d, DB_LSTAT_NOGRANT);
5180#endif
5181 ADD_INT(d, DB_LSTAT_PENDING);
5182 ADD_INT(d, DB_LSTAT_WAITING);
5183#endif
5184
5185 ADD_INT(d, DB_ARCH_ABS);
5186 ADD_INT(d, DB_ARCH_DATA);
5187 ADD_INT(d, DB_ARCH_LOG);
5188
5189 ADD_INT(d, DB_BTREE);
5190 ADD_INT(d, DB_HASH);
5191 ADD_INT(d, DB_RECNO);
5192 ADD_INT(d, DB_QUEUE);
5193 ADD_INT(d, DB_UNKNOWN);
5194
5195 ADD_INT(d, DB_DUP);
5196 ADD_INT(d, DB_DUPSORT);
5197 ADD_INT(d, DB_RECNUM);
5198 ADD_INT(d, DB_RENUMBER);
5199 ADD_INT(d, DB_REVSPLITOFF);
5200 ADD_INT(d, DB_SNAPSHOT);
5201
5202 ADD_INT(d, DB_JOIN_NOSORT);
5203
5204 ADD_INT(d, DB_AFTER);
5205 ADD_INT(d, DB_APPEND);
5206 ADD_INT(d, DB_BEFORE);
5207 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005208#if (DBVER >= 41)
5209 _addIntToDict(d, "DB_CHECKPOINT", 0);
5210#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005211 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005212 ADD_INT(d, DB_CURLSN);
5213#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005214#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005215 ADD_INT(d, DB_COMMIT);
5216#endif
5217 ADD_INT(d, DB_CONSUME);
5218#if (DBVER >= 32)
5219 ADD_INT(d, DB_CONSUME_WAIT);
5220#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005221 ADD_INT(d, DB_CURRENT);
5222#if (DBVER >= 33)
5223 ADD_INT(d, DB_FAST_STAT);
5224#endif
5225 ADD_INT(d, DB_FIRST);
5226 ADD_INT(d, DB_FLUSH);
5227 ADD_INT(d, DB_GET_BOTH);
5228 ADD_INT(d, DB_GET_RECNO);
5229 ADD_INT(d, DB_JOIN_ITEM);
5230 ADD_INT(d, DB_KEYFIRST);
5231 ADD_INT(d, DB_KEYLAST);
5232 ADD_INT(d, DB_LAST);
5233 ADD_INT(d, DB_NEXT);
5234 ADD_INT(d, DB_NEXT_DUP);
5235 ADD_INT(d, DB_NEXT_NODUP);
5236 ADD_INT(d, DB_NODUPDATA);
5237 ADD_INT(d, DB_NOOVERWRITE);
5238 ADD_INT(d, DB_NOSYNC);
5239 ADD_INT(d, DB_POSITION);
5240 ADD_INT(d, DB_PREV);
5241 ADD_INT(d, DB_PREV_NODUP);
5242 ADD_INT(d, DB_RECORDCOUNT);
5243 ADD_INT(d, DB_SET);
5244 ADD_INT(d, DB_SET_RANGE);
5245 ADD_INT(d, DB_SET_RECNO);
5246 ADD_INT(d, DB_WRITECURSOR);
5247
5248 ADD_INT(d, DB_OPFLAGS_MASK);
5249 ADD_INT(d, DB_RMW);
5250#if (DBVER >= 33)
5251 ADD_INT(d, DB_DIRTY_READ);
5252 ADD_INT(d, DB_MULTIPLE);
5253 ADD_INT(d, DB_MULTIPLE_KEY);
5254#endif
5255
5256#if (DBVER >= 33)
5257 ADD_INT(d, DB_DONOTINDEX);
5258#endif
5259
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005260#if (DBVER >= 41)
5261 _addIntToDict(d, "DB_INCOMPLETE", 0);
5262#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005263 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005264#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005265 ADD_INT(d, DB_KEYEMPTY);
5266 ADD_INT(d, DB_KEYEXIST);
5267 ADD_INT(d, DB_LOCK_DEADLOCK);
5268 ADD_INT(d, DB_LOCK_NOTGRANTED);
5269 ADD_INT(d, DB_NOSERVER);
5270 ADD_INT(d, DB_NOSERVER_HOME);
5271 ADD_INT(d, DB_NOSERVER_ID);
5272 ADD_INT(d, DB_NOTFOUND);
5273 ADD_INT(d, DB_OLD_VERSION);
5274 ADD_INT(d, DB_RUNRECOVERY);
5275 ADD_INT(d, DB_VERIFY_BAD);
5276#if (DBVER >= 33)
5277 ADD_INT(d, DB_PAGE_NOTFOUND);
5278 ADD_INT(d, DB_SECONDARY_BAD);
5279#endif
5280#if (DBVER >= 40)
5281 ADD_INT(d, DB_STAT_CLEAR);
5282 ADD_INT(d, DB_REGION_INIT);
5283 ADD_INT(d, DB_NOLOCKING);
5284 ADD_INT(d, DB_YIELDCPU);
5285 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5286 ADD_INT(d, DB_NOPANIC);
5287#endif
5288
Gregory P. Smith41631e82003-09-21 00:08:14 +00005289#if (DBVER >= 42)
5290 ADD_INT(d, DB_TIME_NOTGRANTED);
5291 ADD_INT(d, DB_TXN_NOT_DURABLE);
5292 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5293 ADD_INT(d, DB_LOG_AUTOREMOVE);
5294 ADD_INT(d, DB_DIRECT_LOG);
5295 ADD_INT(d, DB_DIRECT_DB);
5296 ADD_INT(d, DB_INIT_REP);
5297 ADD_INT(d, DB_ENCRYPT);
5298 ADD_INT(d, DB_CHKSUM);
5299#endif
5300
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005301#if (DBVER >= 43)
5302 ADD_INT(d, DB_LOG_INMEMORY);
5303 ADD_INT(d, DB_BUFFER_SMALL);
5304#endif
5305
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005306#if (DBVER >= 41)
5307 ADD_INT(d, DB_ENCRYPT_AES);
5308 ADD_INT(d, DB_AUTO_COMMIT);
5309#else
5310 /* allow berkeleydb 4.1 aware apps to run on older versions */
5311 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5312#endif
5313
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005314 ADD_INT(d, EINVAL);
5315 ADD_INT(d, EACCES);
5316 ADD_INT(d, ENOSPC);
5317 ADD_INT(d, ENOMEM);
5318 ADD_INT(d, EAGAIN);
5319 ADD_INT(d, EBUSY);
5320 ADD_INT(d, EEXIST);
5321 ADD_INT(d, ENOENT);
5322 ADD_INT(d, EPERM);
5323
Barry Warsaw1baa9822003-03-31 19:51:29 +00005324#if (DBVER >= 40)
5325 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5326 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5327#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005328
5329 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005330 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005331 PyDict_SetItemString(d, "DBError", DBError);
5332
Gregory P. Smithe9477062005-06-04 06:46:59 +00005333 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5334 * from both DBError and KeyError, since the API only supports
5335 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005336 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005337 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5338 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005339 Py_file_input, d, d);
5340 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005341 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005342 PyDict_DelItemString(d, "KeyError");
5343
5344
5345 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005346#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005347 PyDict_SetItemString(d, #name, name)
5348
5349#if !INCOMPLETE_IS_WARNING
5350 MAKE_EX(DBIncompleteError);
5351#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005352 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005353 MAKE_EX(DBKeyEmptyError);
5354 MAKE_EX(DBKeyExistError);
5355 MAKE_EX(DBLockDeadlockError);
5356 MAKE_EX(DBLockNotGrantedError);
5357 MAKE_EX(DBOldVersionError);
5358 MAKE_EX(DBRunRecoveryError);
5359 MAKE_EX(DBVerifyBadError);
5360 MAKE_EX(DBNoServerError);
5361 MAKE_EX(DBNoServerHomeError);
5362 MAKE_EX(DBNoServerIDError);
5363#if (DBVER >= 33)
5364 MAKE_EX(DBPageNotFoundError);
5365 MAKE_EX(DBSecondaryBadError);
5366#endif
5367
5368 MAKE_EX(DBInvalidArgError);
5369 MAKE_EX(DBAccessError);
5370 MAKE_EX(DBNoSpaceError);
5371 MAKE_EX(DBNoMemoryError);
5372 MAKE_EX(DBAgainError);
5373 MAKE_EX(DBBusyError);
5374 MAKE_EX(DBFileExistsError);
5375 MAKE_EX(DBNoSuchFileError);
5376 MAKE_EX(DBPermissionsError);
5377
5378#undef MAKE_EX
5379
5380 /* Check for errors */
5381 if (PyErr_Occurred()) {
5382 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005383 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005384 }
5385}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005386
5387/* allow this module to be named _pybsddb so that it can be installed
5388 * and imported on top of python >= 2.3 that includes its own older
5389 * copy of the library named _bsddb without importing the old version. */
5390DL_EXPORT(void) init_pybsddb(void)
5391{
5392 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5393 init_bsddb();
5394}