blob: fca203dc32131edc45a22d6d1b577791e4a30e5e [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. Smith8a474042006-01-27 07:05:40 +0000100#define PY_BSDDB_VERSION "4.4.2"
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;
Neal Norwitz62a21122006-01-25 05:21:55 +0000269 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000270#ifdef HAVE_WEAKREF
271 PyObject *in_weakreflist; /* List of weak references */
272#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000273} DBTxnObject;
274
275
276typedef struct {
277 PyObject_HEAD
278 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000279#ifdef HAVE_WEAKREF
280 PyObject *in_weakreflist; /* List of weak references */
281#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000282} DBLockObject;
283
284
285
286staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
287
288#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
289#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
290#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
291#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
292#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
293
294
295/* --------------------------------------------------------------------- */
296/* Utility macros and functions */
297
298#define RETURN_IF_ERR() \
299 if (makeDBError(err)) { \
300 return NULL; \
301 }
302
303#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
304
Gregory P. Smithe2767172003-11-02 08:06:29 +0000305#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
306 if ((nonNull) == NULL) { \
307 PyObject *errTuple = NULL; \
308 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
309 PyErr_SetObject((pyErrObj), errTuple); \
310 Py_DECREF(errTuple); \
311 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000312 }
313
Gregory P. Smithe2767172003-11-02 08:06:29 +0000314#define CHECK_DB_NOT_CLOSED(dbobj) \
315 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
316
317#define CHECK_ENV_NOT_CLOSED(env) \
318 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000319
320#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000321 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000322
323
324#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
325 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
326
327#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
328
329#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000330 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000331
332
333static int makeDBError(int err);
334
335
336/* Return the access method type of the DBObject */
337static int _DB_get_type(DBObject* self)
338{
339#if (DBVER >= 33)
340 DBTYPE type;
341 int err;
342 err = self->db->get_type(self->db, &type);
343 if (makeDBError(err)) {
344 return -1;
345 }
346 return type;
347#else
348 return self->db->get_type(self->db);
349#endif
350}
351
352
353/* Create a DBT structure (containing key and data values) from Python
354 strings. Returns 1 on success, 0 on an error. */
355static int make_dbt(PyObject* obj, DBT* dbt)
356{
357 CLEAR_DBT(*dbt);
358 if (obj == Py_None) {
359 /* no need to do anything, the structure has already been zeroed */
360 }
361 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
362 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000363 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000364 return 0;
365 }
366 return 1;
367}
368
369
370/* Recno and Queue DBs can have integer keys. This function figures out
371 what's been given, verifies that it's allowed, and then makes the DBT.
372
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000373 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000374static int
375make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000376{
377 db_recno_t recno;
378 int type;
379
380 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000381 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000382 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000383 if (type == -1)
384 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 if (type == DB_RECNO || type == DB_QUEUE) {
386 PyErr_SetString(
387 PyExc_TypeError,
388 "None keys not allowed for Recno and Queue DB's");
389 return 0;
390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000391 /* no need to do anything, the structure has already been zeroed */
392 }
393
394 else if (PyString_Check(keyobj)) {
395 /* verify access method type */
396 type = _DB_get_type(self);
397 if (type == -1)
398 return 0;
399 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000400 PyErr_SetString(
401 PyExc_TypeError,
402 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000403 return 0;
404 }
405
406 key->data = PyString_AS_STRING(keyobj);
407 key->size = PyString_GET_SIZE(keyobj);
408 }
409
410 else if (PyInt_Check(keyobj)) {
411 /* verify access method type */
412 type = _DB_get_type(self);
413 if (type == -1)
414 return 0;
415 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000416 /* if BTREE then an Integer key is allowed with the
417 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000418 *pflags |= DB_SET_RECNO;
419 }
420 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000421 PyErr_SetString(
422 PyExc_TypeError,
423 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000424 return 0;
425 }
426
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000427 /* Make a key out of the requested recno, use allocated space so DB
428 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000429 recno = PyInt_AS_LONG(keyobj);
430 key->data = malloc(sizeof(db_recno_t));
431 if (key->data == NULL) {
432 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
433 return 0;
434 }
435 key->ulen = key->size = sizeof(db_recno_t);
436 memcpy(key->data, &recno, sizeof(db_recno_t));
437 key->flags = DB_DBT_REALLOC;
438 }
439 else {
440 PyErr_Format(PyExc_TypeError,
441 "String or Integer object expected for key, %s found",
442 keyobj->ob_type->tp_name);
443 return 0;
444 }
445
446 return 1;
447}
448
449
450/* Add partial record access to an existing DBT data struct.
451 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
452 and the data storage/retrieval will be done using dlen and doff. */
453static int add_partial_dbt(DBT* d, int dlen, int doff) {
454 /* if neither were set we do nothing (-1 is the default value) */
455 if ((dlen == -1) && (doff == -1)) {
456 return 1;
457 }
458
459 if ((dlen < 0) || (doff < 0)) {
460 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
461 return 0;
462 }
463
464 d->flags = d->flags | DB_DBT_PARTIAL;
465 d->dlen = (unsigned int) dlen;
466 d->doff = (unsigned int) doff;
467 return 1;
468}
469
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000470/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
471/* TODO: make this use the native libc strlcpy() when available (BSD) */
472unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
473{
474 unsigned int srclen, copylen;
475
476 srclen = strlen(src);
477 if (n <= 0)
478 return srclen;
479 copylen = (srclen > n-1) ? n-1 : srclen;
480 /* populate dest[0] thru dest[copylen-1] */
481 memcpy(dest, src, copylen);
482 /* guarantee null termination */
483 dest[copylen] = 0;
484
485 return srclen;
486}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000487
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000488/* Callback used to save away more information about errors from the DB
489 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000490static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000492static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000493#else
494static void _db_errorCallback(const DB_ENV *db_env,
495 const char* prefix, const char* msg)
496#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000497{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000498 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000499}
500
501
502/* make a nice exception object to raise for errors. */
503static int makeDBError(int err)
504{
505 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000506 PyObject *errObj = NULL;
507 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508 int exceptionRaised = 0;
509
510 switch (err) {
511 case 0: /* successful, no error */ break;
512
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000513#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514 case DB_INCOMPLETE:
515#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000516 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000517 if (_db_errmsg[0]) {
518 strcat(errTxt, " -- ");
519 strcat(errTxt, _db_errmsg);
520 _db_errmsg[0] = 0;
521 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000522#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
524#else
525 fprintf(stderr, errTxt);
526 fprintf(stderr, "\n");
527#endif
528
529#else /* do an exception instead */
530 errObj = DBIncompleteError;
531#endif
532 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000533#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000534
535 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
536 case DB_KEYEXIST: errObj = DBKeyExistError; break;
537 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
538 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
539 case DB_NOTFOUND: errObj = DBNotFoundError; break;
540 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
541 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
542 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
543 case DB_NOSERVER: errObj = DBNoServerError; break;
544 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
545 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
546#if (DBVER >= 33)
547 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
548 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
549#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000550 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000551
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000552#if (DBVER >= 43)
553 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
554 case ENOMEM: errObj = PyExc_MemoryError; break;
555#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556 case EINVAL: errObj = DBInvalidArgError; break;
557 case EACCES: errObj = DBAccessError; break;
558 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000559 case EAGAIN: errObj = DBAgainError; break;
560 case EBUSY : errObj = DBBusyError; break;
561 case EEXIST: errObj = DBFileExistsError; break;
562 case ENOENT: errObj = DBNoSuchFileError; break;
563 case EPERM : errObj = DBPermissionsError; break;
564
565 default: errObj = DBError; break;
566 }
567
568 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000569 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000570 if (_db_errmsg[0]) {
571 strcat(errTxt, " -- ");
572 strcat(errTxt, _db_errmsg);
573 _db_errmsg[0] = 0;
574 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000575
576 errTuple = Py_BuildValue("(is)", err, errTxt);
577 PyErr_SetObject(errObj, errTuple);
578 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000579 }
580
581 return ((errObj != NULL) || exceptionRaised);
582}
583
584
585
586/* set a type exception */
587static void makeTypeError(char* expected, PyObject* found)
588{
589 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
590 expected, found->ob_type->tp_name);
591}
592
593
594/* verify that an obj is either None or a DBTxn, and set the txn pointer */
595static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
596{
597 if (txnobj == Py_None || txnobj == NULL) {
598 *txn = NULL;
599 return 1;
600 }
601 if (DBTxnObject_Check(txnobj)) {
602 *txn = ((DBTxnObject*)txnobj)->txn;
603 return 1;
604 }
605 else
606 makeTypeError("DBTxn", txnobj);
607 return 0;
608}
609
610
611/* Delete a key from a database
612 Returns 0 on success, -1 on an error. */
613static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
614{
615 int err;
616
617 MYDB_BEGIN_ALLOW_THREADS;
618 err = self->db->del(self->db, txn, key, 0);
619 MYDB_END_ALLOW_THREADS;
620 if (makeDBError(err)) {
621 return -1;
622 }
623 self->haveStat = 0;
624 return 0;
625}
626
627
628/* Store a key into a database
629 Returns 0 on success, -1 on an error. */
630static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
631{
632 int err;
633
634 MYDB_BEGIN_ALLOW_THREADS;
635 err = self->db->put(self->db, txn, key, data, flags);
636 MYDB_END_ALLOW_THREADS;
637 if (makeDBError(err)) {
638 return -1;
639 }
640 self->haveStat = 0;
641 return 0;
642}
643
644/* Get a key/data pair from a cursor */
645static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
646 PyObject *args, PyObject *kwargs, char *format)
647{
648 int err;
649 PyObject* retval = NULL;
650 DBT key, data;
651 int dlen = -1;
652 int doff = -1;
653 int flags = 0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000654 static const char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000655
656 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
657 &flags, &dlen, &doff))
658 return NULL;
659
660 CHECK_CURSOR_NOT_CLOSED(self);
661
662 flags |= extra_flags;
663 CLEAR_DBT(key);
664 CLEAR_DBT(data);
665 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
666 /* Tell BerkeleyDB to malloc the return value (thread safe) */
667 data.flags = DB_DBT_MALLOC;
668 key.flags = DB_DBT_MALLOC;
669 }
670 if (!add_partial_dbt(&data, dlen, doff))
671 return NULL;
672
673 MYDB_BEGIN_ALLOW_THREADS;
674 err = self->dbc->c_get(self->dbc, &key, &data, flags);
675 MYDB_END_ALLOW_THREADS;
676
Gregory P. Smithe9477062005-06-04 06:46:59 +0000677 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
678 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679 Py_INCREF(Py_None);
680 retval = Py_None;
681 }
682 else if (makeDBError(err)) {
683 retval = NULL;
684 }
685 else { /* otherwise, success! */
686
687 /* if Recno or Queue, return the key as an Int */
688 switch (_DB_get_type(self->mydb)) {
689 case -1:
690 retval = NULL;
691 break;
692
693 case DB_RECNO:
694 case DB_QUEUE:
695 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
696 data.data, data.size);
697 break;
698 case DB_HASH:
699 case DB_BTREE:
700 default:
701 retval = Py_BuildValue("s#s#", key.data, key.size,
702 data.data, data.size);
703 break;
704 }
705 }
706 if (!err) {
707 FREE_DBT(key);
708 FREE_DBT(data);
709 }
710 return retval;
711}
712
713
714/* add an integer to a dictionary using the given name as a key */
715static void _addIntToDict(PyObject* dict, char *name, int value)
716{
717 PyObject* v = PyInt_FromLong((long) value);
718 if (!v || PyDict_SetItemString(dict, name, v))
719 PyErr_Clear();
720
721 Py_XDECREF(v);
722}
723
724
725
726
727/* --------------------------------------------------------------------- */
728/* Allocators and deallocators */
729
730static DBObject*
731newDBObject(DBEnvObject* arg, int flags)
732{
733 DBObject* self;
734 DB_ENV* db_env = NULL;
735 int err;
736
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738 if (self == NULL)
739 return NULL;
740
741 self->haveStat = 0;
742 self->flags = 0;
743 self->setflags = 0;
744 self->myenvobj = NULL;
745#if (DBVER >= 33)
746 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000747 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000748 self->primaryDBType = 0;
749#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000750#ifdef HAVE_WEAKREF
751 self->in_weakreflist = NULL;
752#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000753
754 /* keep a reference to our python DBEnv object */
755 if (arg) {
756 Py_INCREF(arg);
757 self->myenvobj = arg;
758 db_env = arg->db_env;
759 }
760
761 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000762 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000764 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
765 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000766
767 MYDB_BEGIN_ALLOW_THREADS;
768 err = db_create(&self->db, db_env, flags);
769 self->db->set_errcall(self->db, _db_errorCallback);
770#if (DBVER >= 33)
771 self->db->app_private = (void*)self;
772#endif
773 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000774 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
775 * list so that a DBEnv can refuse to close without aborting any open
776 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (makeDBError(err)) {
778 if (self->myenvobj) {
779 Py_DECREF(self->myenvobj);
780 self->myenvobj = NULL;
781 }
782 self = NULL;
783 }
784 return self;
785}
786
787
788static void
789DB_dealloc(DBObject* self)
790{
791 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000792 /* avoid closing a DB when its DBEnv has been closed out from under
793 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000795 (self->myenvobj && self->myenvobj->db_env))
796 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797 MYDB_BEGIN_ALLOW_THREADS;
798 self->db->close(self->db, 0);
799 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000800#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000801 } else {
802 PyErr_Warn(PyExc_RuntimeWarning,
803 "DB could not be closed in destructor: DBEnv already closed");
804#endif
805 }
806 self->db = NULL;
807 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000808#ifdef HAVE_WEAKREF
809 if (self->in_weakreflist != NULL) {
810 PyObject_ClearWeakRefs((PyObject *) self);
811 }
812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813 if (self->myenvobj) {
814 Py_DECREF(self->myenvobj);
815 self->myenvobj = NULL;
816 }
817#if (DBVER >= 33)
818 if (self->associateCallback != NULL) {
819 Py_DECREF(self->associateCallback);
820 self->associateCallback = NULL;
821 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000822 if (self->btCompareCallback != NULL) {
823 Py_DECREF(self->btCompareCallback);
824 self->btCompareCallback = NULL;
825 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828}
829
830
831static DBCursorObject*
832newDBCursorObject(DBC* dbc, DBObject* db)
833{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000834 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 if (self == NULL)
836 return NULL;
837
838 self->dbc = dbc;
839 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000840#ifdef HAVE_WEAKREF
841 self->in_weakreflist = NULL;
842#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 Py_INCREF(self->mydb);
844 return self;
845}
846
847
848static void
849DBCursor_dealloc(DBCursorObject* self)
850{
851 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000852
853#ifdef HAVE_WEAKREF
854 if (self->in_weakreflist != NULL) {
855 PyObject_ClearWeakRefs((PyObject *) self);
856 }
857#endif
858
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 if (self->dbc != NULL) {
860 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000861 /* If the underlying database has been closed, we don't
862 need to do anything. If the environment has been closed
863 we need to leak, as BerkeleyDB will crash trying to access
864 the environment. There was an exception when the
865 user closed the environment even though there still was
866 a database open. */
867 if (self->mydb->db && self->mydb->myenvobj &&
868 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000869 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870 self->dbc = NULL;
871 MYDB_END_ALLOW_THREADS;
872 }
873 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000874 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875}
876
877
878static DBEnvObject*
879newDBEnvObject(int flags)
880{
881 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000882 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000883 if (self == NULL)
884 return NULL;
885
886 self->closed = 1;
887 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000888 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
889 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000890#ifdef HAVE_WEAKREF
891 self->in_weakreflist = NULL;
892#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893
894 MYDB_BEGIN_ALLOW_THREADS;
895 err = db_env_create(&self->db_env, flags);
896 MYDB_END_ALLOW_THREADS;
897 if (makeDBError(err)) {
898 self = NULL;
899 }
900 else {
901 self->db_env->set_errcall(self->db_env, _db_errorCallback);
902 }
903 return self;
904}
905
906
907static void
908DBEnv_dealloc(DBEnvObject* self)
909{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000910#ifdef HAVE_WEAKREF
911 if (self->in_weakreflist != NULL) {
912 PyObject_ClearWeakRefs((PyObject *) self);
913 }
914#endif
915
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000916 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917 MYDB_BEGIN_ALLOW_THREADS;
918 self->db_env->close(self->db_env, 0);
919 MYDB_END_ALLOW_THREADS;
920 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922}
923
924
925static DBTxnObject*
926newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
927{
928 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000929 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000932 Py_INCREF(myenv);
933 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000934#ifdef HAVE_WEAKREF
935 self->in_weakreflist = NULL;
936#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937
938 MYDB_BEGIN_ALLOW_THREADS;
939#if (DBVER >= 40)
940 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
941#else
942 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
943#endif
944 MYDB_END_ALLOW_THREADS;
945 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000946 Py_DECREF(self->env);
947 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948 self = NULL;
949 }
950 return self;
951}
952
953
954static void
955DBTxn_dealloc(DBTxnObject* self)
956{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000957#ifdef HAVE_WEAKREF
958 if (self->in_weakreflist != NULL) {
959 PyObject_ClearWeakRefs((PyObject *) self);
960 }
961#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962
Gregory P. Smith31c50652004-06-28 01:20:40 +0000963#ifdef HAVE_WARNINGS
964 if (self->txn) {
965 /* it hasn't been finalized, abort it! */
966 MYDB_BEGIN_ALLOW_THREADS;
967#if (DBVER >= 40)
968 self->txn->abort(self->txn);
969#else
970 txn_abort(self->txn);
971#endif
972 MYDB_END_ALLOW_THREADS;
973 PyErr_Warn(PyExc_RuntimeWarning,
974 "DBTxn aborted in destructor. No prior commit() or abort().");
975 }
976#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000977
Neal Norwitz62a21122006-01-25 05:21:55 +0000978 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980}
981
982
983static DBLockObject*
984newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
985 db_lockmode_t lock_mode, int flags)
986{
987 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000988 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000989 if (self == NULL)
990 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000991#ifdef HAVE_WEAKREF
992 self->in_weakreflist = NULL;
993#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994
995 MYDB_BEGIN_ALLOW_THREADS;
996#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000997 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
998 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999#else
1000 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1001#endif
1002 MYDB_END_ALLOW_THREADS;
1003 if (makeDBError(err)) {
1004 self = NULL;
1005 }
1006
1007 return self;
1008}
1009
1010
1011static void
1012DBLock_dealloc(DBLockObject* self)
1013{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001014#ifdef HAVE_WEAKREF
1015 if (self->in_weakreflist != NULL) {
1016 PyObject_ClearWeakRefs((PyObject *) self);
1017 }
1018#endif
1019 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001021 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022}
1023
1024
1025/* --------------------------------------------------------------------- */
1026/* DB methods */
1027
1028static PyObject*
1029DB_append(DBObject* self, PyObject* args)
1030{
1031 PyObject* txnobj = NULL;
1032 PyObject* dataobj;
1033 db_recno_t recno;
1034 DBT key, data;
1035 DB_TXN *txn = NULL;
1036
1037 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1038 return NULL;
1039
1040 CHECK_DB_NOT_CLOSED(self);
1041
1042 /* make a dummy key out of a recno */
1043 recno = 0;
1044 CLEAR_DBT(key);
1045 key.data = &recno;
1046 key.size = sizeof(recno);
1047 key.ulen = key.size;
1048 key.flags = DB_DBT_USERMEM;
1049
1050 if (!make_dbt(dataobj, &data)) return NULL;
1051 if (!checkTxnObj(txnobj, &txn)) return NULL;
1052
1053 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1054 return NULL;
1055
1056 return PyInt_FromLong(recno);
1057}
1058
1059
1060#if (DBVER >= 33)
1061
1062static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001063_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1064 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065{
1066 int retval = DB_DONOTINDEX;
1067 DBObject* secondaryDB = (DBObject*)db->app_private;
1068 PyObject* callback = secondaryDB->associateCallback;
1069 int type = secondaryDB->primaryDBType;
1070 PyObject* key;
1071 PyObject* data;
1072 PyObject* args;
1073 PyObject* result;
1074
1075
1076 if (callback != NULL) {
1077 MYDB_BEGIN_BLOCK_THREADS;
1078
1079 if (type == DB_RECNO || type == DB_QUEUE) {
1080 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1081 }
1082 else {
1083 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1084 }
1085 data = PyString_FromStringAndSize(priData->data, priData->size);
1086 args = PyTuple_New(2);
1087 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1088 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1089
1090 result = PyEval_CallObject(callback, args);
1091
1092 if (result == NULL) {
1093 PyErr_Print();
1094 }
1095 else if (result == Py_None) {
1096 retval = DB_DONOTINDEX;
1097 }
1098 else if (PyInt_Check(result)) {
1099 retval = PyInt_AsLong(result);
1100 }
1101 else if (PyString_Check(result)) {
1102 char* data;
1103 int size;
1104
1105 CLEAR_DBT(*secKey);
1106#if PYTHON_API_VERSION <= 1007
1107 /* 1.5 compatibility */
1108 size = PyString_Size(result);
1109 data = PyString_AsString(result);
1110#else
1111 PyString_AsStringAndSize(result, &data, &size);
1112#endif
1113 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1114 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001115 if (secKey->data) {
1116 memcpy(secKey->data, data, size);
1117 secKey->size = size;
1118 retval = 0;
1119 }
1120 else {
1121 PyErr_SetString(PyExc_MemoryError,
1122 "malloc failed in _db_associateCallback");
1123 PyErr_Print();
1124 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125 }
1126 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001127 PyErr_SetString(
1128 PyExc_TypeError,
1129 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130 PyErr_Print();
1131 }
1132
1133 Py_DECREF(args);
1134 if (result) {
1135 Py_DECREF(result);
1136 }
1137
1138 MYDB_END_BLOCK_THREADS;
1139 }
1140 return retval;
1141}
1142
1143
1144static PyObject*
1145DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1146{
1147 int err, flags=0;
1148 DBObject* secondaryDB;
1149 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001150#if (DBVER >= 41)
1151 PyObject *txnobj = NULL;
1152 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001153 static const char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1154 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001155#else
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001156 static const char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001157#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001158
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001159#if (DBVER >= 41)
1160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1161 &secondaryDB, &callback, &flags,
1162 &txnobj)) {
1163#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001165 &secondaryDB, &callback, &flags)) {
1166#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001167 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001168 }
1169
1170#if (DBVER >= 41)
1171 if (!checkTxnObj(txnobj, &txn)) return NULL;
1172#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173
1174 CHECK_DB_NOT_CLOSED(self);
1175 if (!DBObject_Check(secondaryDB)) {
1176 makeTypeError("DB", (PyObject*)secondaryDB);
1177 return NULL;
1178 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001179 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001180 if (callback == Py_None) {
1181 callback = NULL;
1182 }
1183 else if (!PyCallable_Check(callback)) {
1184 makeTypeError("Callable", callback);
1185 return NULL;
1186 }
1187
1188 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001189 Py_XDECREF(secondaryDB->associateCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001190 Py_INCREF(callback);
1191 secondaryDB->associateCallback = callback;
1192 secondaryDB->primaryDBType = _DB_get_type(self);
1193
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001194 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1195 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1196 * The global interepreter lock is not initialized until the first
1197 * thread is created using thread.start_new_thread() or fork() is
1198 * called. that would cause the ALLOW_THREADS here to segfault due
1199 * to a null pointer reference if no threads or child processes
1200 * have been created. This works around that and is a no-op if
1201 * threads have already been initialized.
1202 * (see pybsddb-users mailing list post on 2002-08-07)
1203 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001204#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001205 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001206#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001208#if (DBVER >= 41)
1209 err = self->db->associate(self->db,
1210 txn,
1211 secondaryDB->db,
1212 _db_associateCallback,
1213 flags);
1214#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001215 err = self->db->associate(self->db,
1216 secondaryDB->db,
1217 _db_associateCallback,
1218 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001219#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001220 MYDB_END_ALLOW_THREADS;
1221
1222 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001223 Py_XDECREF(secondaryDB->associateCallback);
1224 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225 secondaryDB->primaryDBType = 0;
1226 }
1227
1228 RETURN_IF_ERR();
1229 RETURN_NONE();
1230}
1231
1232
1233#endif
1234
1235
1236static PyObject*
1237DB_close(DBObject* self, PyObject* args)
1238{
1239 int err, flags=0;
1240 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1241 return NULL;
1242 if (self->db != NULL) {
1243 if (self->myenvobj)
1244 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001246 self->db = NULL;
1247 RETURN_IF_ERR();
1248 }
1249 RETURN_NONE();
1250}
1251
1252
1253#if (DBVER >= 32)
1254static PyObject*
1255_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1256{
1257 int err, flags=0, type;
1258 PyObject* txnobj = NULL;
1259 PyObject* retval = NULL;
1260 DBT key, data;
1261 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001262 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001263
1264 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1265 &txnobj, &flags))
1266 return NULL;
1267
1268 CHECK_DB_NOT_CLOSED(self);
1269 type = _DB_get_type(self);
1270 if (type == -1)
1271 return NULL;
1272 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001273 PyErr_SetString(PyExc_TypeError,
1274 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001275 return NULL;
1276 }
1277 if (!checkTxnObj(txnobj, &txn))
1278 return NULL;
1279
1280 CLEAR_DBT(key);
1281 CLEAR_DBT(data);
1282 if (CHECK_DBFLAG(self, DB_THREAD)) {
1283 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1284 data.flags = DB_DBT_MALLOC;
1285 key.flags = DB_DBT_MALLOC;
1286 }
1287
1288 MYDB_BEGIN_ALLOW_THREADS;
1289 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1290 MYDB_END_ALLOW_THREADS;
1291
Gregory P. Smithe9477062005-06-04 06:46:59 +00001292 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1293 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294 err = 0;
1295 Py_INCREF(Py_None);
1296 retval = Py_None;
1297 }
1298 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001299 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1300 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001301 FREE_DBT(key);
1302 FREE_DBT(data);
1303 }
1304
1305 RETURN_IF_ERR();
1306 return retval;
1307}
1308
1309static PyObject*
1310DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1311{
1312 return _DB_consume(self, args, kwargs, DB_CONSUME);
1313}
1314
1315static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001316DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1317 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001318{
1319 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1320}
1321#endif
1322
1323
1324
1325static PyObject*
1326DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1327{
1328 int err, flags=0;
1329 DBC* dbc;
1330 PyObject* txnobj = NULL;
1331 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001332 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333
1334 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1335 &txnobj, &flags))
1336 return NULL;
1337 CHECK_DB_NOT_CLOSED(self);
1338 if (!checkTxnObj(txnobj, &txn))
1339 return NULL;
1340
1341 MYDB_BEGIN_ALLOW_THREADS;
1342 err = self->db->cursor(self->db, txn, &dbc, flags);
1343 MYDB_END_ALLOW_THREADS;
1344 RETURN_IF_ERR();
1345 return (PyObject*) newDBCursorObject(dbc, self);
1346}
1347
1348
1349static PyObject*
1350DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1351{
1352 PyObject* txnobj = NULL;
1353 int flags = 0;
1354 PyObject* keyobj;
1355 DBT key;
1356 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001357 static const char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001358
1359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1360 &keyobj, &txnobj, &flags))
1361 return NULL;
1362 CHECK_DB_NOT_CLOSED(self);
1363 if (!make_key_dbt(self, keyobj, &key, NULL))
1364 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001365 if (!checkTxnObj(txnobj, &txn)) {
1366 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001367 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001368 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001370 if (-1 == _DB_delete(self, txn, &key, 0)) {
1371 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001373 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001374
1375 FREE_DBT(key);
1376 RETURN_NONE();
1377}
1378
1379
1380static PyObject*
1381DB_fd(DBObject* self, PyObject* args)
1382{
1383 int err, the_fd;
1384
1385 if (!PyArg_ParseTuple(args,":fd"))
1386 return NULL;
1387 CHECK_DB_NOT_CLOSED(self);
1388
1389 MYDB_BEGIN_ALLOW_THREADS;
1390 err = self->db->fd(self->db, &the_fd);
1391 MYDB_END_ALLOW_THREADS;
1392 RETURN_IF_ERR();
1393 return PyInt_FromLong(the_fd);
1394}
1395
1396
1397static PyObject*
1398DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1399{
1400 int err, flags=0;
1401 PyObject* txnobj = NULL;
1402 PyObject* keyobj;
1403 PyObject* dfltobj = NULL;
1404 PyObject* retval = NULL;
1405 int dlen = -1;
1406 int doff = -1;
1407 DBT key, data;
1408 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001409 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1410 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001413 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1414 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001415 return NULL;
1416
1417 CHECK_DB_NOT_CLOSED(self);
1418 if (!make_key_dbt(self, keyobj, &key, &flags))
1419 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001420 if (!checkTxnObj(txnobj, &txn)) {
1421 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001423 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001424
1425 CLEAR_DBT(data);
1426 if (CHECK_DBFLAG(self, DB_THREAD)) {
1427 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1428 data.flags = DB_DBT_MALLOC;
1429 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001430 if (!add_partial_dbt(&data, dlen, doff)) {
1431 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001432 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001433 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434
1435 MYDB_BEGIN_ALLOW_THREADS;
1436 err = self->db->get(self->db, txn, &key, &data, flags);
1437 MYDB_END_ALLOW_THREADS;
1438
Gregory P. Smithe9477062005-06-04 06:46:59 +00001439 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001440 err = 0;
1441 Py_INCREF(dfltobj);
1442 retval = dfltobj;
1443 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001444 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1445 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001446 err = 0;
1447 Py_INCREF(Py_None);
1448 retval = Py_None;
1449 }
1450 else if (!err) {
1451 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001452 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1453 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454 else /* return just the data */
1455 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456 FREE_DBT(data);
1457 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001458 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001459
1460 RETURN_IF_ERR();
1461 return retval;
1462}
1463
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001464#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001465static PyObject*
1466DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1467{
1468 int err, flags=0;
1469 PyObject* txnobj = NULL;
1470 PyObject* keyobj;
1471 PyObject* dfltobj = NULL;
1472 PyObject* retval = NULL;
1473 int dlen = -1;
1474 int doff = -1;
1475 DBT key, pkey, data;
1476 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001477 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1478 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001479
1480 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1481 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1482 &doff))
1483 return NULL;
1484
1485 CHECK_DB_NOT_CLOSED(self);
1486 if (!make_key_dbt(self, keyobj, &key, &flags))
1487 return NULL;
1488 if (!checkTxnObj(txnobj, &txn)) {
1489 FREE_DBT(key);
1490 return NULL;
1491 }
1492
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
1495 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1496 data.flags = DB_DBT_MALLOC;
1497 }
1498 if (!add_partial_dbt(&data, dlen, doff)) {
1499 FREE_DBT(key);
1500 return NULL;
1501 }
1502
1503 CLEAR_DBT(pkey);
1504 pkey.flags = DB_DBT_MALLOC;
1505
1506 MYDB_BEGIN_ALLOW_THREADS;
1507 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1508 MYDB_END_ALLOW_THREADS;
1509
Gregory P. Smithe9477062005-06-04 06:46:59 +00001510 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001511 err = 0;
1512 Py_INCREF(dfltobj);
1513 retval = dfltobj;
1514 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001515 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1516 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001517 err = 0;
1518 Py_INCREF(Py_None);
1519 retval = Py_None;
1520 }
1521 else if (!err) {
1522 PyObject *pkeyObj;
1523 PyObject *dataObj;
1524 dataObj = PyString_FromStringAndSize(data.data, data.size);
1525
1526 if (self->primaryDBType == DB_RECNO ||
1527 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001528 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001529 else
1530 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1531
1532 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1533 {
1534 PyObject *keyObj;
1535 int type = _DB_get_type(self);
1536 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001537 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001538 else
1539 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001540#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001541 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001542#else
1543 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1544#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001545 }
1546 else /* return just the pkey and data */
1547 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001548#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001549 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001550#else
1551 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1552#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001553 }
1554 FREE_DBT(pkey);
1555 FREE_DBT(data);
1556 }
1557 FREE_DBT(key);
1558
1559 RETURN_IF_ERR();
1560 return retval;
1561}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001562#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001563
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001564
1565/* Return size of entry */
1566static PyObject*
1567DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1568{
1569 int err, flags=0;
1570 PyObject* txnobj = NULL;
1571 PyObject* keyobj;
1572 PyObject* retval = NULL;
1573 DBT key, data;
1574 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001575 static const char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001576
1577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1578 &keyobj, &txnobj))
1579 return NULL;
1580 CHECK_DB_NOT_CLOSED(self);
1581 if (!make_key_dbt(self, keyobj, &key, &flags))
1582 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001583 if (!checkTxnObj(txnobj, &txn)) {
1584 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001585 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001586 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001587 CLEAR_DBT(data);
1588
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001589 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1590 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001591 data.flags = DB_DBT_USERMEM;
1592 data.ulen = 0;
1593 MYDB_BEGIN_ALLOW_THREADS;
1594 err = self->db->get(self->db, txn, &key, &data, flags);
1595 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001596 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001597 retval = PyInt_FromLong((long)data.size);
1598 err = 0;
1599 }
1600
1601 FREE_DBT(key);
1602 FREE_DBT(data);
1603 RETURN_IF_ERR();
1604 return retval;
1605}
1606
1607
1608static PyObject*
1609DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1610{
1611 int err, flags=0;
1612 PyObject* txnobj = NULL;
1613 PyObject* keyobj;
1614 PyObject* dataobj;
1615 PyObject* retval = NULL;
1616 DBT key, data;
1617 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001618 static const char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001619
1620
1621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1622 &keyobj, &dataobj, &txnobj, &flags))
1623 return NULL;
1624
1625 CHECK_DB_NOT_CLOSED(self);
1626 if (!make_key_dbt(self, keyobj, &key, NULL))
1627 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001628 if ( !make_dbt(dataobj, &data) ||
1629 !checkTxnObj(txnobj, &txn) )
1630 {
1631 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001632 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001633 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634
1635 flags |= DB_GET_BOTH;
1636
1637 if (CHECK_DBFLAG(self, DB_THREAD)) {
1638 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1639 data.flags = DB_DBT_MALLOC;
1640 /* TODO: Is this flag needed? We're passing a data object that should
1641 match what's in the DB, so there should be no need to malloc.
1642 We run the risk of freeing something twice! Check this. */
1643 }
1644
1645 MYDB_BEGIN_ALLOW_THREADS;
1646 err = self->db->get(self->db, txn, &key, &data, flags);
1647 MYDB_END_ALLOW_THREADS;
1648
Gregory P. Smithe9477062005-06-04 06:46:59 +00001649 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1650 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001651 err = 0;
1652 Py_INCREF(Py_None);
1653 retval = Py_None;
1654 }
1655 else if (!err) {
1656 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1657 FREE_DBT(data); /* Only if retrieval was successful */
1658 }
1659
1660 FREE_DBT(key);
1661 RETURN_IF_ERR();
1662 return retval;
1663}
1664
1665
1666static PyObject*
1667DB_get_byteswapped(DBObject* self, PyObject* args)
1668{
1669#if (DBVER >= 33)
1670 int err = 0;
1671#endif
1672 int retval = -1;
1673
1674 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1675 return NULL;
1676 CHECK_DB_NOT_CLOSED(self);
1677
1678#if (DBVER >= 33)
1679 MYDB_BEGIN_ALLOW_THREADS;
1680 err = self->db->get_byteswapped(self->db, &retval);
1681 MYDB_END_ALLOW_THREADS;
1682 RETURN_IF_ERR();
1683#else
1684 MYDB_BEGIN_ALLOW_THREADS;
1685 retval = self->db->get_byteswapped(self->db);
1686 MYDB_END_ALLOW_THREADS;
1687#endif
1688 return PyInt_FromLong(retval);
1689}
1690
1691
1692static PyObject*
1693DB_get_type(DBObject* self, PyObject* args)
1694{
1695 int type;
1696
1697 if (!PyArg_ParseTuple(args,":get_type"))
1698 return NULL;
1699 CHECK_DB_NOT_CLOSED(self);
1700
1701 MYDB_BEGIN_ALLOW_THREADS;
1702 type = _DB_get_type(self);
1703 MYDB_END_ALLOW_THREADS;
1704 if (type == -1)
1705 return NULL;
1706 return PyInt_FromLong(type);
1707}
1708
1709
1710static PyObject*
1711DB_join(DBObject* self, PyObject* args)
1712{
1713 int err, flags=0;
1714 int length, x;
1715 PyObject* cursorsObj;
1716 DBC** cursors;
1717 DBC* dbc;
1718
1719
1720 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1721 return NULL;
1722
1723 CHECK_DB_NOT_CLOSED(self);
1724
1725 if (!PySequence_Check(cursorsObj)) {
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 return NULL;
1729 }
1730
1731 length = PyObject_Length(cursorsObj);
1732 cursors = malloc((length+1) * sizeof(DBC*));
1733 cursors[length] = NULL;
1734 for (x=0; x<length; x++) {
1735 PyObject* item = PySequence_GetItem(cursorsObj, x);
1736 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001737 PyErr_SetString(PyExc_TypeError,
1738 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001739 free(cursors);
1740 return NULL;
1741 }
1742 cursors[x] = ((DBCursorObject*)item)->dbc;
1743 }
1744
1745 MYDB_BEGIN_ALLOW_THREADS;
1746 err = self->db->join(self->db, cursors, &dbc, flags);
1747 MYDB_END_ALLOW_THREADS;
1748 free(cursors);
1749 RETURN_IF_ERR();
1750
Gregory P. Smith7441e652003-11-03 21:35:31 +00001751 /* FIXME: this is a buggy interface. The returned cursor
1752 contains internal references to the passed in cursors
1753 but does not hold python references to them or prevent
1754 them from being closed prematurely. This can cause
1755 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756 return (PyObject*) newDBCursorObject(dbc, self);
1757}
1758
1759
1760static PyObject*
1761DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1762{
1763 int err, flags=0;
1764 PyObject* txnobj = NULL;
1765 PyObject* keyobj;
1766 DBT key;
1767 DB_TXN *txn = NULL;
1768 DB_KEY_RANGE range;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001769 static const char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001770
1771 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1772 &keyobj, &txnobj, &flags))
1773 return NULL;
1774 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001775 if (!make_dbt(keyobj, &key))
1776 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001777 return NULL;
1778 if (!checkTxnObj(txnobj, &txn))
1779 return NULL;
1780
1781 MYDB_BEGIN_ALLOW_THREADS;
1782 err = self->db->key_range(self->db, txn, &key, &range, flags);
1783 MYDB_END_ALLOW_THREADS;
1784
1785 RETURN_IF_ERR();
1786 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1787}
1788
1789
1790static PyObject*
1791DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1792{
1793 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1794 char* filename = NULL;
1795 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001796#if (DBVER >= 41)
1797 PyObject *txnobj = NULL;
1798 DB_TXN *txn = NULL;
1799 /* with dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001800 static const char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001801 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1802 /* without dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001803 static const char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001804 "filename", "dbtype", "flags", "mode", "txn", NULL};
1805#else
1806 /* with dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001807 static const char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001808 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1809 /* without dbname */
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001810 static const char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001811 "filename", "dbtype", "flags", "mode", NULL};
1812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001813
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001814#if (DBVER >= 41)
1815 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1816 &filename, &dbname, &type, &flags, &mode,
1817 &txnobj))
1818#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001819 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001820 &filename, &dbname, &type, &flags,
1821 &mode))
1822#endif
1823 {
1824 PyErr_Clear();
1825 type = DB_UNKNOWN; flags = 0; mode = 0660;
1826 filename = NULL; dbname = NULL;
1827#if (DBVER >= 41)
1828 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1829 kwnames_basic,
1830 &filename, &type, &flags, &mode,
1831 &txnobj))
1832 return NULL;
1833#else
1834 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1835 kwnames_basic,
1836 &filename, &type, &flags, &mode))
1837 return NULL;
1838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001839 }
1840
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001841#if (DBVER >= 41)
1842 if (!checkTxnObj(txnobj, &txn)) return NULL;
1843#endif
1844
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 if (NULL == self->db) {
1846 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1847 "Cannot call open() twice for DB object"));
1848 return NULL;
1849 }
1850
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001851#if 0 && (DBVER >= 41)
1852 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1853 && (self->myenvobj->flags & DB_INIT_TXN))
1854 {
1855 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1856 * explicitly passed) but we are in a transaction ready environment:
1857 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1858 * to work on BerkeleyDB 4.1 without needing to modify their
1859 * DBEnv or DB open calls.
1860 * TODO make this behaviour of the library configurable.
1861 */
1862 flags |= DB_AUTO_COMMIT;
1863 }
1864#endif
1865
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001866 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001867#if (DBVER >= 41)
1868 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1869#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001870 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001871#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001872 MYDB_END_ALLOW_THREADS;
1873 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001874 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875 self->db = NULL;
1876 return NULL;
1877 }
1878
1879 self->flags = flags;
1880 RETURN_NONE();
1881}
1882
1883
1884static PyObject*
1885DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1886{
1887 int flags=0;
1888 PyObject* txnobj = NULL;
1889 int dlen = -1;
1890 int doff = -1;
1891 PyObject* keyobj, *dataobj, *retval;
1892 DBT key, data;
1893 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001894 static const char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1895 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001896
1897 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1898 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1899 return NULL;
1900
1901 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001902 if (!make_key_dbt(self, keyobj, &key, NULL))
1903 return NULL;
1904 if ( !make_dbt(dataobj, &data) ||
1905 !add_partial_dbt(&data, dlen, doff) ||
1906 !checkTxnObj(txnobj, &txn) )
1907 {
1908 FREE_DBT(key);
1909 return NULL;
1910 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911
1912 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1913 FREE_DBT(key);
1914 return NULL;
1915 }
1916
1917 if (flags & DB_APPEND)
1918 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1919 else {
1920 retval = Py_None;
1921 Py_INCREF(retval);
1922 }
1923 FREE_DBT(key);
1924 return retval;
1925}
1926
1927
1928
1929static PyObject*
1930DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1931{
1932 char* filename;
1933 char* database = NULL;
1934 int err, flags=0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001935 static const char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936
1937 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1938 &filename, &database, &flags))
1939 return NULL;
1940 CHECK_DB_NOT_CLOSED(self);
1941
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001942 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001943 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 RETURN_IF_ERR();
1945 RETURN_NONE();
1946}
1947
1948
1949
1950static PyObject*
1951DB_rename(DBObject* self, PyObject* args)
1952{
1953 char* filename;
1954 char* database;
1955 char* newname;
1956 int err, flags=0;
1957
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001958 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1959 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 return NULL;
1961 CHECK_DB_NOT_CLOSED(self);
1962
1963 MYDB_BEGIN_ALLOW_THREADS;
1964 err = self->db->rename(self->db, filename, database, newname, flags);
1965 MYDB_END_ALLOW_THREADS;
1966 RETURN_IF_ERR();
1967 RETURN_NONE();
1968}
1969
1970
1971static PyObject*
1972DB_set_bt_minkey(DBObject* self, PyObject* args)
1973{
1974 int err, minkey;
1975
1976 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1977 return NULL;
1978 CHECK_DB_NOT_CLOSED(self);
1979
1980 MYDB_BEGIN_ALLOW_THREADS;
1981 err = self->db->set_bt_minkey(self->db, minkey);
1982 MYDB_END_ALLOW_THREADS;
1983 RETURN_IF_ERR();
1984 RETURN_NONE();
1985}
1986
Neal Norwitz84562352005-10-20 04:30:15 +00001987#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001988static int
1989_default_cmp (const DBT *leftKey,
1990 const DBT *rightKey)
1991{
1992 int res;
1993 int lsize = leftKey->size, rsize = rightKey->size;
1994
1995 res = memcmp (leftKey->data, rightKey->data,
1996 lsize < rsize ? lsize : rsize);
1997
1998 if (res == 0) {
1999 if (lsize < rsize) {
2000 res = -1;
2001 }
2002 else if (lsize > rsize) {
2003 res = 1;
2004 }
2005 }
2006 return res;
2007}
2008
2009static int
2010_db_compareCallback (DB* db,
2011 const DBT *leftKey,
2012 const DBT *rightKey)
2013{
2014 int res = 0;
2015 PyObject *args;
2016 PyObject *result;
2017 PyObject *leftObject;
2018 PyObject *rightObject;
2019 DBObject *self = (DBObject *) db->app_private;
2020
2021 if (self == NULL || self->btCompareCallback == NULL) {
2022 MYDB_BEGIN_BLOCK_THREADS;
2023 PyErr_SetString (PyExc_TypeError,
2024 (self == 0
2025 ? "DB_bt_compare db is NULL."
2026 : "DB_bt_compare callback is NULL."));
2027 /* we're in a callback within the DB code, we can't raise */
2028 PyErr_Print ();
2029 res = _default_cmp (leftKey, rightKey);
2030 MYDB_END_BLOCK_THREADS;
2031 }
2032 else {
2033 MYDB_BEGIN_BLOCK_THREADS;
2034
2035 leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size);
2036 rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size);
2037
Gregory P. Smithac741c52005-06-06 17:31:32 +00002038 args = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002039 Py_INCREF (self);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002040 PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */
2041 PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002042
2043 result = PyEval_CallObject (self->btCompareCallback, args);
2044 if (result == 0) {
2045 /* we're in a callback within the DB code, we can't raise */
Gregory P. Smith8966d3d2005-06-16 19:01:42 +00002046 PyErr_Print ();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002047 res = _default_cmp (leftKey, rightKey);
2048 }
2049 else if (PyInt_Check (result)) {
2050 res = PyInt_AsLong (result);
2051 }
2052 else {
2053 PyErr_SetString (PyExc_TypeError,
2054 "DB_bt_compare callback MUST return an int.");
2055 /* we're in a callback within the DB code, we can't raise */
2056 PyErr_Print ();
2057 res = _default_cmp (leftKey, rightKey);
2058 }
2059
2060 Py_DECREF (args);
2061 Py_XDECREF (result);
2062
2063 MYDB_END_BLOCK_THREADS;
2064 }
2065 return res;
2066}
2067
2068static PyObject*
2069DB_set_bt_compare (DBObject* self, PyObject* args)
2070{
2071 int err;
2072 PyObject *comparator;
2073 PyObject *tuple, *emptyStr, *result;
2074
2075 if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator ))
2076 return NULL;
2077
2078 CHECK_DB_NOT_CLOSED (self);
2079
2080 if (! PyCallable_Check (comparator)) {
2081 makeTypeError ("Callable", comparator);
2082 return NULL;
2083 }
2084
2085 /*
2086 * Perform a test call of the comparator function with two empty
2087 * string objects here. verify that it returns an int (0).
2088 * err if not.
2089 */
Gregory P. Smithac741c52005-06-06 17:31:32 +00002090 tuple = PyTuple_New (2);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002091
2092 emptyStr = PyString_FromStringAndSize (NULL, 0);
2093 Py_INCREF(emptyStr);
Gregory P. Smithac741c52005-06-06 17:31:32 +00002094 PyTuple_SET_ITEM (tuple, 0, emptyStr);
2095 PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096 result = PyEval_CallObject (comparator, tuple);
2097 Py_DECREF (tuple);
2098 if (result == 0 || !PyInt_Check(result)) {
2099 PyErr_SetString (PyExc_TypeError,
2100 "callback MUST return an int");
2101 return NULL;
2102 }
2103 else if (PyInt_AsLong(result) != 0) {
2104 PyErr_SetString (PyExc_TypeError,
2105 "callback failed to return 0 on two empty strings");
2106 return NULL;
2107 }
2108
2109 /* We don't accept multiple set_bt_compare operations, in order to
2110 * simplify the code. This would have no real use, as one cannot
2111 * change the function once the db is opened anyway */
2112 if (self->btCompareCallback != NULL) {
2113 PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once");
2114 return NULL;
2115 }
2116
2117 Py_INCREF (comparator);
2118 self->btCompareCallback = comparator;
2119
2120 /* This is to workaround a problem with un-initialized threads (see
2121 comment in DB_associate) */
2122#ifdef WITH_THREAD
2123 PyEval_InitThreads();
2124#endif
2125
2126 err = self->db->set_bt_compare (self->db,
2127 (comparator != NULL ?
2128 _db_compareCallback : NULL));
2129
2130 if (err) {
2131 /* restore the old state in case of error */
2132 Py_DECREF (comparator);
2133 self->btCompareCallback = NULL;
2134 }
2135
2136 RETURN_IF_ERR ();
2137 RETURN_NONE ();
2138}
Neal Norwitz84562352005-10-20 04:30:15 +00002139#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002140
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002141
2142static PyObject*
2143DB_set_cachesize(DBObject* self, PyObject* args)
2144{
2145 int err;
2146 int gbytes = 0, bytes = 0, ncache = 0;
2147
2148 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2149 &gbytes,&bytes,&ncache))
2150 return NULL;
2151 CHECK_DB_NOT_CLOSED(self);
2152
2153 MYDB_BEGIN_ALLOW_THREADS;
2154 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2155 MYDB_END_ALLOW_THREADS;
2156 RETURN_IF_ERR();
2157 RETURN_NONE();
2158}
2159
2160
2161static PyObject*
2162DB_set_flags(DBObject* self, PyObject* args)
2163{
2164 int err, flags;
2165
2166 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2167 return NULL;
2168 CHECK_DB_NOT_CLOSED(self);
2169
2170 MYDB_BEGIN_ALLOW_THREADS;
2171 err = self->db->set_flags(self->db, flags);
2172 MYDB_END_ALLOW_THREADS;
2173 RETURN_IF_ERR();
2174
2175 self->setflags |= flags;
2176 RETURN_NONE();
2177}
2178
2179
2180static PyObject*
2181DB_set_h_ffactor(DBObject* self, PyObject* args)
2182{
2183 int err, ffactor;
2184
2185 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2186 return NULL;
2187 CHECK_DB_NOT_CLOSED(self);
2188
2189 MYDB_BEGIN_ALLOW_THREADS;
2190 err = self->db->set_h_ffactor(self->db, ffactor);
2191 MYDB_END_ALLOW_THREADS;
2192 RETURN_IF_ERR();
2193 RETURN_NONE();
2194}
2195
2196
2197static PyObject*
2198DB_set_h_nelem(DBObject* self, PyObject* args)
2199{
2200 int err, nelem;
2201
2202 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2203 return NULL;
2204 CHECK_DB_NOT_CLOSED(self);
2205
2206 MYDB_BEGIN_ALLOW_THREADS;
2207 err = self->db->set_h_nelem(self->db, nelem);
2208 MYDB_END_ALLOW_THREADS;
2209 RETURN_IF_ERR();
2210 RETURN_NONE();
2211}
2212
2213
2214static PyObject*
2215DB_set_lorder(DBObject* self, PyObject* args)
2216{
2217 int err, lorder;
2218
2219 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2220 return NULL;
2221 CHECK_DB_NOT_CLOSED(self);
2222
2223 MYDB_BEGIN_ALLOW_THREADS;
2224 err = self->db->set_lorder(self->db, lorder);
2225 MYDB_END_ALLOW_THREADS;
2226 RETURN_IF_ERR();
2227 RETURN_NONE();
2228}
2229
2230
2231static PyObject*
2232DB_set_pagesize(DBObject* self, PyObject* args)
2233{
2234 int err, pagesize;
2235
2236 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2237 return NULL;
2238 CHECK_DB_NOT_CLOSED(self);
2239
2240 MYDB_BEGIN_ALLOW_THREADS;
2241 err = self->db->set_pagesize(self->db, pagesize);
2242 MYDB_END_ALLOW_THREADS;
2243 RETURN_IF_ERR();
2244 RETURN_NONE();
2245}
2246
2247
2248static PyObject*
2249DB_set_re_delim(DBObject* self, PyObject* args)
2250{
2251 int err;
2252 char delim;
2253
2254 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2255 PyErr_Clear();
2256 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2257 return NULL;
2258 }
2259
2260 CHECK_DB_NOT_CLOSED(self);
2261
2262 MYDB_BEGIN_ALLOW_THREADS;
2263 err = self->db->set_re_delim(self->db, delim);
2264 MYDB_END_ALLOW_THREADS;
2265 RETURN_IF_ERR();
2266 RETURN_NONE();
2267}
2268
2269static PyObject*
2270DB_set_re_len(DBObject* self, PyObject* args)
2271{
2272 int err, len;
2273
2274 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2275 return NULL;
2276 CHECK_DB_NOT_CLOSED(self);
2277
2278 MYDB_BEGIN_ALLOW_THREADS;
2279 err = self->db->set_re_len(self->db, len);
2280 MYDB_END_ALLOW_THREADS;
2281 RETURN_IF_ERR();
2282 RETURN_NONE();
2283}
2284
2285
2286static PyObject*
2287DB_set_re_pad(DBObject* self, PyObject* args)
2288{
2289 int err;
2290 char pad;
2291
2292 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2293 PyErr_Clear();
2294 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2295 return NULL;
2296 }
2297 CHECK_DB_NOT_CLOSED(self);
2298
2299 MYDB_BEGIN_ALLOW_THREADS;
2300 err = self->db->set_re_pad(self->db, pad);
2301 MYDB_END_ALLOW_THREADS;
2302 RETURN_IF_ERR();
2303 RETURN_NONE();
2304}
2305
2306
2307static PyObject*
2308DB_set_re_source(DBObject* self, PyObject* args)
2309{
2310 int err;
2311 char *re_source;
2312
2313 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2314 return NULL;
2315 CHECK_DB_NOT_CLOSED(self);
2316
2317 MYDB_BEGIN_ALLOW_THREADS;
2318 err = self->db->set_re_source(self->db, re_source);
2319 MYDB_END_ALLOW_THREADS;
2320 RETURN_IF_ERR();
2321 RETURN_NONE();
2322}
2323
2324
2325#if (DBVER >= 32)
2326static PyObject*
2327DB_set_q_extentsize(DBObject* self, PyObject* args)
2328{
2329 int err;
2330 int extentsize;
2331
2332 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2333 return NULL;
2334 CHECK_DB_NOT_CLOSED(self);
2335
2336 MYDB_BEGIN_ALLOW_THREADS;
2337 err = self->db->set_q_extentsize(self->db, extentsize);
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340 RETURN_NONE();
2341}
2342#endif
2343
2344static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002345DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002346{
2347 int err, flags = 0, type;
2348 void* sp;
2349 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002350#if (DBVER >= 43)
2351 PyObject* txnobj = NULL;
2352 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002353 static const char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002354#else
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002355 static const char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002356#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002357
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002358#if (DBVER >= 43)
2359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2360 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002361 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002362 if (!checkTxnObj(txnobj, &txn))
2363 return NULL;
2364#else
2365 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2366 return NULL;
2367#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002368 CHECK_DB_NOT_CLOSED(self);
2369
2370 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002371#if (DBVER >= 43)
2372 err = self->db->stat(self->db, txn, &sp, flags);
2373#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002374 err = self->db->stat(self->db, &sp, flags);
2375#else
2376 err = self->db->stat(self->db, &sp, NULL, flags);
2377#endif
2378 MYDB_END_ALLOW_THREADS;
2379 RETURN_IF_ERR();
2380
2381 self->haveStat = 1;
2382
2383 /* Turn the stat structure into a dictionary */
2384 type = _DB_get_type(self);
2385 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2386 free(sp);
2387 return NULL;
2388 }
2389
2390#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2391#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2392#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2393
2394 switch (type) {
2395 case DB_HASH:
2396 MAKE_HASH_ENTRY(magic);
2397 MAKE_HASH_ENTRY(version);
2398 MAKE_HASH_ENTRY(nkeys);
2399 MAKE_HASH_ENTRY(ndata);
2400 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002401#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002402 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002404 MAKE_HASH_ENTRY(ffactor);
2405 MAKE_HASH_ENTRY(buckets);
2406 MAKE_HASH_ENTRY(free);
2407 MAKE_HASH_ENTRY(bfree);
2408 MAKE_HASH_ENTRY(bigpages);
2409 MAKE_HASH_ENTRY(big_bfree);
2410 MAKE_HASH_ENTRY(overflows);
2411 MAKE_HASH_ENTRY(ovfl_free);
2412 MAKE_HASH_ENTRY(dup);
2413 MAKE_HASH_ENTRY(dup_free);
2414 break;
2415
2416 case DB_BTREE:
2417 case DB_RECNO:
2418 MAKE_BT_ENTRY(magic);
2419 MAKE_BT_ENTRY(version);
2420 MAKE_BT_ENTRY(nkeys);
2421 MAKE_BT_ENTRY(ndata);
2422 MAKE_BT_ENTRY(pagesize);
2423 MAKE_BT_ENTRY(minkey);
2424 MAKE_BT_ENTRY(re_len);
2425 MAKE_BT_ENTRY(re_pad);
2426 MAKE_BT_ENTRY(levels);
2427 MAKE_BT_ENTRY(int_pg);
2428 MAKE_BT_ENTRY(leaf_pg);
2429 MAKE_BT_ENTRY(dup_pg);
2430 MAKE_BT_ENTRY(over_pg);
2431 MAKE_BT_ENTRY(free);
2432 MAKE_BT_ENTRY(int_pgfree);
2433 MAKE_BT_ENTRY(leaf_pgfree);
2434 MAKE_BT_ENTRY(dup_pgfree);
2435 MAKE_BT_ENTRY(over_pgfree);
2436 break;
2437
2438 case DB_QUEUE:
2439 MAKE_QUEUE_ENTRY(magic);
2440 MAKE_QUEUE_ENTRY(version);
2441 MAKE_QUEUE_ENTRY(nkeys);
2442 MAKE_QUEUE_ENTRY(ndata);
2443 MAKE_QUEUE_ENTRY(pagesize);
2444 MAKE_QUEUE_ENTRY(pages);
2445 MAKE_QUEUE_ENTRY(re_len);
2446 MAKE_QUEUE_ENTRY(re_pad);
2447 MAKE_QUEUE_ENTRY(pgfree);
2448#if (DBVER == 31)
2449 MAKE_QUEUE_ENTRY(start);
2450#endif
2451 MAKE_QUEUE_ENTRY(first_recno);
2452 MAKE_QUEUE_ENTRY(cur_recno);
2453 break;
2454
2455 default:
2456 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2457 Py_DECREF(d);
2458 d = NULL;
2459 }
2460
2461#undef MAKE_HASH_ENTRY
2462#undef MAKE_BT_ENTRY
2463#undef MAKE_QUEUE_ENTRY
2464
2465 free(sp);
2466 return d;
2467}
2468
2469static PyObject*
2470DB_sync(DBObject* self, PyObject* args)
2471{
2472 int err;
2473 int flags = 0;
2474
2475 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2476 return NULL;
2477 CHECK_DB_NOT_CLOSED(self);
2478
2479 MYDB_BEGIN_ALLOW_THREADS;
2480 err = self->db->sync(self->db, flags);
2481 MYDB_END_ALLOW_THREADS;
2482 RETURN_IF_ERR();
2483 RETURN_NONE();
2484}
2485
2486
2487#if (DBVER >= 33)
2488static PyObject*
2489DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2490{
2491 int err, flags=0;
2492 u_int32_t count=0;
2493 PyObject* txnobj = NULL;
2494 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002495 static const char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002496
2497 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2498 &txnobj, &flags))
2499 return NULL;
2500 CHECK_DB_NOT_CLOSED(self);
2501 if (!checkTxnObj(txnobj, &txn))
2502 return NULL;
2503
2504 MYDB_BEGIN_ALLOW_THREADS;
2505 err = self->db->truncate(self->db, txn, &count, flags);
2506 MYDB_END_ALLOW_THREADS;
2507 RETURN_IF_ERR();
2508 return PyInt_FromLong(count);
2509}
2510#endif
2511
2512
2513static PyObject*
2514DB_upgrade(DBObject* self, PyObject* args)
2515{
2516 int err, flags=0;
2517 char *filename;
2518
2519 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2520 return NULL;
2521 CHECK_DB_NOT_CLOSED(self);
2522
2523 MYDB_BEGIN_ALLOW_THREADS;
2524 err = self->db->upgrade(self->db, filename, flags);
2525 MYDB_END_ALLOW_THREADS;
2526 RETURN_IF_ERR();
2527 RETURN_NONE();
2528}
2529
2530
2531static PyObject*
2532DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2533{
2534 int err, flags=0;
2535 char* fileName;
2536 char* dbName=NULL;
2537 char* outFileName=NULL;
2538 FILE* outFile=NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002539 static const char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2540 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002541
2542 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2543 &fileName, &dbName, &outFileName, &flags))
2544 return NULL;
2545
2546 CHECK_DB_NOT_CLOSED(self);
2547 if (outFileName)
2548 outFile = fopen(outFileName, "w");
2549
2550 MYDB_BEGIN_ALLOW_THREADS;
2551 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2552 MYDB_END_ALLOW_THREADS;
2553 if (outFileName)
2554 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002555
2556 /* DB.verify acts as a DB handle destructor (like close); this was
2557 * documented in BerkeleyDB 4.2 but had the undocumented effect
2558 * of not being safe in prior versions while still requiring an explicit
2559 * DB.close call afterwards. Lets call close for the user to emulate
2560 * the safe 4.2 behaviour. */
2561#if (DBVER <= 41)
2562 self->db->close(self->db, 0);
2563#endif
2564 self->db = NULL;
2565
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002566 RETURN_IF_ERR();
2567 RETURN_NONE();
2568}
2569
2570
2571static PyObject*
2572DB_set_get_returns_none(DBObject* self, PyObject* args)
2573{
2574 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002575 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002576
2577 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2578 return NULL;
2579 CHECK_DB_NOT_CLOSED(self);
2580
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002581 if (self->moduleFlags.getReturnsNone)
2582 ++oldValue;
2583 if (self->moduleFlags.cursorSetReturnsNone)
2584 ++oldValue;
2585 self->moduleFlags.getReturnsNone = (flags >= 1);
2586 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587 return PyInt_FromLong(oldValue);
2588}
2589
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002590#if (DBVER >= 41)
2591static PyObject*
2592DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2593{
2594 int err;
2595 u_int32_t flags=0;
2596 char *passwd = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002597 static const char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002598
2599 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2600 &passwd, &flags)) {
2601 return NULL;
2602 }
2603
2604 MYDB_BEGIN_ALLOW_THREADS;
2605 err = self->db->set_encrypt(self->db, passwd, flags);
2606 MYDB_END_ALLOW_THREADS;
2607
2608 RETURN_IF_ERR();
2609 RETURN_NONE();
2610}
2611#endif /* DBVER >= 41 */
2612
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002613
2614/*-------------------------------------------------------------- */
2615/* Mapping and Dictionary-like access routines */
2616
2617int DB_length(DBObject* self)
2618{
2619 int err;
2620 long size = 0;
2621 int flags = 0;
2622 void* sp;
2623
2624 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002625 PyErr_SetObject(DBError,
2626 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002627 return -1;
2628 }
2629
2630 if (self->haveStat) { /* Has the stat function been called recently? If
2631 so, we can use the cached value. */
2632 flags = DB_CACHED_COUNTS;
2633 }
2634
2635 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002636#if (DBVER >= 43)
2637 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2638#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002639 err = self->db->stat(self->db, &sp, flags);
2640#else
2641 err = self->db->stat(self->db, &sp, NULL, flags);
2642#endif
2643 MYDB_END_ALLOW_THREADS;
2644
2645 if (err)
2646 return -1;
2647
2648 self->haveStat = 1;
2649
2650 /* All the stat structures have matching fields upto the ndata field,
2651 so we can use any of them for the type cast */
2652 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2653 free(sp);
2654 return size;
2655}
2656
2657
2658PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2659{
2660 int err;
2661 PyObject* retval;
2662 DBT key;
2663 DBT data;
2664
2665 CHECK_DB_NOT_CLOSED(self);
2666 if (!make_key_dbt(self, keyobj, &key, NULL))
2667 return NULL;
2668
2669 CLEAR_DBT(data);
2670 if (CHECK_DBFLAG(self, DB_THREAD)) {
2671 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2672 data.flags = DB_DBT_MALLOC;
2673 }
2674 MYDB_BEGIN_ALLOW_THREADS;
2675 err = self->db->get(self->db, NULL, &key, &data, 0);
2676 MYDB_END_ALLOW_THREADS;
2677 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2678 PyErr_SetObject(PyExc_KeyError, keyobj);
2679 retval = NULL;
2680 }
2681 else if (makeDBError(err)) {
2682 retval = NULL;
2683 }
2684 else {
2685 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2686 FREE_DBT(data);
2687 }
2688
2689 FREE_DBT(key);
2690 return retval;
2691}
2692
2693
2694static int
2695DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2696{
2697 DBT key, data;
2698 int retval;
2699 int flags = 0;
2700
2701 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002702 PyErr_SetObject(DBError,
2703 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704 return -1;
2705 }
2706
2707 if (!make_key_dbt(self, keyobj, &key, NULL))
2708 return -1;
2709
2710 if (dataobj != NULL) {
2711 if (!make_dbt(dataobj, &data))
2712 retval = -1;
2713 else {
2714 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002715 /* dictionaries shouldn't have duplicate keys */
2716 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717 retval = _DB_put(self, NULL, &key, &data, flags);
2718
2719 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002720 /* try deleting any old record that matches and then PUT it
2721 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002722 _DB_delete(self, NULL, &key, 0);
2723 PyErr_Clear();
2724 retval = _DB_put(self, NULL, &key, &data, flags);
2725 }
2726 }
2727 }
2728 else {
2729 /* dataobj == NULL, so delete the key */
2730 retval = _DB_delete(self, NULL, &key, 0);
2731 }
2732 FREE_DBT(key);
2733 return retval;
2734}
2735
2736
2737static PyObject*
2738DB_has_key(DBObject* self, PyObject* args)
2739{
2740 int err;
2741 PyObject* keyobj;
2742 DBT key, data;
2743 PyObject* txnobj = NULL;
2744 DB_TXN *txn = NULL;
2745
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002746 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 return NULL;
2748 CHECK_DB_NOT_CLOSED(self);
2749 if (!make_key_dbt(self, keyobj, &key, NULL))
2750 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002751 if (!checkTxnObj(txnobj, &txn)) {
2752 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002753 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002754 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002755
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002756 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002757 it has a record but can't allocate a buffer for the data. This saves
2758 having to deal with data we won't be using.
2759 */
2760 CLEAR_DBT(data);
2761 data.flags = DB_DBT_USERMEM;
2762
2763 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002764 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002765 MYDB_END_ALLOW_THREADS;
2766 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002767
2768 if (err == DB_BUFFER_SMALL || err == 0) {
2769 return PyInt_FromLong(1);
2770 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2771 return PyInt_FromLong(0);
2772 }
2773
2774 makeDBError(err);
2775 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002776}
2777
2778
2779#define _KEYS_LIST 1
2780#define _VALUES_LIST 2
2781#define _ITEMS_LIST 3
2782
2783static PyObject*
2784_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2785{
2786 int err, dbtype;
2787 DBT key;
2788 DBT data;
2789 DBC *cursor;
2790 PyObject* list;
2791 PyObject* item = NULL;
2792
2793 CHECK_DB_NOT_CLOSED(self);
2794 CLEAR_DBT(key);
2795 CLEAR_DBT(data);
2796
2797 dbtype = _DB_get_type(self);
2798 if (dbtype == -1)
2799 return NULL;
2800
2801 list = PyList_New(0);
2802 if (list == NULL) {
2803 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2804 return NULL;
2805 }
2806
2807 /* get a cursor */
2808 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002809 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002810 MYDB_END_ALLOW_THREADS;
2811 RETURN_IF_ERR();
2812
2813 if (CHECK_DBFLAG(self, DB_THREAD)) {
2814 key.flags = DB_DBT_REALLOC;
2815 data.flags = DB_DBT_REALLOC;
2816 }
2817
2818 while (1) { /* use the cursor to traverse the DB, collecting items */
2819 MYDB_BEGIN_ALLOW_THREADS;
2820 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2821 MYDB_END_ALLOW_THREADS;
2822
2823 if (err) {
2824 /* for any error, break out of the loop */
2825 break;
2826 }
2827
2828 switch (type) {
2829 case _KEYS_LIST:
2830 switch(dbtype) {
2831 case DB_BTREE:
2832 case DB_HASH:
2833 default:
2834 item = PyString_FromStringAndSize((char*)key.data, key.size);
2835 break;
2836 case DB_RECNO:
2837 case DB_QUEUE:
2838 item = PyInt_FromLong(*((db_recno_t*)key.data));
2839 break;
2840 }
2841 break;
2842
2843 case _VALUES_LIST:
2844 item = PyString_FromStringAndSize((char*)data.data, data.size);
2845 break;
2846
2847 case _ITEMS_LIST:
2848 switch(dbtype) {
2849 case DB_BTREE:
2850 case DB_HASH:
2851 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002852 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2853 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 break;
2855 case DB_RECNO:
2856 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002857 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2858 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002859 break;
2860 }
2861 break;
2862 }
2863 if (item == NULL) {
2864 Py_DECREF(list);
2865 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2866 list = NULL;
2867 goto done;
2868 }
2869 PyList_Append(list, item);
2870 Py_DECREF(item);
2871 }
2872
Gregory P. Smithe9477062005-06-04 06:46:59 +00002873 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2874 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875 Py_DECREF(list);
2876 list = NULL;
2877 }
2878
2879 done:
2880 FREE_DBT(key);
2881 FREE_DBT(data);
2882 MYDB_BEGIN_ALLOW_THREADS;
2883 cursor->c_close(cursor);
2884 MYDB_END_ALLOW_THREADS;
2885 return list;
2886}
2887
2888
2889static PyObject*
2890DB_keys(DBObject* self, PyObject* args)
2891{
2892 PyObject* txnobj = NULL;
2893 DB_TXN *txn = NULL;
2894
2895 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2896 return NULL;
2897 if (!checkTxnObj(txnobj, &txn))
2898 return NULL;
2899 return _DB_make_list(self, txn, _KEYS_LIST);
2900}
2901
2902
2903static PyObject*
2904DB_items(DBObject* self, PyObject* args)
2905{
2906 PyObject* txnobj = NULL;
2907 DB_TXN *txn = NULL;
2908
2909 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2910 return NULL;
2911 if (!checkTxnObj(txnobj, &txn))
2912 return NULL;
2913 return _DB_make_list(self, txn, _ITEMS_LIST);
2914}
2915
2916
2917static PyObject*
2918DB_values(DBObject* self, PyObject* args)
2919{
2920 PyObject* txnobj = NULL;
2921 DB_TXN *txn = NULL;
2922
2923 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2924 return NULL;
2925 if (!checkTxnObj(txnobj, &txn))
2926 return NULL;
2927 return _DB_make_list(self, txn, _VALUES_LIST);
2928}
2929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002930/* --------------------------------------------------------------------- */
2931/* DBCursor methods */
2932
2933
2934static PyObject*
2935DBC_close(DBCursorObject* self, PyObject* args)
2936{
2937 int err = 0;
2938
2939 if (!PyArg_ParseTuple(args, ":close"))
2940 return NULL;
2941
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002942 if (self->dbc != NULL) {
2943 MYDB_BEGIN_ALLOW_THREADS;
2944 err = self->dbc->c_close(self->dbc);
2945 self->dbc = NULL;
2946 MYDB_END_ALLOW_THREADS;
2947 }
2948 RETURN_IF_ERR();
2949 RETURN_NONE();
2950}
2951
2952
2953static PyObject*
2954DBC_count(DBCursorObject* self, PyObject* args)
2955{
2956 int err = 0;
2957 db_recno_t count;
2958 int flags = 0;
2959
2960 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2961 return NULL;
2962
2963 CHECK_CURSOR_NOT_CLOSED(self);
2964
2965 MYDB_BEGIN_ALLOW_THREADS;
2966 err = self->dbc->c_count(self->dbc, &count, flags);
2967 MYDB_END_ALLOW_THREADS;
2968 RETURN_IF_ERR();
2969
2970 return PyInt_FromLong(count);
2971}
2972
2973
2974static PyObject*
2975DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2976{
2977 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2978}
2979
2980
2981static PyObject*
2982DBC_delete(DBCursorObject* self, PyObject* args)
2983{
2984 int err, flags=0;
2985
2986 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2987 return NULL;
2988
2989 CHECK_CURSOR_NOT_CLOSED(self);
2990
2991 MYDB_BEGIN_ALLOW_THREADS;
2992 err = self->dbc->c_del(self->dbc, flags);
2993 MYDB_END_ALLOW_THREADS;
2994 RETURN_IF_ERR();
2995
2996 self->mydb->haveStat = 0;
2997 RETURN_NONE();
2998}
2999
3000
3001static PyObject*
3002DBC_dup(DBCursorObject* self, PyObject* args)
3003{
3004 int err, flags =0;
3005 DBC* dbc = NULL;
3006
3007 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3008 return NULL;
3009
3010 CHECK_CURSOR_NOT_CLOSED(self);
3011
3012 MYDB_BEGIN_ALLOW_THREADS;
3013 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3014 MYDB_END_ALLOW_THREADS;
3015 RETURN_IF_ERR();
3016
3017 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3018}
3019
3020static PyObject*
3021DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3022{
3023 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3024}
3025
3026
3027static PyObject*
3028DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3029{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003030 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031 PyObject* keyobj = NULL;
3032 PyObject* dataobj = NULL;
3033 PyObject* retval = NULL;
3034 int dlen = -1;
3035 int doff = -1;
3036 DBT key, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003037 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3038 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003039
3040 CLEAR_DBT(key);
3041 CLEAR_DBT(data);
3042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003043 &flags, &dlen, &doff))
3044 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3047 &kwnames[1],
3048 &keyobj, &flags, &dlen, &doff))
3049 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003051 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3052 kwnames, &keyobj, &dataobj,
3053 &flags, &dlen, &doff))
3054 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003055 return NULL;
3056 }
3057 }
3058 }
3059
3060 CHECK_CURSOR_NOT_CLOSED(self);
3061
3062 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3063 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003064 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3065 (!add_partial_dbt(&data, dlen, doff)) )
3066 {
3067 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003069 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003070
3071 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3072 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003073 if (!(key.flags & DB_DBT_REALLOC)) {
3074 key.flags |= DB_DBT_MALLOC;
3075 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003076 }
3077
3078 MYDB_BEGIN_ALLOW_THREADS;
3079 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3080 MYDB_END_ALLOW_THREADS;
3081
Gregory P. Smithe9477062005-06-04 06:46:59 +00003082 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3083 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003084 Py_INCREF(Py_None);
3085 retval = Py_None;
3086 }
3087 else if (makeDBError(err)) {
3088 retval = NULL;
3089 }
3090 else {
3091 switch (_DB_get_type(self->mydb)) {
3092 case -1:
3093 retval = NULL;
3094 break;
3095 case DB_BTREE:
3096 case DB_HASH:
3097 default:
3098 retval = Py_BuildValue("s#s#", key.data, key.size,
3099 data.data, data.size);
3100 break;
3101 case DB_RECNO:
3102 case DB_QUEUE:
3103 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3104 data.data, data.size);
3105 break;
3106 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003107 FREE_DBT(data);
3108 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003109 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003110 return retval;
3111}
3112
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003113#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003114static PyObject*
3115DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3116{
3117 int err, flags=0;
3118 PyObject* keyobj = NULL;
3119 PyObject* dataobj = NULL;
3120 PyObject* retval = NULL;
3121 int dlen = -1;
3122 int doff = -1;
3123 DBT key, pkey, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003124 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3125 NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003126
3127 CLEAR_DBT(key);
3128 CLEAR_DBT(data);
3129 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3130 &flags, &dlen, &doff))
3131 {
3132 PyErr_Clear();
3133 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3134 &kwnames[1],
3135 &keyobj, &flags, &dlen, &doff))
3136 {
3137 PyErr_Clear();
3138 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3139 kwnames, &keyobj, &dataobj,
3140 &flags, &dlen, &doff))
3141 {
3142 return NULL;
3143 }
3144 }
3145 }
3146
3147 CHECK_CURSOR_NOT_CLOSED(self);
3148
3149 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3150 return NULL;
3151 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3152 (!add_partial_dbt(&data, dlen, doff)) ) {
3153 FREE_DBT(key);
3154 return NULL;
3155 }
3156
3157 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3158 data.flags = DB_DBT_MALLOC;
3159 if (!(key.flags & DB_DBT_REALLOC)) {
3160 key.flags |= DB_DBT_MALLOC;
3161 }
3162 }
3163
3164 CLEAR_DBT(pkey);
3165 pkey.flags = DB_DBT_MALLOC;
3166
3167 MYDB_BEGIN_ALLOW_THREADS;
3168 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3169 MYDB_END_ALLOW_THREADS;
3170
Gregory P. Smithe9477062005-06-04 06:46:59 +00003171 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3172 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003173 Py_INCREF(Py_None);
3174 retval = Py_None;
3175 }
3176 else if (makeDBError(err)) {
3177 retval = NULL;
3178 }
3179 else {
3180 PyObject *pkeyObj;
3181 PyObject *dataObj;
3182 dataObj = PyString_FromStringAndSize(data.data, data.size);
3183
3184 if (self->mydb->primaryDBType == DB_RECNO ||
3185 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003186 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003187 else
3188 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3189
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003190 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003191 {
3192 PyObject *keyObj;
3193 int type = _DB_get_type(self->mydb);
3194 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003195 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003196 else
3197 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003198#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003199 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003200#else
3201 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3202#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003203 FREE_DBT(key);
3204 }
3205 else /* return just the pkey and data */
3206 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003207#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003208 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003209#else
3210 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3211#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003212 }
3213 FREE_DBT(pkey);
3214 FREE_DBT(data);
3215 }
3216 /* the only time REALLOC should be set is if we used an integer
3217 * key that make_key_dbt malloc'd for us. always free these. */
3218 if (key.flags & DB_DBT_REALLOC) {
3219 FREE_DBT(key);
3220 }
3221 return retval;
3222}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003223#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225
3226static PyObject*
3227DBC_get_recno(DBCursorObject* self, PyObject* args)
3228{
3229 int err;
3230 db_recno_t recno;
3231 DBT key;
3232 DBT data;
3233
3234 if (!PyArg_ParseTuple(args, ":get_recno"))
3235 return NULL;
3236
3237 CHECK_CURSOR_NOT_CLOSED(self);
3238
3239 CLEAR_DBT(key);
3240 CLEAR_DBT(data);
3241 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3242 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3243 data.flags = DB_DBT_MALLOC;
3244 key.flags = DB_DBT_MALLOC;
3245 }
3246
3247 MYDB_BEGIN_ALLOW_THREADS;
3248 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3249 MYDB_END_ALLOW_THREADS;
3250 RETURN_IF_ERR();
3251
3252 recno = *((db_recno_t*)data.data);
3253 FREE_DBT(key);
3254 FREE_DBT(data);
3255 return PyInt_FromLong(recno);
3256}
3257
3258
3259static PyObject*
3260DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3261{
3262 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3263}
3264
3265
3266static PyObject*
3267DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3268{
3269 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3270}
3271
3272
3273static PyObject*
3274DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3275{
3276 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3277}
3278
3279
3280static PyObject*
3281DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3282{
3283 int err, flags = 0;
3284 PyObject* keyobj, *dataobj;
3285 DBT key, data;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003286 static const char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3287 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003288 int dlen = -1;
3289 int doff = -1;
3290
3291 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3292 &keyobj, &dataobj, &flags, &dlen, &doff))
3293 return NULL;
3294
3295 CHECK_CURSOR_NOT_CLOSED(self);
3296
3297 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3298 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003299 if (!make_dbt(dataobj, &data) ||
3300 !add_partial_dbt(&data, dlen, doff) )
3301 {
3302 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003304 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305
3306 MYDB_BEGIN_ALLOW_THREADS;
3307 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3308 MYDB_END_ALLOW_THREADS;
3309 FREE_DBT(key);
3310 RETURN_IF_ERR();
3311 self->mydb->haveStat = 0;
3312 RETURN_NONE();
3313}
3314
3315
3316static PyObject*
3317DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3318{
3319 int err, flags = 0;
3320 DBT key, data;
3321 PyObject* retval, *keyobj;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003322 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003323 int dlen = -1;
3324 int doff = -1;
3325
3326 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3327 &keyobj, &flags, &dlen, &doff))
3328 return NULL;
3329
3330 CHECK_CURSOR_NOT_CLOSED(self);
3331
3332 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3333 return NULL;
3334
3335 CLEAR_DBT(data);
3336 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3337 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3338 data.flags = DB_DBT_MALLOC;
3339 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003340 if (!add_partial_dbt(&data, dlen, doff)) {
3341 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003343 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003344
3345 MYDB_BEGIN_ALLOW_THREADS;
3346 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3347 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003348 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3349 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003350 Py_INCREF(Py_None);
3351 retval = Py_None;
3352 }
3353 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354 retval = NULL;
3355 }
3356 else {
3357 switch (_DB_get_type(self->mydb)) {
3358 case -1:
3359 retval = NULL;
3360 break;
3361 case DB_BTREE:
3362 case DB_HASH:
3363 default:
3364 retval = Py_BuildValue("s#s#", key.data, key.size,
3365 data.data, data.size);
3366 break;
3367 case DB_RECNO:
3368 case DB_QUEUE:
3369 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3370 data.data, data.size);
3371 break;
3372 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003374 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003375 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003376 /* the only time REALLOC should be set is if we used an integer
3377 * key that make_key_dbt malloc'd for us. always free these. */
3378 if (key.flags & DB_DBT_REALLOC) {
3379 FREE_DBT(key);
3380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003381
3382 return retval;
3383}
3384
3385
3386static PyObject*
3387DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3388{
3389 int err, flags = 0;
3390 DBT key, data;
3391 PyObject* retval, *keyobj;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003392 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393 int dlen = -1;
3394 int doff = -1;
3395
3396 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3397 &keyobj, &flags, &dlen, &doff))
3398 return NULL;
3399
3400 CHECK_CURSOR_NOT_CLOSED(self);
3401
3402 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3403 return NULL;
3404
3405 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003406 if (!add_partial_dbt(&data, dlen, doff)) {
3407 FREE_DBT(key);
3408 return NULL;
3409 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3411 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003412 data.flags |= DB_DBT_MALLOC;
3413 /* only BTREE databases will return anything in the key */
3414 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3415 key.flags |= DB_DBT_MALLOC;
3416 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 MYDB_BEGIN_ALLOW_THREADS;
3419 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3420 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003421 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3422 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003423 Py_INCREF(Py_None);
3424 retval = Py_None;
3425 }
3426 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427 retval = NULL;
3428 }
3429 else {
3430 switch (_DB_get_type(self->mydb)) {
3431 case -1:
3432 retval = NULL;
3433 break;
3434 case DB_BTREE:
3435 case DB_HASH:
3436 default:
3437 retval = Py_BuildValue("s#s#", key.data, key.size,
3438 data.data, data.size);
3439 break;
3440 case DB_RECNO:
3441 case DB_QUEUE:
3442 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3443 data.data, data.size);
3444 break;
3445 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003446 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447 FREE_DBT(data);
3448 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003450 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003451 if (key.flags & DB_DBT_REALLOC) {
3452 FREE_DBT(key);
3453 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454
3455 return retval;
3456}
3457
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003458static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003459_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3460 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003462 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003464 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465
Gregory P. Smith7441e652003-11-03 21:35:31 +00003466 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3468 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003469 if (!make_dbt(dataobj, &data)) {
3470 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003472 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473
3474 MYDB_BEGIN_ALLOW_THREADS;
3475 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3476 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003477 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003478 Py_INCREF(Py_None);
3479 retval = Py_None;
3480 }
3481 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 retval = NULL;
3483 }
3484 else {
3485 switch (_DB_get_type(self->mydb)) {
3486 case -1:
3487 retval = NULL;
3488 break;
3489 case DB_BTREE:
3490 case DB_HASH:
3491 default:
3492 retval = Py_BuildValue("s#s#", key.data, key.size,
3493 data.data, data.size);
3494 break;
3495 case DB_RECNO:
3496 case DB_QUEUE:
3497 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3498 data.data, data.size);
3499 break;
3500 }
3501 }
3502
3503 FREE_DBT(key);
3504 return retval;
3505}
3506
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003507static PyObject*
3508DBC_get_both(DBCursorObject* self, PyObject* args)
3509{
3510 int flags=0;
3511 PyObject *keyobj, *dataobj;
3512
3513 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3514 return NULL;
3515
Gregory P. Smith7441e652003-11-03 21:35:31 +00003516 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003517 CHECK_CURSOR_NOT_CLOSED(self);
3518
3519 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3520 self->mydb->moduleFlags.getReturnsNone);
3521}
3522
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003523/* Return size of entry */
3524static PyObject*
3525DBC_get_current_size(DBCursorObject* self, PyObject* args)
3526{
3527 int err, flags=DB_CURRENT;
3528 PyObject* retval = NULL;
3529 DBT key, data;
3530
3531 if (!PyArg_ParseTuple(args, ":get_current_size"))
3532 return NULL;
3533 CHECK_CURSOR_NOT_CLOSED(self);
3534 CLEAR_DBT(key);
3535 CLEAR_DBT(data);
3536
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003537 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003538 getting the record size. */
3539 data.flags = DB_DBT_USERMEM;
3540 data.ulen = 0;
3541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3543 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003544 if (err == DB_BUFFER_SMALL || !err) {
3545 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003546 retval = PyInt_FromLong((long)data.size);
3547 err = 0;
3548 }
3549
3550 FREE_DBT(key);
3551 FREE_DBT(data);
3552 RETURN_IF_ERR();
3553 return retval;
3554}
3555
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003556static PyObject*
3557DBC_set_both(DBCursorObject* self, PyObject* args)
3558{
3559 int flags=0;
3560 PyObject *keyobj, *dataobj;
3561
3562 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3563 return NULL;
3564
Gregory P. Smith7441e652003-11-03 21:35:31 +00003565 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003566 CHECK_CURSOR_NOT_CLOSED(self);
3567
3568 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3569 self->mydb->moduleFlags.cursorSetReturnsNone);
3570}
3571
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572
3573static PyObject*
3574DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3575{
3576 int err, irecno, flags=0;
3577 db_recno_t recno;
3578 DBT key, data;
3579 PyObject* retval;
3580 int dlen = -1;
3581 int doff = -1;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003582 static const char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583
3584 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3585 &irecno, &flags, &dlen, &doff))
3586 return NULL;
3587
3588 CHECK_CURSOR_NOT_CLOSED(self);
3589
3590 CLEAR_DBT(key);
3591 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003592 /* use allocated space so DB will be able to realloc room for the real
3593 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 key.data = malloc(sizeof(db_recno_t));
3595 if (key.data == NULL) {
3596 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3597 return NULL;
3598 }
3599 key.size = sizeof(db_recno_t);
3600 key.ulen = key.size;
3601 memcpy(key.data, &recno, sizeof(db_recno_t));
3602 key.flags = DB_DBT_REALLOC;
3603
3604 CLEAR_DBT(data);
3605 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3606 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3607 data.flags = DB_DBT_MALLOC;
3608 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003609 if (!add_partial_dbt(&data, dlen, doff)) {
3610 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003612 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613
3614 MYDB_BEGIN_ALLOW_THREADS;
3615 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3616 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003617 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3618 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003619 Py_INCREF(Py_None);
3620 retval = Py_None;
3621 }
3622 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003623 retval = NULL;
3624 }
3625 else { /* Can only be used for BTrees, so no need to return int key */
3626 retval = Py_BuildValue("s#s#", key.data, key.size,
3627 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003628 FREE_DBT(data);
3629 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003630 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003631
3632 return retval;
3633}
3634
3635
3636static PyObject*
3637DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3638{
3639 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3640}
3641
3642
3643static PyObject*
3644DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3645{
3646 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3647}
3648
3649
3650static PyObject*
3651DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3652{
3653 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3654}
3655
3656
3657static PyObject*
3658DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3659{
3660 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3661}
3662
3663
3664static PyObject*
3665DBC_join_item(DBCursorObject* self, PyObject* args)
3666{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003667 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003668 DBT key, data;
3669 PyObject* retval;
3670
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672 return NULL;
3673
3674 CHECK_CURSOR_NOT_CLOSED(self);
3675
3676 CLEAR_DBT(key);
3677 CLEAR_DBT(data);
3678 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3679 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3680 key.flags = DB_DBT_MALLOC;
3681 }
3682
3683 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003684 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003686 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3687 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 Py_INCREF(Py_None);
3689 retval = Py_None;
3690 }
3691 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 retval = NULL;
3693 }
3694 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003695 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003696 FREE_DBT(key);
3697 }
3698
3699 return retval;
3700}
3701
3702
3703
3704/* --------------------------------------------------------------------- */
3705/* DBEnv methods */
3706
3707
3708static PyObject*
3709DBEnv_close(DBEnvObject* self, PyObject* args)
3710{
3711 int err, flags = 0;
3712
3713 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3714 return NULL;
3715 if (!self->closed) { /* Don't close more than once */
3716 MYDB_BEGIN_ALLOW_THREADS;
3717 err = self->db_env->close(self->db_env, flags);
3718 MYDB_END_ALLOW_THREADS;
3719 /* after calling DBEnv->close, regardless of error, this DBEnv
3720 * may not be accessed again (BerkeleyDB docs). */
3721 self->closed = 1;
3722 self->db_env = NULL;
3723 RETURN_IF_ERR();
3724 }
3725 RETURN_NONE();
3726}
3727
3728
3729static PyObject*
3730DBEnv_open(DBEnvObject* self, PyObject* args)
3731{
3732 int err, flags=0, mode=0660;
3733 char *db_home;
3734
3735 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3736 return NULL;
3737
3738 CHECK_ENV_NOT_CLOSED(self);
3739
3740 MYDB_BEGIN_ALLOW_THREADS;
3741 err = self->db_env->open(self->db_env, db_home, flags, mode);
3742 MYDB_END_ALLOW_THREADS;
3743 RETURN_IF_ERR();
3744 self->closed = 0;
3745 self->flags = flags;
3746 RETURN_NONE();
3747}
3748
3749
3750static PyObject*
3751DBEnv_remove(DBEnvObject* self, PyObject* args)
3752{
3753 int err, flags=0;
3754 char *db_home;
3755
3756 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3757 return NULL;
3758 CHECK_ENV_NOT_CLOSED(self);
3759 MYDB_BEGIN_ALLOW_THREADS;
3760 err = self->db_env->remove(self->db_env, db_home, flags);
3761 MYDB_END_ALLOW_THREADS;
3762 RETURN_IF_ERR();
3763 RETURN_NONE();
3764}
3765
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003766#if (DBVER >= 41)
3767static PyObject*
3768DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3769{
3770 int err;
3771 u_int32_t flags=0;
3772 char *file = NULL;
3773 char *database = NULL;
3774 PyObject *txnobj = NULL;
3775 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003776 static const char* kwnames[] = { "file", "database", "txn", "flags",
3777 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003778
3779 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3780 &file, &database, &txnobj, &flags)) {
3781 return NULL;
3782 }
3783 if (!checkTxnObj(txnobj, &txn)) {
3784 return NULL;
3785 }
3786 CHECK_ENV_NOT_CLOSED(self);
3787 MYDB_BEGIN_ALLOW_THREADS;
3788 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3789 MYDB_END_ALLOW_THREADS;
3790 RETURN_IF_ERR();
3791 RETURN_NONE();
3792}
3793
3794static PyObject*
3795DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3796{
3797 int err;
3798 u_int32_t flags=0;
3799 char *file = NULL;
3800 char *database = NULL;
3801 char *newname = NULL;
3802 PyObject *txnobj = NULL;
3803 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003804 static const char* kwnames[] = { "file", "database", "newname", "txn",
3805 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003806
3807 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3808 &file, &database, &newname, &txnobj, &flags)) {
3809 return NULL;
3810 }
3811 if (!checkTxnObj(txnobj, &txn)) {
3812 return NULL;
3813 }
3814 CHECK_ENV_NOT_CLOSED(self);
3815 MYDB_BEGIN_ALLOW_THREADS;
3816 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3817 flags);
3818 MYDB_END_ALLOW_THREADS;
3819 RETURN_IF_ERR();
3820 RETURN_NONE();
3821}
3822
3823static PyObject*
3824DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3825{
3826 int err;
3827 u_int32_t flags=0;
3828 char *passwd = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003829 static const char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003830
3831 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3832 &passwd, &flags)) {
3833 return NULL;
3834 }
3835
3836 MYDB_BEGIN_ALLOW_THREADS;
3837 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3838 MYDB_END_ALLOW_THREADS;
3839
3840 RETURN_IF_ERR();
3841 RETURN_NONE();
3842}
3843#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003844
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003845#if (DBVER >= 40)
3846static PyObject*
3847DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3848{
3849 int err;
3850 u_int32_t flags=0;
3851 u_int32_t timeout = 0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003852 static const char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003853
3854 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3855 &timeout, &flags)) {
3856 return NULL;
3857 }
3858
3859 MYDB_BEGIN_ALLOW_THREADS;
3860 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3861 MYDB_END_ALLOW_THREADS;
3862
3863 RETURN_IF_ERR();
3864 RETURN_NONE();
3865}
3866#endif /* DBVER >= 40 */
3867
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003868static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003869DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3870{
3871 int err;
3872 long shm_key = 0;
3873
3874 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3875 return NULL;
3876 CHECK_ENV_NOT_CLOSED(self);
3877
3878 err = self->db_env->set_shm_key(self->db_env, shm_key);
3879 RETURN_IF_ERR();
3880 RETURN_NONE();
3881}
3882
3883static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003884DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3885{
3886 int err, gbytes=0, bytes=0, ncache=0;
3887
3888 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3889 &gbytes, &bytes, &ncache))
3890 return NULL;
3891 CHECK_ENV_NOT_CLOSED(self);
3892
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3898}
3899
3900
3901#if (DBVER >= 32)
3902static PyObject*
3903DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3904{
3905 int err, flags=0, onoff=0;
3906
3907 if (!PyArg_ParseTuple(args, "ii:set_flags",
3908 &flags, &onoff))
3909 return NULL;
3910 CHECK_ENV_NOT_CLOSED(self);
3911
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->set_flags(self->db_env, flags, onoff);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3917}
3918#endif
3919
3920
3921static PyObject*
3922DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3923{
3924 int err;
3925 char *dir;
3926
3927 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3928 return NULL;
3929 CHECK_ENV_NOT_CLOSED(self);
3930
3931 MYDB_BEGIN_ALLOW_THREADS;
3932 err = self->db_env->set_data_dir(self->db_env, dir);
3933 MYDB_END_ALLOW_THREADS;
3934 RETURN_IF_ERR();
3935 RETURN_NONE();
3936}
3937
3938
3939static PyObject*
3940DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3941{
3942 int err, lg_bsize;
3943
3944 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3945 return NULL;
3946 CHECK_ENV_NOT_CLOSED(self);
3947
3948 MYDB_BEGIN_ALLOW_THREADS;
3949 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3950 MYDB_END_ALLOW_THREADS;
3951 RETURN_IF_ERR();
3952 RETURN_NONE();
3953}
3954
3955
3956static PyObject*
3957DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3958{
3959 int err;
3960 char *dir;
3961
3962 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3963 return NULL;
3964 CHECK_ENV_NOT_CLOSED(self);
3965
3966 MYDB_BEGIN_ALLOW_THREADS;
3967 err = self->db_env->set_lg_dir(self->db_env, dir);
3968 MYDB_END_ALLOW_THREADS;
3969 RETURN_IF_ERR();
3970 RETURN_NONE();
3971}
3972
3973static PyObject*
3974DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3975{
3976 int err, lg_max;
3977
3978 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3981
3982 MYDB_BEGIN_ALLOW_THREADS;
3983 err = self->db_env->set_lg_max(self->db_env, lg_max);
3984 MYDB_END_ALLOW_THREADS;
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988
3989
Neal Norwitz84562352005-10-20 04:30:15 +00003990#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003992DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3993{
3994 int err, lg_max;
3995
3996 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
3999
4000 MYDB_BEGIN_ALLOW_THREADS;
4001 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4002 MYDB_END_ALLOW_THREADS;
4003 RETURN_IF_ERR();
4004 RETURN_NONE();
4005}
Neal Norwitz84562352005-10-20 04:30:15 +00004006#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004007
4008
4009static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004010DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4011{
4012 int err, lk_detect;
4013
4014 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4015 return NULL;
4016 CHECK_ENV_NOT_CLOSED(self);
4017
4018 MYDB_BEGIN_ALLOW_THREADS;
4019 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4020 MYDB_END_ALLOW_THREADS;
4021 RETURN_IF_ERR();
4022 RETURN_NONE();
4023}
4024
4025
4026static PyObject*
4027DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4028{
4029 int err, max;
4030
4031 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4034
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_lk_max(self->db_env, max);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4040}
4041
4042
4043#if (DBVER >= 32)
4044
4045static PyObject*
4046DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4047{
4048 int err, max;
4049
4050 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_lk_max_locks(self->db_env, max);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4064{
4065 int err, max;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
4079static PyObject*
4080DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4081{
4082 int err, max;
4083
4084 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lk_max_objects(self->db_env, max);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095#endif
4096
4097
4098static PyObject*
4099DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4100{
4101 int err, mp_mmapsize;
4102
4103 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4104 return NULL;
4105 CHECK_ENV_NOT_CLOSED(self);
4106
4107 MYDB_BEGIN_ALLOW_THREADS;
4108 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4109 MYDB_END_ALLOW_THREADS;
4110 RETURN_IF_ERR();
4111 RETURN_NONE();
4112}
4113
4114
4115static PyObject*
4116DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4117{
4118 int err;
4119 char *dir;
4120
4121 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4122 return NULL;
4123 CHECK_ENV_NOT_CLOSED(self);
4124
4125 MYDB_BEGIN_ALLOW_THREADS;
4126 err = self->db_env->set_tmp_dir(self->db_env, dir);
4127 MYDB_END_ALLOW_THREADS;
4128 RETURN_IF_ERR();
4129 RETURN_NONE();
4130}
4131
4132
4133static PyObject*
4134DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4135{
4136 int flags = 0;
4137 PyObject* txnobj = NULL;
4138 DB_TXN *txn = NULL;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004139 static const char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004140
4141 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4142 &txnobj, &flags))
4143 return NULL;
4144
4145 if (!checkTxnObj(txnobj, &txn))
4146 return NULL;
4147 CHECK_ENV_NOT_CLOSED(self);
4148
4149 return (PyObject*)newDBTxnObject(self, txn, flags);
4150}
4151
4152
4153static PyObject*
4154DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4155{
4156 int err, kbyte=0, min=0, flags=0;
4157
4158 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4159 return NULL;
4160 CHECK_ENV_NOT_CLOSED(self);
4161
4162 MYDB_BEGIN_ALLOW_THREADS;
4163#if (DBVER >= 40)
4164 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4165#else
4166 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4167#endif
4168 MYDB_END_ALLOW_THREADS;
4169 RETURN_IF_ERR();
4170 RETURN_NONE();
4171}
4172
4173
4174static PyObject*
4175DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4176{
4177 int err, max;
4178
4179 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4180 return NULL;
4181 CHECK_ENV_NOT_CLOSED(self);
4182
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004183 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004184 RETURN_IF_ERR();
4185 RETURN_NONE();
4186}
4187
4188
4189static PyObject*
4190DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4191{
4192 int err;
4193 time_t stamp;
4194
4195 if (!PyArg_ParseTuple(args, "i:set_tx_timestamp", &stamp))
4196 return NULL;
4197 CHECK_ENV_NOT_CLOSED(self);
4198
4199 err = self->db_env->set_tx_timestamp(self->db_env, &stamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004200 RETURN_IF_ERR();
4201 RETURN_NONE();
4202}
4203
4204
4205static PyObject*
4206DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4207{
4208 int err, atype, flags=0;
4209 int aborted = 0;
4210
4211 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4212 return NULL;
4213 CHECK_ENV_NOT_CLOSED(self);
4214
4215 MYDB_BEGIN_ALLOW_THREADS;
4216#if (DBVER >= 40)
4217 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4218#else
4219 err = lock_detect(self->db_env, flags, atype, &aborted);
4220#endif
4221 MYDB_END_ALLOW_THREADS;
4222 RETURN_IF_ERR();
4223 return PyInt_FromLong(aborted);
4224}
4225
4226
4227static PyObject*
4228DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4229{
4230 int flags=0;
4231 int locker, lock_mode;
4232 DBT obj;
4233 PyObject* objobj;
4234
4235 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4236 return NULL;
4237
4238
4239 if (!make_dbt(objobj, &obj))
4240 return NULL;
4241
4242 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4243}
4244
4245
4246static PyObject*
4247DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4248{
4249 int err;
4250 u_int32_t theID;
4251
4252 if (!PyArg_ParseTuple(args, ":lock_id"))
4253 return NULL;
4254
4255 CHECK_ENV_NOT_CLOSED(self);
4256 MYDB_BEGIN_ALLOW_THREADS;
4257#if (DBVER >= 40)
4258 err = self->db_env->lock_id(self->db_env, &theID);
4259#else
4260 err = lock_id(self->db_env, &theID);
4261#endif
4262 MYDB_END_ALLOW_THREADS;
4263 RETURN_IF_ERR();
4264
4265 return PyInt_FromLong((long)theID);
4266}
4267
4268
4269static PyObject*
4270DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4271{
4272 int err;
4273 DBLockObject* dblockobj;
4274
4275 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4276 return NULL;
4277
4278 CHECK_ENV_NOT_CLOSED(self);
4279 MYDB_BEGIN_ALLOW_THREADS;
4280#if (DBVER >= 40)
4281 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4282#else
4283 err = lock_put(self->db_env, &dblockobj->lock);
4284#endif
4285 MYDB_END_ALLOW_THREADS;
4286 RETURN_IF_ERR();
4287 RETURN_NONE();
4288}
4289
4290
4291static PyObject*
4292DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4293{
4294 int err;
4295 DB_LOCK_STAT* sp;
4296 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004297 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004298
4299 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4300 return NULL;
4301 CHECK_ENV_NOT_CLOSED(self);
4302
4303 MYDB_BEGIN_ALLOW_THREADS;
4304#if (DBVER >= 40)
4305 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4306#else
4307#if (DBVER >= 33)
4308 err = lock_stat(self->db_env, &sp);
4309#else
4310 err = lock_stat(self->db_env, &sp, NULL);
4311#endif
4312#endif
4313 MYDB_END_ALLOW_THREADS;
4314 RETURN_IF_ERR();
4315
4316 /* Turn the stat structure into a dictionary */
4317 d = PyDict_New();
4318 if (d == NULL) {
4319 free(sp);
4320 return NULL;
4321 }
4322
4323#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4324
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004325#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004326 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004327#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004328 MAKE_ENTRY(nmodes);
4329#if (DBVER >= 32)
4330 MAKE_ENTRY(maxlocks);
4331 MAKE_ENTRY(maxlockers);
4332 MAKE_ENTRY(maxobjects);
4333 MAKE_ENTRY(nlocks);
4334 MAKE_ENTRY(maxnlocks);
4335#endif
4336 MAKE_ENTRY(nlockers);
4337 MAKE_ENTRY(maxnlockers);
4338#if (DBVER >= 32)
4339 MAKE_ENTRY(nobjects);
4340 MAKE_ENTRY(maxnobjects);
4341#endif
4342 MAKE_ENTRY(nrequests);
4343 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004344#if (DBVER < 44)
4345 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004346 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004347#else
4348 MAKE_ENTRY(lock_nowait);
4349 MAKE_ENTRY(lock_wait);
4350#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004351 MAKE_ENTRY(ndeadlocks);
4352 MAKE_ENTRY(regsize);
4353 MAKE_ENTRY(region_wait);
4354 MAKE_ENTRY(region_nowait);
4355
4356#undef MAKE_ENTRY
4357 free(sp);
4358 return d;
4359}
4360
4361
4362static PyObject*
4363DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4364{
4365 int flags=0;
4366 int err;
4367 char **log_list_start, **log_list;
4368 PyObject* list;
4369 PyObject* item = NULL;
4370
4371 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4372 return NULL;
4373
4374 CHECK_ENV_NOT_CLOSED(self);
4375 MYDB_BEGIN_ALLOW_THREADS;
4376#if (DBVER >= 40)
4377 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4378#elif (DBVER == 33)
4379 err = log_archive(self->db_env, &log_list, flags);
4380#else
4381 err = log_archive(self->db_env, &log_list, flags, NULL);
4382#endif
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385
4386 list = PyList_New(0);
4387 if (list == NULL) {
4388 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4389 return NULL;
4390 }
4391
4392 if (log_list) {
4393 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4394 item = PyString_FromString (*log_list);
4395 if (item == NULL) {
4396 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004397 PyErr_SetString(PyExc_MemoryError,
4398 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004399 list = NULL;
4400 break;
4401 }
4402 PyList_Append(list, item);
4403 Py_DECREF(item);
4404 }
4405 free(log_list_start);
4406 }
4407 return list;
4408}
4409
4410
4411static PyObject*
4412DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4413{
4414 int err;
4415 DB_TXN_STAT* sp;
4416 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004417 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004418
4419 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4420 return NULL;
4421 CHECK_ENV_NOT_CLOSED(self);
4422
4423 MYDB_BEGIN_ALLOW_THREADS;
4424#if (DBVER >= 40)
4425 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4426#elif (DBVER == 33)
4427 err = txn_stat(self->db_env, &sp);
4428#else
4429 err = txn_stat(self->db_env, &sp, NULL);
4430#endif
4431 MYDB_END_ALLOW_THREADS;
4432 RETURN_IF_ERR();
4433
4434 /* Turn the stat structure into a dictionary */
4435 d = PyDict_New();
4436 if (d == NULL) {
4437 free(sp);
4438 return NULL;
4439 }
4440
4441#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4442
4443 MAKE_ENTRY(time_ckp);
4444 MAKE_ENTRY(last_txnid);
4445 MAKE_ENTRY(maxtxns);
4446 MAKE_ENTRY(nactive);
4447 MAKE_ENTRY(maxnactive);
4448 MAKE_ENTRY(nbegins);
4449 MAKE_ENTRY(naborts);
4450 MAKE_ENTRY(ncommits);
4451 MAKE_ENTRY(regsize);
4452 MAKE_ENTRY(region_wait);
4453 MAKE_ENTRY(region_nowait);
4454
4455#undef MAKE_ENTRY
4456 free(sp);
4457 return d;
4458}
4459
4460
4461static PyObject*
4462DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4463{
4464 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004465 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004466
4467 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4468 return NULL;
4469 CHECK_ENV_NOT_CLOSED(self);
4470
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004471 if (self->moduleFlags.getReturnsNone)
4472 ++oldValue;
4473 if (self->moduleFlags.cursorSetReturnsNone)
4474 ++oldValue;
4475 self->moduleFlags.getReturnsNone = (flags >= 1);
4476 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004477 return PyInt_FromLong(oldValue);
4478}
4479
4480
4481/* --------------------------------------------------------------------- */
4482/* DBTxn methods */
4483
4484
4485static PyObject*
4486DBTxn_commit(DBTxnObject* self, PyObject* args)
4487{
4488 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004489 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490
4491 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4492 return NULL;
4493
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004494 if (!self->txn) {
4495 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4496 "DBTxn must not be used after txn_commit or txn_abort"));
4497 return NULL;
4498 }
4499 txn = self->txn;
4500 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004501 MYDB_BEGIN_ALLOW_THREADS;
4502#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004503 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004504#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004505 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004506#endif
4507 MYDB_END_ALLOW_THREADS;
4508 RETURN_IF_ERR();
4509 RETURN_NONE();
4510}
4511
4512static PyObject*
4513DBTxn_prepare(DBTxnObject* self, PyObject* args)
4514{
4515#if (DBVER >= 33)
4516 int err;
4517 char* gid=NULL;
4518 int gid_size=0;
4519
4520 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4521 return NULL;
4522
4523 if (gid_size != DB_XIDDATASIZE) {
4524 PyErr_SetString(PyExc_TypeError,
4525 "gid must be DB_XIDDATASIZE bytes long");
4526 return NULL;
4527 }
4528
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004529 if (!self->txn) {
4530 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4531 "DBTxn must not be used after txn_commit or txn_abort"));
4532 return NULL;
4533 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004534 MYDB_BEGIN_ALLOW_THREADS;
4535#if (DBVER >= 40)
4536 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4537#else
4538 err = txn_prepare(self->txn, (u_int8_t*)gid);
4539#endif
4540 MYDB_END_ALLOW_THREADS;
4541 RETURN_IF_ERR();
4542 RETURN_NONE();
4543#else
4544 int err;
4545
4546 if (!PyArg_ParseTuple(args, ":prepare"))
4547 return NULL;
4548
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004549 if (!self->txn) {
4550 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4551 "DBTxn must not be used after txn_commit or txn_abort"));
4552 return NULL;
4553 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004554 MYDB_BEGIN_ALLOW_THREADS;
4555 err = txn_prepare(self->txn);
4556 MYDB_END_ALLOW_THREADS;
4557 RETURN_IF_ERR();
4558 RETURN_NONE();
4559#endif
4560}
4561
4562
4563static PyObject*
4564DBTxn_abort(DBTxnObject* self, PyObject* args)
4565{
4566 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004567 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004568
4569 if (!PyArg_ParseTuple(args, ":abort"))
4570 return NULL;
4571
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004572 if (!self->txn) {
4573 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4574 "DBTxn must not be used after txn_commit or txn_abort"));
4575 return NULL;
4576 }
4577 txn = self->txn;
4578 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004579 MYDB_BEGIN_ALLOW_THREADS;
4580#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004581 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004582#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004583 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584#endif
4585 MYDB_END_ALLOW_THREADS;
4586 RETURN_IF_ERR();
4587 RETURN_NONE();
4588}
4589
4590
4591static PyObject*
4592DBTxn_id(DBTxnObject* self, PyObject* args)
4593{
4594 int id;
4595
4596 if (!PyArg_ParseTuple(args, ":id"))
4597 return NULL;
4598
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004599 if (!self->txn) {
4600 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4601 "DBTxn must not be used after txn_commit or txn_abort"));
4602 return NULL;
4603 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004604 MYDB_BEGIN_ALLOW_THREADS;
4605#if (DBVER >= 40)
4606 id = self->txn->id(self->txn);
4607#else
4608 id = txn_id(self->txn);
4609#endif
4610 MYDB_END_ALLOW_THREADS;
4611 return PyInt_FromLong(id);
4612}
4613
4614/* --------------------------------------------------------------------- */
4615/* Method definition tables and type objects */
4616
4617static PyMethodDef DB_methods[] = {
4618 {"append", (PyCFunction)DB_append, METH_VARARGS},
4619#if (DBVER >= 33)
4620 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4621#endif
4622 {"close", (PyCFunction)DB_close, METH_VARARGS},
4623#if (DBVER >= 32)
4624 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4625 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4626#endif
4627 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4628 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4629 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4630 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004631#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004632 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004633#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004634 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4635 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4636 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4637 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4638 {"join", (PyCFunction)DB_join, METH_VARARGS},
4639 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4640 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4641 {"items", (PyCFunction)DB_items, METH_VARARGS},
4642 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4643 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4644 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4645 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4646 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4647 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004648#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004649 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004651 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004652#if (DBVER >= 41)
4653 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4654#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004655 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4656 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4657 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4658 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4659 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4660 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4661 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4662 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4663 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4664#if (DBVER >= 32)
4665 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4666#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004667 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004668 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4669#if (DBVER >= 33)
4670 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4671#endif
4672 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4673 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4674 {"values", (PyCFunction)DB_values, METH_VARARGS},
4675 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4676 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4677 {NULL, NULL} /* sentinel */
4678};
4679
4680
4681static PyMappingMethods DB_mapping = {
4682 (inquiry)DB_length, /*mp_length*/
4683 (binaryfunc)DB_subscript, /*mp_subscript*/
4684 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4685};
4686
4687
4688static PyMethodDef DBCursor_methods[] = {
4689 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4690 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4691 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4692 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4693 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4694 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4695 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004696#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004697 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004698#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004699 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4700 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4701 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4702 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4703 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4704 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4705 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4706 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004707 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004708 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004709 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4710 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4711 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4712 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4713 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4714 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4715 {NULL, NULL} /* sentinel */
4716};
4717
4718
4719static PyMethodDef DBEnv_methods[] = {
4720 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4721 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4722 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004723#if (DBVER >= 41)
4724 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4725 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4726 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4727#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004728#if (DBVER >= 40)
4729 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4730#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004731 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004732 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4733 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4734#if (DBVER >= 32)
4735 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4736#endif
4737 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4738 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4739 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004740#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00004741 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004742#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004743 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4744 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4745#if (DBVER >= 32)
4746 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4747 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4748 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4749#endif
4750 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4751 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4752 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4753 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4754 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4755 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00004756 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004757 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4758 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4759 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4760 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4761 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4762 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4763 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4764 {NULL, NULL} /* sentinel */
4765};
4766
4767
4768static PyMethodDef DBTxn_methods[] = {
4769 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4770 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4771 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4772 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4773 {NULL, NULL} /* sentinel */
4774};
4775
4776
4777static PyObject*
4778DB_getattr(DBObject* self, char *name)
4779{
4780 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4781}
4782
4783
4784static PyObject*
4785DBEnv_getattr(DBEnvObject* self, char *name)
4786{
4787 if (!strcmp(name, "db_home")) {
4788 CHECK_ENV_NOT_CLOSED(self);
4789 if (self->db_env->db_home == NULL) {
4790 RETURN_NONE();
4791 }
4792 return PyString_FromString(self->db_env->db_home);
4793 }
4794
4795 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4796}
4797
4798
4799static PyObject*
4800DBCursor_getattr(DBCursorObject* self, char *name)
4801{
4802 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4803}
4804
4805static PyObject*
4806DBTxn_getattr(DBTxnObject* self, char *name)
4807{
4808 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4809}
4810
4811static PyObject*
4812DBLock_getattr(DBLockObject* self, char *name)
4813{
4814 return NULL;
4815}
4816
4817statichere PyTypeObject DB_Type = {
4818 PyObject_HEAD_INIT(NULL)
4819 0, /*ob_size*/
4820 "DB", /*tp_name*/
4821 sizeof(DBObject), /*tp_basicsize*/
4822 0, /*tp_itemsize*/
4823 /* methods */
4824 (destructor)DB_dealloc, /*tp_dealloc*/
4825 0, /*tp_print*/
4826 (getattrfunc)DB_getattr, /*tp_getattr*/
4827 0, /*tp_setattr*/
4828 0, /*tp_compare*/
4829 0, /*tp_repr*/
4830 0, /*tp_as_number*/
4831 0, /*tp_as_sequence*/
4832 &DB_mapping,/*tp_as_mapping*/
4833 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004834#ifdef HAVE_WEAKREF
4835 0, /* tp_call */
4836 0, /* tp_str */
4837 0, /* tp_getattro */
4838 0, /* tp_setattro */
4839 0, /* tp_as_buffer */
4840 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4841 0, /* tp_doc */
4842 0, /* tp_traverse */
4843 0, /* tp_clear */
4844 0, /* tp_richcompare */
4845 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4846#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004847};
4848
4849
4850statichere PyTypeObject DBCursor_Type = {
4851 PyObject_HEAD_INIT(NULL)
4852 0, /*ob_size*/
4853 "DBCursor", /*tp_name*/
4854 sizeof(DBCursorObject), /*tp_basicsize*/
4855 0, /*tp_itemsize*/
4856 /* methods */
4857 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4858 0, /*tp_print*/
4859 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4860 0, /*tp_setattr*/
4861 0, /*tp_compare*/
4862 0, /*tp_repr*/
4863 0, /*tp_as_number*/
4864 0, /*tp_as_sequence*/
4865 0, /*tp_as_mapping*/
4866 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004867#ifdef HAVE_WEAKREF
4868 0, /* tp_call */
4869 0, /* tp_str */
4870 0, /* tp_getattro */
4871 0, /* tp_setattro */
4872 0, /* tp_as_buffer */
4873 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4874 0, /* tp_doc */
4875 0, /* tp_traverse */
4876 0, /* tp_clear */
4877 0, /* tp_richcompare */
4878 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4879#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004880};
4881
4882
4883statichere PyTypeObject DBEnv_Type = {
4884 PyObject_HEAD_INIT(NULL)
4885 0, /*ob_size*/
4886 "DBEnv", /*tp_name*/
4887 sizeof(DBEnvObject), /*tp_basicsize*/
4888 0, /*tp_itemsize*/
4889 /* methods */
4890 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4891 0, /*tp_print*/
4892 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4893 0, /*tp_setattr*/
4894 0, /*tp_compare*/
4895 0, /*tp_repr*/
4896 0, /*tp_as_number*/
4897 0, /*tp_as_sequence*/
4898 0, /*tp_as_mapping*/
4899 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004900#ifdef HAVE_WEAKREF
4901 0, /* tp_call */
4902 0, /* tp_str */
4903 0, /* tp_getattro */
4904 0, /* tp_setattro */
4905 0, /* tp_as_buffer */
4906 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4907 0, /* tp_doc */
4908 0, /* tp_traverse */
4909 0, /* tp_clear */
4910 0, /* tp_richcompare */
4911 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4912#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004913};
4914
4915statichere PyTypeObject DBTxn_Type = {
4916 PyObject_HEAD_INIT(NULL)
4917 0, /*ob_size*/
4918 "DBTxn", /*tp_name*/
4919 sizeof(DBTxnObject), /*tp_basicsize*/
4920 0, /*tp_itemsize*/
4921 /* methods */
4922 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4923 0, /*tp_print*/
4924 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4925 0, /*tp_setattr*/
4926 0, /*tp_compare*/
4927 0, /*tp_repr*/
4928 0, /*tp_as_number*/
4929 0, /*tp_as_sequence*/
4930 0, /*tp_as_mapping*/
4931 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004932#ifdef HAVE_WEAKREF
4933 0, /* tp_call */
4934 0, /* tp_str */
4935 0, /* tp_getattro */
4936 0, /* tp_setattro */
4937 0, /* tp_as_buffer */
4938 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4939 0, /* tp_doc */
4940 0, /* tp_traverse */
4941 0, /* tp_clear */
4942 0, /* tp_richcompare */
4943 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4944#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004945};
4946
4947
4948statichere PyTypeObject DBLock_Type = {
4949 PyObject_HEAD_INIT(NULL)
4950 0, /*ob_size*/
4951 "DBLock", /*tp_name*/
4952 sizeof(DBLockObject), /*tp_basicsize*/
4953 0, /*tp_itemsize*/
4954 /* methods */
4955 (destructor)DBLock_dealloc, /*tp_dealloc*/
4956 0, /*tp_print*/
4957 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4958 0, /*tp_setattr*/
4959 0, /*tp_compare*/
4960 0, /*tp_repr*/
4961 0, /*tp_as_number*/
4962 0, /*tp_as_sequence*/
4963 0, /*tp_as_mapping*/
4964 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004965#ifdef HAVE_WEAKREF
4966 0, /* tp_call */
4967 0, /* tp_str */
4968 0, /* tp_getattro */
4969 0, /* tp_setattro */
4970 0, /* tp_as_buffer */
4971 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4972 0, /* tp_doc */
4973 0, /* tp_traverse */
4974 0, /* tp_clear */
4975 0, /* tp_richcompare */
4976 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4977#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004978};
4979
4980
4981/* --------------------------------------------------------------------- */
4982/* Module-level functions */
4983
4984static PyObject*
4985DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4986{
4987 PyObject* dbenvobj = NULL;
4988 int flags = 0;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004989 static const char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004990
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004991 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4992 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004993 return NULL;
4994 if (dbenvobj == Py_None)
4995 dbenvobj = NULL;
4996 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4997 makeTypeError("DBEnv", dbenvobj);
4998 return NULL;
4999 }
5000
5001 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5002}
5003
5004
5005static PyObject*
5006DBEnv_construct(PyObject* self, PyObject* args)
5007{
5008 int flags = 0;
5009 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5010 return (PyObject* )newDBEnvObject(flags);
5011}
5012
5013
5014static char bsddb_version_doc[] =
5015"Returns a tuple of major, minor, and patch release numbers of the\n\
5016underlying DB library.";
5017
5018static PyObject*
5019bsddb_version(PyObject* self, PyObject* args)
5020{
5021 int major, minor, patch;
5022
5023 if (!PyArg_ParseTuple(args, ":version"))
5024 return NULL;
5025 db_version(&major, &minor, &patch);
5026 return Py_BuildValue("(iii)", major, minor, patch);
5027}
5028
5029
5030/* List of functions defined in the module */
5031
5032static PyMethodDef bsddb_methods[] = {
5033 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5034 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5035 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5036 {NULL, NULL} /* sentinel */
5037};
5038
5039
5040/* --------------------------------------------------------------------- */
5041/* Module initialization */
5042
5043
5044/* Convenience routine to export an integer value.
5045 * Errors are silently ignored, for better or for worse...
5046 */
5047#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5048
Gregory P. Smith41631e82003-09-21 00:08:14 +00005049#define MODULE_NAME_MAX_LEN 11
5050static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005051
5052DL_EXPORT(void) init_bsddb(void)
5053{
5054 PyObject* m;
5055 PyObject* d;
5056 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5057 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5058 PyObject* cvsid_s = PyString_FromString( rcs_id );
5059
5060 /* Initialize the type of the new type objects here; doing it here
5061 is required for portability to Windows without requiring C++. */
5062 DB_Type.ob_type = &PyType_Type;
5063 DBCursor_Type.ob_type = &PyType_Type;
5064 DBEnv_Type.ob_type = &PyType_Type;
5065 DBTxn_Type.ob_type = &PyType_Type;
5066 DBLock_Type.ob_type = &PyType_Type;
5067
5068
Mark Hammonda69d4092003-04-22 23:13:27 +00005069#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005070 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005071 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005072#endif
5073
5074 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005075 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005076 if (m == NULL)
5077 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005078
5079 /* Add some symbolic constants to the module */
5080 d = PyModule_GetDict(m);
5081 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5082 PyDict_SetItemString(d, "cvsid", cvsid_s);
5083 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5084 Py_DECREF(pybsddb_version_s);
5085 pybsddb_version_s = NULL;
5086 Py_DECREF(cvsid_s);
5087 cvsid_s = NULL;
5088 Py_DECREF(db_version_s);
5089 db_version_s = NULL;
5090
5091 ADD_INT(d, DB_VERSION_MAJOR);
5092 ADD_INT(d, DB_VERSION_MINOR);
5093 ADD_INT(d, DB_VERSION_PATCH);
5094
5095 ADD_INT(d, DB_MAX_PAGES);
5096 ADD_INT(d, DB_MAX_RECORDS);
5097
Gregory P. Smith41631e82003-09-21 00:08:14 +00005098#if (DBVER >= 42)
5099 ADD_INT(d, DB_RPCCLIENT);
5100#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005101 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005102 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5103 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5104#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005105 ADD_INT(d, DB_XA_CREATE);
5106
5107 ADD_INT(d, DB_CREATE);
5108 ADD_INT(d, DB_NOMMAP);
5109 ADD_INT(d, DB_THREAD);
5110
5111 ADD_INT(d, DB_FORCE);
5112 ADD_INT(d, DB_INIT_CDB);
5113 ADD_INT(d, DB_INIT_LOCK);
5114 ADD_INT(d, DB_INIT_LOG);
5115 ADD_INT(d, DB_INIT_MPOOL);
5116 ADD_INT(d, DB_INIT_TXN);
5117#if (DBVER >= 32)
5118 ADD_INT(d, DB_JOINENV);
5119#endif
5120
5121 ADD_INT(d, DB_RECOVER);
5122 ADD_INT(d, DB_RECOVER_FATAL);
5123 ADD_INT(d, DB_TXN_NOSYNC);
5124 ADD_INT(d, DB_USE_ENVIRON);
5125 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5126
5127 ADD_INT(d, DB_LOCKDOWN);
5128 ADD_INT(d, DB_PRIVATE);
5129 ADD_INT(d, DB_SYSTEM_MEM);
5130
5131 ADD_INT(d, DB_TXN_SYNC);
5132 ADD_INT(d, DB_TXN_NOWAIT);
5133
5134 ADD_INT(d, DB_EXCL);
5135 ADD_INT(d, DB_FCNTL_LOCKING);
5136 ADD_INT(d, DB_ODDFILESIZE);
5137 ADD_INT(d, DB_RDWRMASTER);
5138 ADD_INT(d, DB_RDONLY);
5139 ADD_INT(d, DB_TRUNCATE);
5140#if (DBVER >= 32)
5141 ADD_INT(d, DB_EXTENT);
5142 ADD_INT(d, DB_CDB_ALLDB);
5143 ADD_INT(d, DB_VERIFY);
5144#endif
5145 ADD_INT(d, DB_UPGRADE);
5146
5147 ADD_INT(d, DB_AGGRESSIVE);
5148 ADD_INT(d, DB_NOORDERCHK);
5149 ADD_INT(d, DB_ORDERCHKONLY);
5150 ADD_INT(d, DB_PR_PAGE);
5151#if ! (DBVER >= 33)
5152 ADD_INT(d, DB_VRFY_FLAGMASK);
5153 ADD_INT(d, DB_PR_HEADERS);
5154#endif
5155 ADD_INT(d, DB_PR_RECOVERYTEST);
5156 ADD_INT(d, DB_SALVAGE);
5157
5158 ADD_INT(d, DB_LOCK_NORUN);
5159 ADD_INT(d, DB_LOCK_DEFAULT);
5160 ADD_INT(d, DB_LOCK_OLDEST);
5161 ADD_INT(d, DB_LOCK_RANDOM);
5162 ADD_INT(d, DB_LOCK_YOUNGEST);
5163#if (DBVER >= 33)
5164 ADD_INT(d, DB_LOCK_MAXLOCKS);
5165 ADD_INT(d, DB_LOCK_MINLOCKS);
5166 ADD_INT(d, DB_LOCK_MINWRITE);
5167#endif
5168
5169
5170#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005171 /* docs say to use zero instead */
5172 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005173#else
5174 ADD_INT(d, DB_LOCK_CONFLICT);
5175#endif
5176
5177 ADD_INT(d, DB_LOCK_DUMP);
5178 ADD_INT(d, DB_LOCK_GET);
5179 ADD_INT(d, DB_LOCK_INHERIT);
5180 ADD_INT(d, DB_LOCK_PUT);
5181 ADD_INT(d, DB_LOCK_PUT_ALL);
5182 ADD_INT(d, DB_LOCK_PUT_OBJ);
5183
5184 ADD_INT(d, DB_LOCK_NG);
5185 ADD_INT(d, DB_LOCK_READ);
5186 ADD_INT(d, DB_LOCK_WRITE);
5187 ADD_INT(d, DB_LOCK_NOWAIT);
5188#if (DBVER >= 32)
5189 ADD_INT(d, DB_LOCK_WAIT);
5190#endif
5191 ADD_INT(d, DB_LOCK_IWRITE);
5192 ADD_INT(d, DB_LOCK_IREAD);
5193 ADD_INT(d, DB_LOCK_IWR);
5194#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005195#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005196 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005197#else
5198 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5199#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005200 ADD_INT(d, DB_LOCK_WWRITE);
5201#endif
5202
5203 ADD_INT(d, DB_LOCK_RECORD);
5204 ADD_INT(d, DB_LOCK_UPGRADE);
5205#if (DBVER >= 32)
5206 ADD_INT(d, DB_LOCK_SWITCH);
5207#endif
5208#if (DBVER >= 33)
5209 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5210#endif
5211
5212 ADD_INT(d, DB_LOCK_NOWAIT);
5213 ADD_INT(d, DB_LOCK_RECORD);
5214 ADD_INT(d, DB_LOCK_UPGRADE);
5215
5216#if (DBVER >= 33)
5217 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005218#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005219 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005220#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005221 ADD_INT(d, DB_LSTAT_FREE);
5222 ADD_INT(d, DB_LSTAT_HELD);
5223#if (DBVER == 33)
5224 ADD_INT(d, DB_LSTAT_NOGRANT);
5225#endif
5226 ADD_INT(d, DB_LSTAT_PENDING);
5227 ADD_INT(d, DB_LSTAT_WAITING);
5228#endif
5229
5230 ADD_INT(d, DB_ARCH_ABS);
5231 ADD_INT(d, DB_ARCH_DATA);
5232 ADD_INT(d, DB_ARCH_LOG);
5233
5234 ADD_INT(d, DB_BTREE);
5235 ADD_INT(d, DB_HASH);
5236 ADD_INT(d, DB_RECNO);
5237 ADD_INT(d, DB_QUEUE);
5238 ADD_INT(d, DB_UNKNOWN);
5239
5240 ADD_INT(d, DB_DUP);
5241 ADD_INT(d, DB_DUPSORT);
5242 ADD_INT(d, DB_RECNUM);
5243 ADD_INT(d, DB_RENUMBER);
5244 ADD_INT(d, DB_REVSPLITOFF);
5245 ADD_INT(d, DB_SNAPSHOT);
5246
5247 ADD_INT(d, DB_JOIN_NOSORT);
5248
5249 ADD_INT(d, DB_AFTER);
5250 ADD_INT(d, DB_APPEND);
5251 ADD_INT(d, DB_BEFORE);
5252 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005253#if (DBVER >= 41)
5254 _addIntToDict(d, "DB_CHECKPOINT", 0);
5255#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005256 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005257 ADD_INT(d, DB_CURLSN);
5258#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005259#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 ADD_INT(d, DB_COMMIT);
5261#endif
5262 ADD_INT(d, DB_CONSUME);
5263#if (DBVER >= 32)
5264 ADD_INT(d, DB_CONSUME_WAIT);
5265#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 ADD_INT(d, DB_CURRENT);
5267#if (DBVER >= 33)
5268 ADD_INT(d, DB_FAST_STAT);
5269#endif
5270 ADD_INT(d, DB_FIRST);
5271 ADD_INT(d, DB_FLUSH);
5272 ADD_INT(d, DB_GET_BOTH);
5273 ADD_INT(d, DB_GET_RECNO);
5274 ADD_INT(d, DB_JOIN_ITEM);
5275 ADD_INT(d, DB_KEYFIRST);
5276 ADD_INT(d, DB_KEYLAST);
5277 ADD_INT(d, DB_LAST);
5278 ADD_INT(d, DB_NEXT);
5279 ADD_INT(d, DB_NEXT_DUP);
5280 ADD_INT(d, DB_NEXT_NODUP);
5281 ADD_INT(d, DB_NODUPDATA);
5282 ADD_INT(d, DB_NOOVERWRITE);
5283 ADD_INT(d, DB_NOSYNC);
5284 ADD_INT(d, DB_POSITION);
5285 ADD_INT(d, DB_PREV);
5286 ADD_INT(d, DB_PREV_NODUP);
5287 ADD_INT(d, DB_RECORDCOUNT);
5288 ADD_INT(d, DB_SET);
5289 ADD_INT(d, DB_SET_RANGE);
5290 ADD_INT(d, DB_SET_RECNO);
5291 ADD_INT(d, DB_WRITECURSOR);
5292
5293 ADD_INT(d, DB_OPFLAGS_MASK);
5294 ADD_INT(d, DB_RMW);
5295#if (DBVER >= 33)
5296 ADD_INT(d, DB_DIRTY_READ);
5297 ADD_INT(d, DB_MULTIPLE);
5298 ADD_INT(d, DB_MULTIPLE_KEY);
5299#endif
5300
Gregory P. Smith29602d22006-01-24 09:46:48 +00005301#if (DBVER >= 44)
5302 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5303 ADD_INT(d, DB_READ_COMMITTED);
5304#endif
5305
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005306#if (DBVER >= 33)
5307 ADD_INT(d, DB_DONOTINDEX);
5308#endif
5309
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005310#if (DBVER >= 41)
5311 _addIntToDict(d, "DB_INCOMPLETE", 0);
5312#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005313 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005314#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005315 ADD_INT(d, DB_KEYEMPTY);
5316 ADD_INT(d, DB_KEYEXIST);
5317 ADD_INT(d, DB_LOCK_DEADLOCK);
5318 ADD_INT(d, DB_LOCK_NOTGRANTED);
5319 ADD_INT(d, DB_NOSERVER);
5320 ADD_INT(d, DB_NOSERVER_HOME);
5321 ADD_INT(d, DB_NOSERVER_ID);
5322 ADD_INT(d, DB_NOTFOUND);
5323 ADD_INT(d, DB_OLD_VERSION);
5324 ADD_INT(d, DB_RUNRECOVERY);
5325 ADD_INT(d, DB_VERIFY_BAD);
5326#if (DBVER >= 33)
5327 ADD_INT(d, DB_PAGE_NOTFOUND);
5328 ADD_INT(d, DB_SECONDARY_BAD);
5329#endif
5330#if (DBVER >= 40)
5331 ADD_INT(d, DB_STAT_CLEAR);
5332 ADD_INT(d, DB_REGION_INIT);
5333 ADD_INT(d, DB_NOLOCKING);
5334 ADD_INT(d, DB_YIELDCPU);
5335 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5336 ADD_INT(d, DB_NOPANIC);
5337#endif
5338
Gregory P. Smith41631e82003-09-21 00:08:14 +00005339#if (DBVER >= 42)
5340 ADD_INT(d, DB_TIME_NOTGRANTED);
5341 ADD_INT(d, DB_TXN_NOT_DURABLE);
5342 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5343 ADD_INT(d, DB_LOG_AUTOREMOVE);
5344 ADD_INT(d, DB_DIRECT_LOG);
5345 ADD_INT(d, DB_DIRECT_DB);
5346 ADD_INT(d, DB_INIT_REP);
5347 ADD_INT(d, DB_ENCRYPT);
5348 ADD_INT(d, DB_CHKSUM);
5349#endif
5350
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005351#if (DBVER >= 43)
5352 ADD_INT(d, DB_LOG_INMEMORY);
5353 ADD_INT(d, DB_BUFFER_SMALL);
5354#endif
5355
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005356#if (DBVER >= 41)
5357 ADD_INT(d, DB_ENCRYPT_AES);
5358 ADD_INT(d, DB_AUTO_COMMIT);
5359#else
5360 /* allow berkeleydb 4.1 aware apps to run on older versions */
5361 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5362#endif
5363
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005364 ADD_INT(d, EINVAL);
5365 ADD_INT(d, EACCES);
5366 ADD_INT(d, ENOSPC);
5367 ADD_INT(d, ENOMEM);
5368 ADD_INT(d, EAGAIN);
5369 ADD_INT(d, EBUSY);
5370 ADD_INT(d, EEXIST);
5371 ADD_INT(d, ENOENT);
5372 ADD_INT(d, EPERM);
5373
Barry Warsaw1baa9822003-03-31 19:51:29 +00005374#if (DBVER >= 40)
5375 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5376 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5377#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005378
5379 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005380 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005381 PyDict_SetItemString(d, "DBError", DBError);
5382
Gregory P. Smithe9477062005-06-04 06:46:59 +00005383 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5384 * from both DBError and KeyError, since the API only supports
5385 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005386 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005387 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5388 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005389 Py_file_input, d, d);
5390 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005391 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005392 PyDict_DelItemString(d, "KeyError");
5393
5394
5395 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005396#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005397 PyDict_SetItemString(d, #name, name)
5398
5399#if !INCOMPLETE_IS_WARNING
5400 MAKE_EX(DBIncompleteError);
5401#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005402 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005403 MAKE_EX(DBKeyEmptyError);
5404 MAKE_EX(DBKeyExistError);
5405 MAKE_EX(DBLockDeadlockError);
5406 MAKE_EX(DBLockNotGrantedError);
5407 MAKE_EX(DBOldVersionError);
5408 MAKE_EX(DBRunRecoveryError);
5409 MAKE_EX(DBVerifyBadError);
5410 MAKE_EX(DBNoServerError);
5411 MAKE_EX(DBNoServerHomeError);
5412 MAKE_EX(DBNoServerIDError);
5413#if (DBVER >= 33)
5414 MAKE_EX(DBPageNotFoundError);
5415 MAKE_EX(DBSecondaryBadError);
5416#endif
5417
5418 MAKE_EX(DBInvalidArgError);
5419 MAKE_EX(DBAccessError);
5420 MAKE_EX(DBNoSpaceError);
5421 MAKE_EX(DBNoMemoryError);
5422 MAKE_EX(DBAgainError);
5423 MAKE_EX(DBBusyError);
5424 MAKE_EX(DBFileExistsError);
5425 MAKE_EX(DBNoSuchFileError);
5426 MAKE_EX(DBPermissionsError);
5427
5428#undef MAKE_EX
5429
5430 /* Check for errors */
5431 if (PyErr_Occurred()) {
5432 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005433 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434 }
5435}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005436
5437/* allow this module to be named _pybsddb so that it can be installed
5438 * and imported on top of python >= 2.3 that includes its own older
5439 * copy of the library named _bsddb without importing the old version. */
5440DL_EXPORT(void) init_pybsddb(void)
5441{
5442 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5443 init_bsddb();
5444}