blob: 3c50a3974d932330f58eb595caa0af5387914a06 [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
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000104#if (PY_VERSION_HEX < 0x02050000)
105#define Py_ssize_t int
106#endif
107
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000108#ifdef WITH_THREAD
109
110/* These are for when calling Python --> C */
111#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
112#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
113
Mark Hammonda69d4092003-04-22 23:13:27 +0000114/* For 2.3, use the PyGILState_ calls */
115#if (PY_VERSION_HEX >= 0x02030000)
116#define MYDB_USE_GILSTATE
117#endif
118
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000119/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000120#if defined(MYDB_USE_GILSTATE)
121#define MYDB_BEGIN_BLOCK_THREADS \
122 PyGILState_STATE __savestate = PyGILState_Ensure();
123#define MYDB_END_BLOCK_THREADS \
124 PyGILState_Release(__savestate);
125#else /* MYDB_USE_GILSTATE */
126/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000127static PyInterpreterState* _db_interpreterState = NULL;
128#define MYDB_BEGIN_BLOCK_THREADS { \
129 PyThreadState* prevState; \
130 PyThreadState* newState; \
131 PyEval_AcquireLock(); \
132 newState = PyThreadState_New(_db_interpreterState); \
133 prevState = PyThreadState_Swap(newState);
134
135#define MYDB_END_BLOCK_THREADS \
136 newState = PyThreadState_Swap(prevState); \
137 PyThreadState_Clear(newState); \
138 PyEval_ReleaseLock(); \
139 PyThreadState_Delete(newState); \
140 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000141#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000142
143#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000144/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000145#define MYDB_BEGIN_ALLOW_THREADS
146#define MYDB_END_ALLOW_THREADS
147#define MYDB_BEGIN_BLOCK_THREADS
148#define MYDB_END_BLOCK_THREADS
149
150#endif
151
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000152/* Should DB_INCOMPLETE be turned into a warning or an exception? */
153#define INCOMPLETE_IS_WARNING 1
154
155/* --------------------------------------------------------------------- */
156/* Exceptions */
157
158static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000159static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000160static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000161static PyObject* DBKeyExistError; /* DB_KEYEXIST */
162static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
163static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
164static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
165static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
166static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
167static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
168static PyObject* DBNoServerError; /* DB_NOSERVER */
169static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
170static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
171#if (DBVER >= 33)
172static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
173static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
174#endif
175
176#if !INCOMPLETE_IS_WARNING
177static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
178#endif
179
180static PyObject* DBInvalidArgError; /* EINVAL */
181static PyObject* DBAccessError; /* EACCES */
182static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000183static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000184static PyObject* DBAgainError; /* EAGAIN */
185static PyObject* DBBusyError; /* EBUSY */
186static PyObject* DBFileExistsError; /* EEXIST */
187static PyObject* DBNoSuchFileError; /* ENOENT */
188static PyObject* DBPermissionsError; /* EPERM */
189
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000190#if (DBVER < 43)
191#define DB_BUFFER_SMALL ENOMEM
192#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000193
194
195/* --------------------------------------------------------------------- */
196/* Structure definitions */
197
Gregory P. Smitha703a212003-11-03 01:04:41 +0000198#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
199#define HAVE_WEAKREF
200#else
201#undef HAVE_WEAKREF
202#endif
203
Gregory P. Smith31c50652004-06-28 01:20:40 +0000204/* if Python >= 2.1 better support warnings */
205#if PYTHON_API_VERSION >= 1010
206#define HAVE_WARNINGS
207#else
208#undef HAVE_WARNINGS
209#endif
210
Neal Norwitzb4a55812004-07-09 23:30:57 +0000211#if PYTHON_API_VERSION <= 1007
212 /* 1.5 compatibility */
213#define PyObject_New PyObject_NEW
214#define PyObject_Del PyMem_DEL
215#endif
216
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000217struct behaviourFlags {
218 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000219 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000220 unsigned int getReturnsNone : 1;
221 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000222 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000223 unsigned int cursorSetReturnsNone : 1;
224};
225
226#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000227#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000228
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229typedef struct {
230 PyObject_HEAD
231 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000232 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000234 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000235#ifdef HAVE_WEAKREF
236 PyObject *in_weakreflist; /* List of weak references */
237#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000238} DBEnvObject;
239
240
241typedef struct {
242 PyObject_HEAD
243 DB* db;
244 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000245 u_int32_t flags; /* saved flags from open() */
246 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000247 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000248 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000249#if (DBVER >= 33)
250 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000251 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000252 int primaryDBType;
253#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000254#ifdef HAVE_WEAKREF
255 PyObject *in_weakreflist; /* List of weak references */
256#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000257} DBObject;
258
259
260typedef struct {
261 PyObject_HEAD
262 DBC* dbc;
263 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000264#ifdef HAVE_WEAKREF
265 PyObject *in_weakreflist; /* List of weak references */
266#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000267} DBCursorObject;
268
269
270typedef struct {
271 PyObject_HEAD
272 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000273 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000274#ifdef HAVE_WEAKREF
275 PyObject *in_weakreflist; /* List of weak references */
276#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000277} DBTxnObject;
278
279
280typedef struct {
281 PyObject_HEAD
282 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000283#ifdef HAVE_WEAKREF
284 PyObject *in_weakreflist; /* List of weak references */
285#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000286} DBLockObject;
287
288
289
290staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
291
292#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
293#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
294#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
295#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
296#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
297
298
299/* --------------------------------------------------------------------- */
300/* Utility macros and functions */
301
302#define RETURN_IF_ERR() \
303 if (makeDBError(err)) { \
304 return NULL; \
305 }
306
307#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
308
Gregory P. Smithe2767172003-11-02 08:06:29 +0000309#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
310 if ((nonNull) == NULL) { \
311 PyObject *errTuple = NULL; \
312 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
313 PyErr_SetObject((pyErrObj), errTuple); \
314 Py_DECREF(errTuple); \
315 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000316 }
317
Gregory P. Smithe2767172003-11-02 08:06:29 +0000318#define CHECK_DB_NOT_CLOSED(dbobj) \
319 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
320
321#define CHECK_ENV_NOT_CLOSED(env) \
322 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000323
324#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000325 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000326
327
328#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
329 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
330
331#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
332
333#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000334 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000335
336
337static int makeDBError(int err);
338
339
340/* Return the access method type of the DBObject */
341static int _DB_get_type(DBObject* self)
342{
343#if (DBVER >= 33)
344 DBTYPE type;
345 int err;
346 err = self->db->get_type(self->db, &type);
347 if (makeDBError(err)) {
348 return -1;
349 }
350 return type;
351#else
352 return self->db->get_type(self->db);
353#endif
354}
355
356
357/* Create a DBT structure (containing key and data values) from Python
358 strings. Returns 1 on success, 0 on an error. */
359static int make_dbt(PyObject* obj, DBT* dbt)
360{
361 CLEAR_DBT(*dbt);
362 if (obj == Py_None) {
363 /* no need to do anything, the structure has already been zeroed */
364 }
365 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
366 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000367 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000368 return 0;
369 }
370 return 1;
371}
372
373
374/* Recno and Queue DBs can have integer keys. This function figures out
375 what's been given, verifies that it's allowed, and then makes the DBT.
376
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000377 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000378static int
379make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000380{
381 db_recno_t recno;
382 int type;
383
384 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000385 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000386 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000387 if (type == -1)
388 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000389 if (type == DB_RECNO || type == DB_QUEUE) {
390 PyErr_SetString(
391 PyExc_TypeError,
392 "None keys not allowed for Recno and Queue DB's");
393 return 0;
394 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000395 /* no need to do anything, the structure has already been zeroed */
396 }
397
398 else if (PyString_Check(keyobj)) {
399 /* verify access method type */
400 type = _DB_get_type(self);
401 if (type == -1)
402 return 0;
403 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000404 PyErr_SetString(
405 PyExc_TypeError,
406 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000407 return 0;
408 }
409
410 key->data = PyString_AS_STRING(keyobj);
411 key->size = PyString_GET_SIZE(keyobj);
412 }
413
414 else if (PyInt_Check(keyobj)) {
415 /* verify access method type */
416 type = _DB_get_type(self);
417 if (type == -1)
418 return 0;
419 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000420 /* if BTREE then an Integer key is allowed with the
421 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000422 *pflags |= DB_SET_RECNO;
423 }
424 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000425 PyErr_SetString(
426 PyExc_TypeError,
427 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 return 0;
429 }
430
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000431 /* Make a key out of the requested recno, use allocated space so DB
432 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000433 recno = PyInt_AS_LONG(keyobj);
434 key->data = malloc(sizeof(db_recno_t));
435 if (key->data == NULL) {
436 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
437 return 0;
438 }
439 key->ulen = key->size = sizeof(db_recno_t);
440 memcpy(key->data, &recno, sizeof(db_recno_t));
441 key->flags = DB_DBT_REALLOC;
442 }
443 else {
444 PyErr_Format(PyExc_TypeError,
445 "String or Integer object expected for key, %s found",
446 keyobj->ob_type->tp_name);
447 return 0;
448 }
449
450 return 1;
451}
452
453
454/* Add partial record access to an existing DBT data struct.
455 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
456 and the data storage/retrieval will be done using dlen and doff. */
457static int add_partial_dbt(DBT* d, int dlen, int doff) {
458 /* if neither were set we do nothing (-1 is the default value) */
459 if ((dlen == -1) && (doff == -1)) {
460 return 1;
461 }
462
463 if ((dlen < 0) || (doff < 0)) {
464 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
465 return 0;
466 }
467
468 d->flags = d->flags | DB_DBT_PARTIAL;
469 d->dlen = (unsigned int) dlen;
470 d->doff = (unsigned int) doff;
471 return 1;
472}
473
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000474/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
475/* TODO: make this use the native libc strlcpy() when available (BSD) */
476unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
477{
478 unsigned int srclen, copylen;
479
480 srclen = strlen(src);
481 if (n <= 0)
482 return srclen;
483 copylen = (srclen > n-1) ? n-1 : srclen;
484 /* populate dest[0] thru dest[copylen-1] */
485 memcpy(dest, src, copylen);
486 /* guarantee null termination */
487 dest[copylen] = 0;
488
489 return srclen;
490}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000491
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000492/* Callback used to save away more information about errors from the DB
493 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000494static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000495#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000496static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000497#else
498static void _db_errorCallback(const DB_ENV *db_env,
499 const char* prefix, const char* msg)
500#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000501{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000502 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000503}
504
505
506/* make a nice exception object to raise for errors. */
507static int makeDBError(int err)
508{
509 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510 PyObject *errObj = NULL;
511 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512 int exceptionRaised = 0;
513
514 switch (err) {
515 case 0: /* successful, no error */ break;
516
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000517#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518 case DB_INCOMPLETE:
519#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521 if (_db_errmsg[0]) {
522 strcat(errTxt, " -- ");
523 strcat(errTxt, _db_errmsg);
524 _db_errmsg[0] = 0;
525 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000526#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000527 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
528#else
529 fprintf(stderr, errTxt);
530 fprintf(stderr, "\n");
531#endif
532
533#else /* do an exception instead */
534 errObj = DBIncompleteError;
535#endif
536 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000537#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000538
539 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
540 case DB_KEYEXIST: errObj = DBKeyExistError; break;
541 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
542 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
543 case DB_NOTFOUND: errObj = DBNotFoundError; break;
544 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
545 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
546 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
547 case DB_NOSERVER: errObj = DBNoServerError; break;
548 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
549 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
550#if (DBVER >= 33)
551 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
552 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
553#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000554 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000555
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000556#if (DBVER >= 43)
557 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
558 case ENOMEM: errObj = PyExc_MemoryError; break;
559#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560 case EINVAL: errObj = DBInvalidArgError; break;
561 case EACCES: errObj = DBAccessError; break;
562 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563 case EAGAIN: errObj = DBAgainError; break;
564 case EBUSY : errObj = DBBusyError; break;
565 case EEXIST: errObj = DBFileExistsError; break;
566 case ENOENT: errObj = DBNoSuchFileError; break;
567 case EPERM : errObj = DBPermissionsError; break;
568
569 default: errObj = DBError; break;
570 }
571
572 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000573 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000574 if (_db_errmsg[0]) {
575 strcat(errTxt, " -- ");
576 strcat(errTxt, _db_errmsg);
577 _db_errmsg[0] = 0;
578 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000579
580 errTuple = Py_BuildValue("(is)", err, errTxt);
581 PyErr_SetObject(errObj, errTuple);
582 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000583 }
584
585 return ((errObj != NULL) || exceptionRaised);
586}
587
588
589
590/* set a type exception */
591static void makeTypeError(char* expected, PyObject* found)
592{
593 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
594 expected, found->ob_type->tp_name);
595}
596
597
598/* verify that an obj is either None or a DBTxn, and set the txn pointer */
599static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
600{
601 if (txnobj == Py_None || txnobj == NULL) {
602 *txn = NULL;
603 return 1;
604 }
605 if (DBTxnObject_Check(txnobj)) {
606 *txn = ((DBTxnObject*)txnobj)->txn;
607 return 1;
608 }
609 else
610 makeTypeError("DBTxn", txnobj);
611 return 0;
612}
613
614
615/* Delete a key from a database
616 Returns 0 on success, -1 on an error. */
617static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
618{
619 int err;
620
621 MYDB_BEGIN_ALLOW_THREADS;
622 err = self->db->del(self->db, txn, key, 0);
623 MYDB_END_ALLOW_THREADS;
624 if (makeDBError(err)) {
625 return -1;
626 }
627 self->haveStat = 0;
628 return 0;
629}
630
631
632/* Store a key into a database
633 Returns 0 on success, -1 on an error. */
634static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
635{
636 int err;
637
638 MYDB_BEGIN_ALLOW_THREADS;
639 err = self->db->put(self->db, txn, key, data, flags);
640 MYDB_END_ALLOW_THREADS;
641 if (makeDBError(err)) {
642 return -1;
643 }
644 self->haveStat = 0;
645 return 0;
646}
647
648/* Get a key/data pair from a cursor */
649static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
650 PyObject *args, PyObject *kwargs, char *format)
651{
652 int err;
653 PyObject* retval = NULL;
654 DBT key, data;
655 int dlen = -1;
656 int doff = -1;
657 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000658 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000659
660 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
661 &flags, &dlen, &doff))
662 return NULL;
663
664 CHECK_CURSOR_NOT_CLOSED(self);
665
666 flags |= extra_flags;
667 CLEAR_DBT(key);
668 CLEAR_DBT(data);
669 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
670 /* Tell BerkeleyDB to malloc the return value (thread safe) */
671 data.flags = DB_DBT_MALLOC;
672 key.flags = DB_DBT_MALLOC;
673 }
674 if (!add_partial_dbt(&data, dlen, doff))
675 return NULL;
676
677 MYDB_BEGIN_ALLOW_THREADS;
678 err = self->dbc->c_get(self->dbc, &key, &data, flags);
679 MYDB_END_ALLOW_THREADS;
680
Gregory P. Smithe9477062005-06-04 06:46:59 +0000681 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
682 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000683 Py_INCREF(Py_None);
684 retval = Py_None;
685 }
686 else if (makeDBError(err)) {
687 retval = NULL;
688 }
689 else { /* otherwise, success! */
690
691 /* if Recno or Queue, return the key as an Int */
692 switch (_DB_get_type(self->mydb)) {
693 case -1:
694 retval = NULL;
695 break;
696
697 case DB_RECNO:
698 case DB_QUEUE:
699 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
700 data.data, data.size);
701 break;
702 case DB_HASH:
703 case DB_BTREE:
704 default:
705 retval = Py_BuildValue("s#s#", key.data, key.size,
706 data.data, data.size);
707 break;
708 }
709 }
710 if (!err) {
711 FREE_DBT(key);
712 FREE_DBT(data);
713 }
714 return retval;
715}
716
717
718/* add an integer to a dictionary using the given name as a key */
719static void _addIntToDict(PyObject* dict, char *name, int value)
720{
721 PyObject* v = PyInt_FromLong((long) value);
722 if (!v || PyDict_SetItemString(dict, name, v))
723 PyErr_Clear();
724
725 Py_XDECREF(v);
726}
727
728
729
730
731/* --------------------------------------------------------------------- */
732/* Allocators and deallocators */
733
734static DBObject*
735newDBObject(DBEnvObject* arg, int flags)
736{
737 DBObject* self;
738 DB_ENV* db_env = NULL;
739 int err;
740
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000741 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742 if (self == NULL)
743 return NULL;
744
745 self->haveStat = 0;
746 self->flags = 0;
747 self->setflags = 0;
748 self->myenvobj = NULL;
749#if (DBVER >= 33)
750 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000751 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 self->primaryDBType = 0;
753#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000754#ifdef HAVE_WEAKREF
755 self->in_weakreflist = NULL;
756#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757
758 /* keep a reference to our python DBEnv object */
759 if (arg) {
760 Py_INCREF(arg);
761 self->myenvobj = arg;
762 db_env = arg->db_env;
763 }
764
765 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000766 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000767 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000768 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
769 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770
771 MYDB_BEGIN_ALLOW_THREADS;
772 err = db_create(&self->db, db_env, flags);
773 self->db->set_errcall(self->db, _db_errorCallback);
774#if (DBVER >= 33)
775 self->db->app_private = (void*)self;
776#endif
777 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000778 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
779 * list so that a DBEnv can refuse to close without aborting any open
780 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781 if (makeDBError(err)) {
782 if (self->myenvobj) {
783 Py_DECREF(self->myenvobj);
784 self->myenvobj = NULL;
785 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000786 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 self = NULL;
788 }
789 return self;
790}
791
792
793static void
794DB_dealloc(DBObject* self)
795{
796 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000797 /* avoid closing a DB when its DBEnv has been closed out from under
798 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000800 (self->myenvobj && self->myenvobj->db_env))
801 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802 MYDB_BEGIN_ALLOW_THREADS;
803 self->db->close(self->db, 0);
804 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000805#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806 } else {
807 PyErr_Warn(PyExc_RuntimeWarning,
808 "DB could not be closed in destructor: DBEnv already closed");
809#endif
810 }
811 self->db = NULL;
812 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000813#ifdef HAVE_WEAKREF
814 if (self->in_weakreflist != NULL) {
815 PyObject_ClearWeakRefs((PyObject *) self);
816 }
817#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 if (self->myenvobj) {
819 Py_DECREF(self->myenvobj);
820 self->myenvobj = NULL;
821 }
822#if (DBVER >= 33)
823 if (self->associateCallback != NULL) {
824 Py_DECREF(self->associateCallback);
825 self->associateCallback = NULL;
826 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000827 if (self->btCompareCallback != NULL) {
828 Py_DECREF(self->btCompareCallback);
829 self->btCompareCallback = NULL;
830 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000831#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833}
834
835
836static DBCursorObject*
837newDBCursorObject(DBC* dbc, DBObject* db)
838{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000839 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000840 if (self == NULL)
841 return NULL;
842
843 self->dbc = dbc;
844 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000845#ifdef HAVE_WEAKREF
846 self->in_weakreflist = NULL;
847#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000848 Py_INCREF(self->mydb);
849 return self;
850}
851
852
853static void
854DBCursor_dealloc(DBCursorObject* self)
855{
856 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000857
858#ifdef HAVE_WEAKREF
859 if (self->in_weakreflist != NULL) {
860 PyObject_ClearWeakRefs((PyObject *) self);
861 }
862#endif
863
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 if (self->dbc != NULL) {
865 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000866 /* If the underlying database has been closed, we don't
867 need to do anything. If the environment has been closed
868 we need to leak, as BerkeleyDB will crash trying to access
869 the environment. There was an exception when the
870 user closed the environment even though there still was
871 a database open. */
872 if (self->mydb->db && self->mydb->myenvobj &&
873 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000874 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 self->dbc = NULL;
876 MYDB_END_ALLOW_THREADS;
877 }
878 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000880}
881
882
883static DBEnvObject*
884newDBEnvObject(int flags)
885{
886 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000887 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888 if (self == NULL)
889 return NULL;
890
891 self->closed = 1;
892 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000893 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
894 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000895#ifdef HAVE_WEAKREF
896 self->in_weakreflist = NULL;
897#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000898
899 MYDB_BEGIN_ALLOW_THREADS;
900 err = db_env_create(&self->db_env, flags);
901 MYDB_END_ALLOW_THREADS;
902 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000903 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000904 self = NULL;
905 }
906 else {
907 self->db_env->set_errcall(self->db_env, _db_errorCallback);
908 }
909 return self;
910}
911
912
913static void
914DBEnv_dealloc(DBEnvObject* self)
915{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000916#ifdef HAVE_WEAKREF
917 if (self->in_weakreflist != NULL) {
918 PyObject_ClearWeakRefs((PyObject *) self);
919 }
920#endif
921
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000922 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000923 MYDB_BEGIN_ALLOW_THREADS;
924 self->db_env->close(self->db_env, 0);
925 MYDB_END_ALLOW_THREADS;
926 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928}
929
930
931static DBTxnObject*
932newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
933{
934 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000935 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000936 if (self == NULL)
937 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000938 Py_INCREF(myenv);
939 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000940#ifdef HAVE_WEAKREF
941 self->in_weakreflist = NULL;
942#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943
944 MYDB_BEGIN_ALLOW_THREADS;
945#if (DBVER >= 40)
946 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
947#else
948 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
949#endif
950 MYDB_END_ALLOW_THREADS;
951 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000952 Py_DECREF(self->env);
953 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954 self = NULL;
955 }
956 return self;
957}
958
959
960static void
961DBTxn_dealloc(DBTxnObject* self)
962{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000963#ifdef HAVE_WEAKREF
964 if (self->in_weakreflist != NULL) {
965 PyObject_ClearWeakRefs((PyObject *) self);
966 }
967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
Gregory P. Smith31c50652004-06-28 01:20:40 +0000969#ifdef HAVE_WARNINGS
970 if (self->txn) {
971 /* it hasn't been finalized, abort it! */
972 MYDB_BEGIN_ALLOW_THREADS;
973#if (DBVER >= 40)
974 self->txn->abort(self->txn);
975#else
976 txn_abort(self->txn);
977#endif
978 MYDB_END_ALLOW_THREADS;
979 PyErr_Warn(PyExc_RuntimeWarning,
980 "DBTxn aborted in destructor. No prior commit() or abort().");
981 }
982#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983
Neal Norwitz62a21122006-01-25 05:21:55 +0000984 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000986}
987
988
989static DBLockObject*
990newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
991 db_lockmode_t lock_mode, int flags)
992{
993 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000994 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000995 if (self == NULL)
996 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000997#ifdef HAVE_WEAKREF
998 self->in_weakreflist = NULL;
999#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001000
1001 MYDB_BEGIN_ALLOW_THREADS;
1002#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001003 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1004 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005#else
1006 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1007#endif
1008 MYDB_END_ALLOW_THREADS;
1009 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001010 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011 self = NULL;
1012 }
1013
1014 return self;
1015}
1016
1017
1018static void
1019DBLock_dealloc(DBLockObject* self)
1020{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001021#ifdef HAVE_WEAKREF
1022 if (self->in_weakreflist != NULL) {
1023 PyObject_ClearWeakRefs((PyObject *) self);
1024 }
1025#endif
1026 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001027
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001028 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029}
1030
1031
1032/* --------------------------------------------------------------------- */
1033/* DB methods */
1034
1035static PyObject*
1036DB_append(DBObject* self, PyObject* args)
1037{
1038 PyObject* txnobj = NULL;
1039 PyObject* dataobj;
1040 db_recno_t recno;
1041 DBT key, data;
1042 DB_TXN *txn = NULL;
1043
Georg Brandl96a8c392006-05-29 21:04:52 +00001044 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045 return NULL;
1046
1047 CHECK_DB_NOT_CLOSED(self);
1048
1049 /* make a dummy key out of a recno */
1050 recno = 0;
1051 CLEAR_DBT(key);
1052 key.data = &recno;
1053 key.size = sizeof(recno);
1054 key.ulen = key.size;
1055 key.flags = DB_DBT_USERMEM;
1056
1057 if (!make_dbt(dataobj, &data)) return NULL;
1058 if (!checkTxnObj(txnobj, &txn)) return NULL;
1059
1060 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1061 return NULL;
1062
1063 return PyInt_FromLong(recno);
1064}
1065
1066
1067#if (DBVER >= 33)
1068
1069static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001070_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1071 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001072{
1073 int retval = DB_DONOTINDEX;
1074 DBObject* secondaryDB = (DBObject*)db->app_private;
1075 PyObject* callback = secondaryDB->associateCallback;
1076 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001077 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001078 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001079
1080
1081 if (callback != NULL) {
1082 MYDB_BEGIN_BLOCK_THREADS;
1083
Thomas Woutersb3153832006-03-08 01:47:19 +00001084 if (type == DB_RECNO || type == DB_QUEUE)
1085 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1086 priData->data, priData->size);
1087 else
1088 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1089 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001090 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001091 result = PyEval_CallObject(callback, args);
1092 }
1093 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001094 PyErr_Print();
1095 }
1096 else if (result == Py_None) {
1097 retval = DB_DONOTINDEX;
1098 }
1099 else if (PyInt_Check(result)) {
1100 retval = PyInt_AsLong(result);
1101 }
1102 else if (PyString_Check(result)) {
1103 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001104 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001105
1106 CLEAR_DBT(*secKey);
1107#if PYTHON_API_VERSION <= 1007
1108 /* 1.5 compatibility */
1109 size = PyString_Size(result);
1110 data = PyString_AsString(result);
1111#else
1112 PyString_AsStringAndSize(result, &data, &size);
1113#endif
1114 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1115 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001116 if (secKey->data) {
1117 memcpy(secKey->data, data, size);
1118 secKey->size = size;
1119 retval = 0;
1120 }
1121 else {
1122 PyErr_SetString(PyExc_MemoryError,
1123 "malloc failed in _db_associateCallback");
1124 PyErr_Print();
1125 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001126 }
1127 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001128 PyErr_SetString(
1129 PyExc_TypeError,
1130 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001131 PyErr_Print();
1132 }
1133
Thomas Woutersb3153832006-03-08 01:47:19 +00001134 Py_XDECREF(args);
1135 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136
1137 MYDB_END_BLOCK_THREADS;
1138 }
1139 return retval;
1140}
1141
1142
1143static PyObject*
1144DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1145{
1146 int err, flags=0;
1147 DBObject* secondaryDB;
1148 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149#if (DBVER >= 41)
1150 PyObject *txnobj = NULL;
1151 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001152 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001153 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001154#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001155 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001156#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001157
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001158#if (DBVER >= 41)
1159 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1160 &secondaryDB, &callback, &flags,
1161 &txnobj)) {
1162#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001164 &secondaryDB, &callback, &flags)) {
1165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001166 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001167 }
1168
1169#if (DBVER >= 41)
1170 if (!checkTxnObj(txnobj, &txn)) return NULL;
1171#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172
1173 CHECK_DB_NOT_CLOSED(self);
1174 if (!DBObject_Check(secondaryDB)) {
1175 makeTypeError("DB", (PyObject*)secondaryDB);
1176 return NULL;
1177 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001178 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001179 if (callback == Py_None) {
1180 callback = NULL;
1181 }
1182 else if (!PyCallable_Check(callback)) {
1183 makeTypeError("Callable", callback);
1184 return NULL;
1185 }
1186
1187 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001188 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001189 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001190 secondaryDB->associateCallback = callback;
1191 secondaryDB->primaryDBType = _DB_get_type(self);
1192
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001193 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1194 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1195 * The global interepreter lock is not initialized until the first
1196 * thread is created using thread.start_new_thread() or fork() is
1197 * called. that would cause the ALLOW_THREADS here to segfault due
1198 * to a null pointer reference if no threads or child processes
1199 * have been created. This works around that and is a no-op if
1200 * threads have already been initialized.
1201 * (see pybsddb-users mailing list post on 2002-08-07)
1202 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001203#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001204 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001205#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207#if (DBVER >= 41)
1208 err = self->db->associate(self->db,
1209 txn,
1210 secondaryDB->db,
1211 _db_associateCallback,
1212 flags);
1213#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001214 err = self->db->associate(self->db,
1215 secondaryDB->db,
1216 _db_associateCallback,
1217 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001218#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219 MYDB_END_ALLOW_THREADS;
1220
1221 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001222 Py_XDECREF(secondaryDB->associateCallback);
1223 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001224 secondaryDB->primaryDBType = 0;
1225 }
1226
1227 RETURN_IF_ERR();
1228 RETURN_NONE();
1229}
1230
1231
1232#endif
1233
1234
1235static PyObject*
1236DB_close(DBObject* self, PyObject* args)
1237{
1238 int err, flags=0;
1239 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1240 return NULL;
1241 if (self->db != NULL) {
1242 if (self->myenvobj)
1243 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001244 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245 self->db = NULL;
1246 RETURN_IF_ERR();
1247 }
1248 RETURN_NONE();
1249}
1250
1251
1252#if (DBVER >= 32)
1253static PyObject*
1254_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1255{
1256 int err, flags=0, type;
1257 PyObject* txnobj = NULL;
1258 PyObject* retval = NULL;
1259 DBT key, data;
1260 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001261 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001262
1263 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1264 &txnobj, &flags))
1265 return NULL;
1266
1267 CHECK_DB_NOT_CLOSED(self);
1268 type = _DB_get_type(self);
1269 if (type == -1)
1270 return NULL;
1271 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001272 PyErr_SetString(PyExc_TypeError,
1273 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001274 return NULL;
1275 }
1276 if (!checkTxnObj(txnobj, &txn))
1277 return NULL;
1278
1279 CLEAR_DBT(key);
1280 CLEAR_DBT(data);
1281 if (CHECK_DBFLAG(self, DB_THREAD)) {
1282 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1283 data.flags = DB_DBT_MALLOC;
1284 key.flags = DB_DBT_MALLOC;
1285 }
1286
1287 MYDB_BEGIN_ALLOW_THREADS;
1288 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1289 MYDB_END_ALLOW_THREADS;
1290
Gregory P. Smithe9477062005-06-04 06:46:59 +00001291 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1292 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293 err = 0;
1294 Py_INCREF(Py_None);
1295 retval = Py_None;
1296 }
1297 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001298 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1299 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300 FREE_DBT(key);
1301 FREE_DBT(data);
1302 }
1303
1304 RETURN_IF_ERR();
1305 return retval;
1306}
1307
1308static PyObject*
1309DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1310{
1311 return _DB_consume(self, args, kwargs, DB_CONSUME);
1312}
1313
1314static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001315DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1316 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001317{
1318 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1319}
1320#endif
1321
1322
1323
1324static PyObject*
1325DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1326{
1327 int err, flags=0;
1328 DBC* dbc;
1329 PyObject* txnobj = NULL;
1330 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001331 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1336 CHECK_DB_NOT_CLOSED(self);
1337 if (!checkTxnObj(txnobj, &txn))
1338 return NULL;
1339
1340 MYDB_BEGIN_ALLOW_THREADS;
1341 err = self->db->cursor(self->db, txn, &dbc, flags);
1342 MYDB_END_ALLOW_THREADS;
1343 RETURN_IF_ERR();
1344 return (PyObject*) newDBCursorObject(dbc, self);
1345}
1346
1347
1348static PyObject*
1349DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1350{
1351 PyObject* txnobj = NULL;
1352 int flags = 0;
1353 PyObject* keyobj;
1354 DBT key;
1355 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001356 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001357
1358 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1359 &keyobj, &txnobj, &flags))
1360 return NULL;
1361 CHECK_DB_NOT_CLOSED(self);
1362 if (!make_key_dbt(self, keyobj, &key, NULL))
1363 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001364 if (!checkTxnObj(txnobj, &txn)) {
1365 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001367 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001369 if (-1 == _DB_delete(self, txn, &key, 0)) {
1370 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001372 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001373
1374 FREE_DBT(key);
1375 RETURN_NONE();
1376}
1377
1378
1379static PyObject*
1380DB_fd(DBObject* self, PyObject* args)
1381{
1382 int err, the_fd;
1383
1384 if (!PyArg_ParseTuple(args,":fd"))
1385 return NULL;
1386 CHECK_DB_NOT_CLOSED(self);
1387
1388 MYDB_BEGIN_ALLOW_THREADS;
1389 err = self->db->fd(self->db, &the_fd);
1390 MYDB_END_ALLOW_THREADS;
1391 RETURN_IF_ERR();
1392 return PyInt_FromLong(the_fd);
1393}
1394
1395
1396static PyObject*
1397DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1398{
1399 int err, flags=0;
1400 PyObject* txnobj = NULL;
1401 PyObject* keyobj;
1402 PyObject* dfltobj = NULL;
1403 PyObject* retval = NULL;
1404 int dlen = -1;
1405 int doff = -1;
1406 DBT key, data;
1407 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001408 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001409 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410
1411 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001412 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1413 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414 return NULL;
1415
1416 CHECK_DB_NOT_CLOSED(self);
1417 if (!make_key_dbt(self, keyobj, &key, &flags))
1418 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001419 if (!checkTxnObj(txnobj, &txn)) {
1420 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001422 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423
1424 CLEAR_DBT(data);
1425 if (CHECK_DBFLAG(self, DB_THREAD)) {
1426 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1427 data.flags = DB_DBT_MALLOC;
1428 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001429 if (!add_partial_dbt(&data, dlen, doff)) {
1430 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001432 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001433
1434 MYDB_BEGIN_ALLOW_THREADS;
1435 err = self->db->get(self->db, txn, &key, &data, flags);
1436 MYDB_END_ALLOW_THREADS;
1437
Gregory P. Smithe9477062005-06-04 06:46:59 +00001438 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439 err = 0;
1440 Py_INCREF(dfltobj);
1441 retval = dfltobj;
1442 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001443 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1444 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 err = 0;
1446 Py_INCREF(Py_None);
1447 retval = Py_None;
1448 }
1449 else if (!err) {
1450 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001451 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1452 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001453 else /* return just the data */
1454 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001455 FREE_DBT(data);
1456 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001457 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001458
1459 RETURN_IF_ERR();
1460 return retval;
1461}
1462
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001463#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001464static PyObject*
1465DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1466{
1467 int err, flags=0;
1468 PyObject* txnobj = NULL;
1469 PyObject* keyobj;
1470 PyObject* dfltobj = NULL;
1471 PyObject* retval = NULL;
1472 int dlen = -1;
1473 int doff = -1;
1474 DBT key, pkey, data;
1475 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001476 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001477 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001478
1479 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1480 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1481 &doff))
1482 return NULL;
1483
1484 CHECK_DB_NOT_CLOSED(self);
1485 if (!make_key_dbt(self, keyobj, &key, &flags))
1486 return NULL;
1487 if (!checkTxnObj(txnobj, &txn)) {
1488 FREE_DBT(key);
1489 return NULL;
1490 }
1491
1492 CLEAR_DBT(data);
1493 if (CHECK_DBFLAG(self, DB_THREAD)) {
1494 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1495 data.flags = DB_DBT_MALLOC;
1496 }
1497 if (!add_partial_dbt(&data, dlen, doff)) {
1498 FREE_DBT(key);
1499 return NULL;
1500 }
1501
1502 CLEAR_DBT(pkey);
1503 pkey.flags = DB_DBT_MALLOC;
1504
1505 MYDB_BEGIN_ALLOW_THREADS;
1506 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1507 MYDB_END_ALLOW_THREADS;
1508
Gregory P. Smithe9477062005-06-04 06:46:59 +00001509 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001510 err = 0;
1511 Py_INCREF(dfltobj);
1512 retval = dfltobj;
1513 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001514 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1515 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001516 err = 0;
1517 Py_INCREF(Py_None);
1518 retval = Py_None;
1519 }
1520 else if (!err) {
1521 PyObject *pkeyObj;
1522 PyObject *dataObj;
1523 dataObj = PyString_FromStringAndSize(data.data, data.size);
1524
1525 if (self->primaryDBType == DB_RECNO ||
1526 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001527 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001528 else
1529 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1530
1531 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1532 {
1533 PyObject *keyObj;
1534 int type = _DB_get_type(self);
1535 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001536 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001537 else
1538 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001539#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001540 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001541#else
1542 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1543#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001544 Py_DECREF(keyObj);
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 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001554 Py_DECREF(dataObj);
1555 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001556 FREE_DBT(pkey);
1557 FREE_DBT(data);
1558 }
1559 FREE_DBT(key);
1560
1561 RETURN_IF_ERR();
1562 return retval;
1563}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001564#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001565
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566
1567/* Return size of entry */
1568static PyObject*
1569DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1570{
1571 int err, flags=0;
1572 PyObject* txnobj = NULL;
1573 PyObject* keyobj;
1574 PyObject* retval = NULL;
1575 DBT key, data;
1576 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001577 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001578
1579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1580 &keyobj, &txnobj))
1581 return NULL;
1582 CHECK_DB_NOT_CLOSED(self);
1583 if (!make_key_dbt(self, keyobj, &key, &flags))
1584 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001585 if (!checkTxnObj(txnobj, &txn)) {
1586 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001587 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001588 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589 CLEAR_DBT(data);
1590
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001591 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1592 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001593 data.flags = DB_DBT_USERMEM;
1594 data.ulen = 0;
1595 MYDB_BEGIN_ALLOW_THREADS;
1596 err = self->db->get(self->db, txn, &key, &data, flags);
1597 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001598 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599 retval = PyInt_FromLong((long)data.size);
1600 err = 0;
1601 }
1602
1603 FREE_DBT(key);
1604 FREE_DBT(data);
1605 RETURN_IF_ERR();
1606 return retval;
1607}
1608
1609
1610static PyObject*
1611DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1612{
1613 int err, flags=0;
1614 PyObject* txnobj = NULL;
1615 PyObject* keyobj;
1616 PyObject* dataobj;
1617 PyObject* retval = NULL;
1618 DBT key, data;
1619 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001620 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001621
1622
1623 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1624 &keyobj, &dataobj, &txnobj, &flags))
1625 return NULL;
1626
1627 CHECK_DB_NOT_CLOSED(self);
1628 if (!make_key_dbt(self, keyobj, &key, NULL))
1629 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001630 if ( !make_dbt(dataobj, &data) ||
1631 !checkTxnObj(txnobj, &txn) )
1632 {
1633 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001635 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636
1637 flags |= DB_GET_BOTH;
1638
1639 if (CHECK_DBFLAG(self, DB_THREAD)) {
1640 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1641 data.flags = DB_DBT_MALLOC;
1642 /* TODO: Is this flag needed? We're passing a data object that should
1643 match what's in the DB, so there should be no need to malloc.
1644 We run the risk of freeing something twice! Check this. */
1645 }
1646
1647 MYDB_BEGIN_ALLOW_THREADS;
1648 err = self->db->get(self->db, txn, &key, &data, flags);
1649 MYDB_END_ALLOW_THREADS;
1650
Gregory P. Smithe9477062005-06-04 06:46:59 +00001651 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1652 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001653 err = 0;
1654 Py_INCREF(Py_None);
1655 retval = Py_None;
1656 }
1657 else if (!err) {
1658 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1659 FREE_DBT(data); /* Only if retrieval was successful */
1660 }
1661
1662 FREE_DBT(key);
1663 RETURN_IF_ERR();
1664 return retval;
1665}
1666
1667
1668static PyObject*
1669DB_get_byteswapped(DBObject* self, PyObject* args)
1670{
1671#if (DBVER >= 33)
1672 int err = 0;
1673#endif
1674 int retval = -1;
1675
1676 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1677 return NULL;
1678 CHECK_DB_NOT_CLOSED(self);
1679
1680#if (DBVER >= 33)
1681 MYDB_BEGIN_ALLOW_THREADS;
1682 err = self->db->get_byteswapped(self->db, &retval);
1683 MYDB_END_ALLOW_THREADS;
1684 RETURN_IF_ERR();
1685#else
1686 MYDB_BEGIN_ALLOW_THREADS;
1687 retval = self->db->get_byteswapped(self->db);
1688 MYDB_END_ALLOW_THREADS;
1689#endif
1690 return PyInt_FromLong(retval);
1691}
1692
1693
1694static PyObject*
1695DB_get_type(DBObject* self, PyObject* args)
1696{
1697 int type;
1698
1699 if (!PyArg_ParseTuple(args,":get_type"))
1700 return NULL;
1701 CHECK_DB_NOT_CLOSED(self);
1702
1703 MYDB_BEGIN_ALLOW_THREADS;
1704 type = _DB_get_type(self);
1705 MYDB_END_ALLOW_THREADS;
1706 if (type == -1)
1707 return NULL;
1708 return PyInt_FromLong(type);
1709}
1710
1711
1712static PyObject*
1713DB_join(DBObject* self, PyObject* args)
1714{
1715 int err, flags=0;
1716 int length, x;
1717 PyObject* cursorsObj;
1718 DBC** cursors;
1719 DBC* dbc;
1720
1721
1722 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1723 return NULL;
1724
1725 CHECK_DB_NOT_CLOSED(self);
1726
1727 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001728 PyErr_SetString(PyExc_TypeError,
1729 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001730 return NULL;
1731 }
1732
1733 length = PyObject_Length(cursorsObj);
1734 cursors = malloc((length+1) * sizeof(DBC*));
1735 cursors[length] = NULL;
1736 for (x=0; x<length; x++) {
1737 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001738 if (item == NULL) {
1739 free(cursors);
1740 return NULL;
1741 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001743 PyErr_SetString(PyExc_TypeError,
1744 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 free(cursors);
1746 return NULL;
1747 }
1748 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001749 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750 }
1751
1752 MYDB_BEGIN_ALLOW_THREADS;
1753 err = self->db->join(self->db, cursors, &dbc, flags);
1754 MYDB_END_ALLOW_THREADS;
1755 free(cursors);
1756 RETURN_IF_ERR();
1757
Gregory P. Smith7441e652003-11-03 21:35:31 +00001758 /* FIXME: this is a buggy interface. The returned cursor
1759 contains internal references to the passed in cursors
1760 but does not hold python references to them or prevent
1761 them from being closed prematurely. This can cause
1762 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001763 return (PyObject*) newDBCursorObject(dbc, self);
1764}
1765
1766
1767static PyObject*
1768DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1769{
1770 int err, flags=0;
1771 PyObject* txnobj = NULL;
1772 PyObject* keyobj;
1773 DBT key;
1774 DB_TXN *txn = NULL;
1775 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001776 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001777
1778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1779 &keyobj, &txnobj, &flags))
1780 return NULL;
1781 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001782 if (!make_dbt(keyobj, &key))
1783 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001784 return NULL;
1785 if (!checkTxnObj(txnobj, &txn))
1786 return NULL;
1787
1788 MYDB_BEGIN_ALLOW_THREADS;
1789 err = self->db->key_range(self->db, txn, &key, &range, flags);
1790 MYDB_END_ALLOW_THREADS;
1791
1792 RETURN_IF_ERR();
1793 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1794}
1795
1796
1797static PyObject*
1798DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1799{
1800 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1801 char* filename = NULL;
1802 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001803#if (DBVER >= 41)
1804 PyObject *txnobj = NULL;
1805 DB_TXN *txn = NULL;
1806 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001807 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001808 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1809 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001810 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001811 "filename", "dbtype", "flags", "mode", "txn", NULL};
1812#else
1813 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001814 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001815 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1816 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001817 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001818 "filename", "dbtype", "flags", "mode", NULL};
1819#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001820
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001821#if (DBVER >= 41)
1822 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1823 &filename, &dbname, &type, &flags, &mode,
1824 &txnobj))
1825#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001826 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827 &filename, &dbname, &type, &flags,
1828 &mode))
1829#endif
1830 {
1831 PyErr_Clear();
1832 type = DB_UNKNOWN; flags = 0; mode = 0660;
1833 filename = NULL; dbname = NULL;
1834#if (DBVER >= 41)
1835 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1836 kwnames_basic,
1837 &filename, &type, &flags, &mode,
1838 &txnobj))
1839 return NULL;
1840#else
1841 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1842 kwnames_basic,
1843 &filename, &type, &flags, &mode))
1844 return NULL;
1845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846 }
1847
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001848#if (DBVER >= 41)
1849 if (!checkTxnObj(txnobj, &txn)) return NULL;
1850#endif
1851
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001853 PyObject *t = Py_BuildValue("(is)", 0,
1854 "Cannot call open() twice for DB object");
1855 PyErr_SetObject(DBError, t);
1856 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001857 return NULL;
1858 }
1859
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001860#if 0 && (DBVER >= 41)
1861 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1862 && (self->myenvobj->flags & DB_INIT_TXN))
1863 {
1864 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1865 * explicitly passed) but we are in a transaction ready environment:
1866 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1867 * to work on BerkeleyDB 4.1 without needing to modify their
1868 * DBEnv or DB open calls.
1869 * TODO make this behaviour of the library configurable.
1870 */
1871 flags |= DB_AUTO_COMMIT;
1872 }
1873#endif
1874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001876#if (DBVER >= 41)
1877 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1878#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001879 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001880#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001881 MYDB_END_ALLOW_THREADS;
1882 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001883 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001884 self->db = NULL;
1885 return NULL;
1886 }
1887
1888 self->flags = flags;
1889 RETURN_NONE();
1890}
1891
1892
1893static PyObject*
1894DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1895{
1896 int flags=0;
1897 PyObject* txnobj = NULL;
1898 int dlen = -1;
1899 int doff = -1;
1900 PyObject* keyobj, *dataobj, *retval;
1901 DBT key, data;
1902 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001903 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001904 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001905
1906 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1907 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1908 return NULL;
1909
1910 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001911 if (!make_key_dbt(self, keyobj, &key, NULL))
1912 return NULL;
1913 if ( !make_dbt(dataobj, &data) ||
1914 !add_partial_dbt(&data, dlen, doff) ||
1915 !checkTxnObj(txnobj, &txn) )
1916 {
1917 FREE_DBT(key);
1918 return NULL;
1919 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001920
1921 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1922 FREE_DBT(key);
1923 return NULL;
1924 }
1925
1926 if (flags & DB_APPEND)
1927 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1928 else {
1929 retval = Py_None;
1930 Py_INCREF(retval);
1931 }
1932 FREE_DBT(key);
1933 return retval;
1934}
1935
1936
1937
1938static PyObject*
1939DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1940{
1941 char* filename;
1942 char* database = NULL;
1943 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001944 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945
1946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1947 &filename, &database, &flags))
1948 return NULL;
1949 CHECK_DB_NOT_CLOSED(self);
1950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001952 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001953 RETURN_IF_ERR();
1954 RETURN_NONE();
1955}
1956
1957
1958
1959static PyObject*
1960DB_rename(DBObject* self, PyObject* args)
1961{
1962 char* filename;
1963 char* database;
1964 char* newname;
1965 int err, flags=0;
1966
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001967 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1968 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001969 return NULL;
1970 CHECK_DB_NOT_CLOSED(self);
1971
1972 MYDB_BEGIN_ALLOW_THREADS;
1973 err = self->db->rename(self->db, filename, database, newname, flags);
1974 MYDB_END_ALLOW_THREADS;
1975 RETURN_IF_ERR();
1976 RETURN_NONE();
1977}
1978
1979
1980static PyObject*
1981DB_set_bt_minkey(DBObject* self, PyObject* args)
1982{
1983 int err, minkey;
1984
1985 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1986 return NULL;
1987 CHECK_DB_NOT_CLOSED(self);
1988
1989 MYDB_BEGIN_ALLOW_THREADS;
1990 err = self->db->set_bt_minkey(self->db, minkey);
1991 MYDB_END_ALLOW_THREADS;
1992 RETURN_IF_ERR();
1993 RETURN_NONE();
1994}
1995
Neal Norwitz84562352005-10-20 04:30:15 +00001996#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001997static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001998_default_cmp(const DBT *leftKey,
1999 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002000{
2001 int res;
2002 int lsize = leftKey->size, rsize = rightKey->size;
2003
Georg Brandlef1701f2006-03-07 14:57:48 +00002004 res = memcmp(leftKey->data, rightKey->data,
2005 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002006
2007 if (res == 0) {
2008 if (lsize < rsize) {
2009 res = -1;
2010 }
2011 else if (lsize > rsize) {
2012 res = 1;
2013 }
2014 }
2015 return res;
2016}
2017
2018static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002019_db_compareCallback(DB* db,
2020 const DBT *leftKey,
2021 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002022{
2023 int res = 0;
2024 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002025 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002026 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002027
2028 if (self == NULL || self->btCompareCallback == NULL) {
2029 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002030 PyErr_SetString(PyExc_TypeError,
2031 (self == 0
2032 ? "DB_bt_compare db is NULL."
2033 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002034 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002035 PyErr_Print();
2036 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002037 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002038 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002039 MYDB_BEGIN_BLOCK_THREADS;
2040
Thomas Woutersb3153832006-03-08 01:47:19 +00002041 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2042 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002043 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002044 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002045 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002046 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002047 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002048 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002049 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002050 PyErr_Print();
2051 res = _default_cmp(leftKey, rightKey);
2052 } else if (PyInt_Check(result)) {
2053 res = PyInt_AsLong(result);
2054 } else {
2055 PyErr_SetString(PyExc_TypeError,
2056 "DB_bt_compare callback MUST return an int.");
2057 /* we're in a callback within the DB code, we can't raise */
2058 PyErr_Print();
2059 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002060 }
2061
Thomas Woutersb3153832006-03-08 01:47:19 +00002062 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002063 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002064
2065 MYDB_END_BLOCK_THREADS;
2066 }
2067 return res;
2068}
2069
2070static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002071DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002072{
2073 int err;
2074 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002075 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002076
Georg Brandlef1701f2006-03-07 14:57:48 +00002077 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002078 return NULL;
2079
Georg Brandlef1701f2006-03-07 14:57:48 +00002080 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081
Georg Brandlef1701f2006-03-07 14:57:48 +00002082 if (!PyCallable_Check(comparator)) {
2083 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002084 return NULL;
2085 }
2086
2087 /*
2088 * Perform a test call of the comparator function with two empty
2089 * string objects here. verify that it returns an int (0).
2090 * err if not.
2091 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002092 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002093 result = PyEval_CallObject(comparator, tuple);
2094 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002095 if (result == NULL)
2096 return NULL;
2097 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002098 PyErr_SetString(PyExc_TypeError,
2099 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002101 } else if (PyInt_AsLong(result) != 0) {
2102 PyErr_SetString(PyExc_TypeError,
2103 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104 return NULL;
2105 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002106 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107
2108 /* We don't accept multiple set_bt_compare operations, in order to
2109 * simplify the code. This would have no real use, as one cannot
2110 * change the function once the db is opened anyway */
2111 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002113 return NULL;
2114 }
2115
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002117 self->btCompareCallback = comparator;
2118
2119 /* This is to workaround a problem with un-initialized threads (see
2120 comment in DB_associate) */
2121#ifdef WITH_THREAD
2122 PyEval_InitThreads();
2123#endif
2124
Thomas Woutersb3153832006-03-08 01:47:19 +00002125 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126
2127 if (err) {
2128 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 self->btCompareCallback = NULL;
2131 }
2132
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 RETURN_IF_ERR();
2134 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002135}
Neal Norwitz84562352005-10-20 04:30:15 +00002136#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002138
2139static PyObject*
2140DB_set_cachesize(DBObject* self, PyObject* args)
2141{
2142 int err;
2143 int gbytes = 0, bytes = 0, ncache = 0;
2144
2145 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2146 &gbytes,&bytes,&ncache))
2147 return NULL;
2148 CHECK_DB_NOT_CLOSED(self);
2149
2150 MYDB_BEGIN_ALLOW_THREADS;
2151 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2152 MYDB_END_ALLOW_THREADS;
2153 RETURN_IF_ERR();
2154 RETURN_NONE();
2155}
2156
2157
2158static PyObject*
2159DB_set_flags(DBObject* self, PyObject* args)
2160{
2161 int err, flags;
2162
2163 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2164 return NULL;
2165 CHECK_DB_NOT_CLOSED(self);
2166
2167 MYDB_BEGIN_ALLOW_THREADS;
2168 err = self->db->set_flags(self->db, flags);
2169 MYDB_END_ALLOW_THREADS;
2170 RETURN_IF_ERR();
2171
2172 self->setflags |= flags;
2173 RETURN_NONE();
2174}
2175
2176
2177static PyObject*
2178DB_set_h_ffactor(DBObject* self, PyObject* args)
2179{
2180 int err, ffactor;
2181
2182 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2183 return NULL;
2184 CHECK_DB_NOT_CLOSED(self);
2185
2186 MYDB_BEGIN_ALLOW_THREADS;
2187 err = self->db->set_h_ffactor(self->db, ffactor);
2188 MYDB_END_ALLOW_THREADS;
2189 RETURN_IF_ERR();
2190 RETURN_NONE();
2191}
2192
2193
2194static PyObject*
2195DB_set_h_nelem(DBObject* self, PyObject* args)
2196{
2197 int err, nelem;
2198
2199 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2200 return NULL;
2201 CHECK_DB_NOT_CLOSED(self);
2202
2203 MYDB_BEGIN_ALLOW_THREADS;
2204 err = self->db->set_h_nelem(self->db, nelem);
2205 MYDB_END_ALLOW_THREADS;
2206 RETURN_IF_ERR();
2207 RETURN_NONE();
2208}
2209
2210
2211static PyObject*
2212DB_set_lorder(DBObject* self, PyObject* args)
2213{
2214 int err, lorder;
2215
2216 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2217 return NULL;
2218 CHECK_DB_NOT_CLOSED(self);
2219
2220 MYDB_BEGIN_ALLOW_THREADS;
2221 err = self->db->set_lorder(self->db, lorder);
2222 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2225}
2226
2227
2228static PyObject*
2229DB_set_pagesize(DBObject* self, PyObject* args)
2230{
2231 int err, pagesize;
2232
2233 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2234 return NULL;
2235 CHECK_DB_NOT_CLOSED(self);
2236
2237 MYDB_BEGIN_ALLOW_THREADS;
2238 err = self->db->set_pagesize(self->db, pagesize);
2239 MYDB_END_ALLOW_THREADS;
2240 RETURN_IF_ERR();
2241 RETURN_NONE();
2242}
2243
2244
2245static PyObject*
2246DB_set_re_delim(DBObject* self, PyObject* args)
2247{
2248 int err;
2249 char delim;
2250
2251 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2252 PyErr_Clear();
2253 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2254 return NULL;
2255 }
2256
2257 CHECK_DB_NOT_CLOSED(self);
2258
2259 MYDB_BEGIN_ALLOW_THREADS;
2260 err = self->db->set_re_delim(self->db, delim);
2261 MYDB_END_ALLOW_THREADS;
2262 RETURN_IF_ERR();
2263 RETURN_NONE();
2264}
2265
2266static PyObject*
2267DB_set_re_len(DBObject* self, PyObject* args)
2268{
2269 int err, len;
2270
2271 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2272 return NULL;
2273 CHECK_DB_NOT_CLOSED(self);
2274
2275 MYDB_BEGIN_ALLOW_THREADS;
2276 err = self->db->set_re_len(self->db, len);
2277 MYDB_END_ALLOW_THREADS;
2278 RETURN_IF_ERR();
2279 RETURN_NONE();
2280}
2281
2282
2283static PyObject*
2284DB_set_re_pad(DBObject* self, PyObject* args)
2285{
2286 int err;
2287 char pad;
2288
2289 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2290 PyErr_Clear();
2291 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2292 return NULL;
2293 }
2294 CHECK_DB_NOT_CLOSED(self);
2295
2296 MYDB_BEGIN_ALLOW_THREADS;
2297 err = self->db->set_re_pad(self->db, pad);
2298 MYDB_END_ALLOW_THREADS;
2299 RETURN_IF_ERR();
2300 RETURN_NONE();
2301}
2302
2303
2304static PyObject*
2305DB_set_re_source(DBObject* self, PyObject* args)
2306{
2307 int err;
2308 char *re_source;
2309
2310 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2311 return NULL;
2312 CHECK_DB_NOT_CLOSED(self);
2313
2314 MYDB_BEGIN_ALLOW_THREADS;
2315 err = self->db->set_re_source(self->db, re_source);
2316 MYDB_END_ALLOW_THREADS;
2317 RETURN_IF_ERR();
2318 RETURN_NONE();
2319}
2320
2321
2322#if (DBVER >= 32)
2323static PyObject*
2324DB_set_q_extentsize(DBObject* self, PyObject* args)
2325{
2326 int err;
2327 int extentsize;
2328
2329 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2330 return NULL;
2331 CHECK_DB_NOT_CLOSED(self);
2332
2333 MYDB_BEGIN_ALLOW_THREADS;
2334 err = self->db->set_q_extentsize(self->db, extentsize);
2335 MYDB_END_ALLOW_THREADS;
2336 RETURN_IF_ERR();
2337 RETURN_NONE();
2338}
2339#endif
2340
2341static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002342DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002343{
2344 int err, flags = 0, type;
2345 void* sp;
2346 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002347#if (DBVER >= 43)
2348 PyObject* txnobj = NULL;
2349 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002350 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002351#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002352 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002353#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002354
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002355#if (DBVER >= 43)
2356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2357 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002358 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002359 if (!checkTxnObj(txnobj, &txn))
2360 return NULL;
2361#else
2362 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2363 return NULL;
2364#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002365 CHECK_DB_NOT_CLOSED(self);
2366
2367 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002368#if (DBVER >= 43)
2369 err = self->db->stat(self->db, txn, &sp, flags);
2370#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002371 err = self->db->stat(self->db, &sp, flags);
2372#else
2373 err = self->db->stat(self->db, &sp, NULL, flags);
2374#endif
2375 MYDB_END_ALLOW_THREADS;
2376 RETURN_IF_ERR();
2377
2378 self->haveStat = 1;
2379
2380 /* Turn the stat structure into a dictionary */
2381 type = _DB_get_type(self);
2382 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2383 free(sp);
2384 return NULL;
2385 }
2386
2387#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2388#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2389#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2390
2391 switch (type) {
2392 case DB_HASH:
2393 MAKE_HASH_ENTRY(magic);
2394 MAKE_HASH_ENTRY(version);
2395 MAKE_HASH_ENTRY(nkeys);
2396 MAKE_HASH_ENTRY(ndata);
2397 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002398#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002399 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002400#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002401 MAKE_HASH_ENTRY(ffactor);
2402 MAKE_HASH_ENTRY(buckets);
2403 MAKE_HASH_ENTRY(free);
2404 MAKE_HASH_ENTRY(bfree);
2405 MAKE_HASH_ENTRY(bigpages);
2406 MAKE_HASH_ENTRY(big_bfree);
2407 MAKE_HASH_ENTRY(overflows);
2408 MAKE_HASH_ENTRY(ovfl_free);
2409 MAKE_HASH_ENTRY(dup);
2410 MAKE_HASH_ENTRY(dup_free);
2411 break;
2412
2413 case DB_BTREE:
2414 case DB_RECNO:
2415 MAKE_BT_ENTRY(magic);
2416 MAKE_BT_ENTRY(version);
2417 MAKE_BT_ENTRY(nkeys);
2418 MAKE_BT_ENTRY(ndata);
2419 MAKE_BT_ENTRY(pagesize);
2420 MAKE_BT_ENTRY(minkey);
2421 MAKE_BT_ENTRY(re_len);
2422 MAKE_BT_ENTRY(re_pad);
2423 MAKE_BT_ENTRY(levels);
2424 MAKE_BT_ENTRY(int_pg);
2425 MAKE_BT_ENTRY(leaf_pg);
2426 MAKE_BT_ENTRY(dup_pg);
2427 MAKE_BT_ENTRY(over_pg);
2428 MAKE_BT_ENTRY(free);
2429 MAKE_BT_ENTRY(int_pgfree);
2430 MAKE_BT_ENTRY(leaf_pgfree);
2431 MAKE_BT_ENTRY(dup_pgfree);
2432 MAKE_BT_ENTRY(over_pgfree);
2433 break;
2434
2435 case DB_QUEUE:
2436 MAKE_QUEUE_ENTRY(magic);
2437 MAKE_QUEUE_ENTRY(version);
2438 MAKE_QUEUE_ENTRY(nkeys);
2439 MAKE_QUEUE_ENTRY(ndata);
2440 MAKE_QUEUE_ENTRY(pagesize);
2441 MAKE_QUEUE_ENTRY(pages);
2442 MAKE_QUEUE_ENTRY(re_len);
2443 MAKE_QUEUE_ENTRY(re_pad);
2444 MAKE_QUEUE_ENTRY(pgfree);
2445#if (DBVER == 31)
2446 MAKE_QUEUE_ENTRY(start);
2447#endif
2448 MAKE_QUEUE_ENTRY(first_recno);
2449 MAKE_QUEUE_ENTRY(cur_recno);
2450 break;
2451
2452 default:
2453 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2454 Py_DECREF(d);
2455 d = NULL;
2456 }
2457
2458#undef MAKE_HASH_ENTRY
2459#undef MAKE_BT_ENTRY
2460#undef MAKE_QUEUE_ENTRY
2461
2462 free(sp);
2463 return d;
2464}
2465
2466static PyObject*
2467DB_sync(DBObject* self, PyObject* args)
2468{
2469 int err;
2470 int flags = 0;
2471
2472 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2473 return NULL;
2474 CHECK_DB_NOT_CLOSED(self);
2475
2476 MYDB_BEGIN_ALLOW_THREADS;
2477 err = self->db->sync(self->db, flags);
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480 RETURN_NONE();
2481}
2482
2483
2484#if (DBVER >= 33)
2485static PyObject*
2486DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2487{
2488 int err, flags=0;
2489 u_int32_t count=0;
2490 PyObject* txnobj = NULL;
2491 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002492 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002493
2494 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2495 &txnobj, &flags))
2496 return NULL;
2497 CHECK_DB_NOT_CLOSED(self);
2498 if (!checkTxnObj(txnobj, &txn))
2499 return NULL;
2500
2501 MYDB_BEGIN_ALLOW_THREADS;
2502 err = self->db->truncate(self->db, txn, &count, flags);
2503 MYDB_END_ALLOW_THREADS;
2504 RETURN_IF_ERR();
2505 return PyInt_FromLong(count);
2506}
2507#endif
2508
2509
2510static PyObject*
2511DB_upgrade(DBObject* self, PyObject* args)
2512{
2513 int err, flags=0;
2514 char *filename;
2515
2516 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2517 return NULL;
2518 CHECK_DB_NOT_CLOSED(self);
2519
2520 MYDB_BEGIN_ALLOW_THREADS;
2521 err = self->db->upgrade(self->db, filename, flags);
2522 MYDB_END_ALLOW_THREADS;
2523 RETURN_IF_ERR();
2524 RETURN_NONE();
2525}
2526
2527
2528static PyObject*
2529DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2530{
2531 int err, flags=0;
2532 char* fileName;
2533 char* dbName=NULL;
2534 char* outFileName=NULL;
2535 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002536 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002537 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002538
2539 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2540 &fileName, &dbName, &outFileName, &flags))
2541 return NULL;
2542
2543 CHECK_DB_NOT_CLOSED(self);
2544 if (outFileName)
2545 outFile = fopen(outFileName, "w");
2546
2547 MYDB_BEGIN_ALLOW_THREADS;
2548 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2549 MYDB_END_ALLOW_THREADS;
2550 if (outFileName)
2551 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002552
2553 /* DB.verify acts as a DB handle destructor (like close); this was
2554 * documented in BerkeleyDB 4.2 but had the undocumented effect
2555 * of not being safe in prior versions while still requiring an explicit
2556 * DB.close call afterwards. Lets call close for the user to emulate
2557 * the safe 4.2 behaviour. */
2558#if (DBVER <= 41)
2559 self->db->close(self->db, 0);
2560#endif
2561 self->db = NULL;
2562
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002563 RETURN_IF_ERR();
2564 RETURN_NONE();
2565}
2566
2567
2568static PyObject*
2569DB_set_get_returns_none(DBObject* self, PyObject* args)
2570{
2571 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002572 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573
2574 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2575 return NULL;
2576 CHECK_DB_NOT_CLOSED(self);
2577
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002578 if (self->moduleFlags.getReturnsNone)
2579 ++oldValue;
2580 if (self->moduleFlags.cursorSetReturnsNone)
2581 ++oldValue;
2582 self->moduleFlags.getReturnsNone = (flags >= 1);
2583 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002584 return PyInt_FromLong(oldValue);
2585}
2586
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002587#if (DBVER >= 41)
2588static PyObject*
2589DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2590{
2591 int err;
2592 u_int32_t flags=0;
2593 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002594 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002595
2596 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2597 &passwd, &flags)) {
2598 return NULL;
2599 }
2600
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->set_encrypt(self->db, passwd, flags);
2603 MYDB_END_ALLOW_THREADS;
2604
2605 RETURN_IF_ERR();
2606 RETURN_NONE();
2607}
2608#endif /* DBVER >= 41 */
2609
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002610
2611/*-------------------------------------------------------------- */
2612/* Mapping and Dictionary-like access routines */
2613
Martin v. Löwis18e16552006-02-15 17:27:45 +00002614Py_ssize_t DB_length(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002615{
2616 int err;
2617 long size = 0;
2618 int flags = 0;
2619 void* sp;
2620
2621 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002622 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2623 PyErr_SetObject(DBError, t);
2624 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002625 return -1;
2626 }
2627
2628 if (self->haveStat) { /* Has the stat function been called recently? If
2629 so, we can use the cached value. */
2630 flags = DB_CACHED_COUNTS;
2631 }
2632
2633 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002634#if (DBVER >= 43)
2635 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2636#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002637 err = self->db->stat(self->db, &sp, flags);
2638#else
2639 err = self->db->stat(self->db, &sp, NULL, flags);
2640#endif
2641 MYDB_END_ALLOW_THREADS;
2642
2643 if (err)
2644 return -1;
2645
2646 self->haveStat = 1;
2647
2648 /* All the stat structures have matching fields upto the ndata field,
2649 so we can use any of them for the type cast */
2650 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2651 free(sp);
2652 return size;
2653}
2654
2655
2656PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2657{
2658 int err;
2659 PyObject* retval;
2660 DBT key;
2661 DBT data;
2662
2663 CHECK_DB_NOT_CLOSED(self);
2664 if (!make_key_dbt(self, keyobj, &key, NULL))
2665 return NULL;
2666
2667 CLEAR_DBT(data);
2668 if (CHECK_DBFLAG(self, DB_THREAD)) {
2669 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2670 data.flags = DB_DBT_MALLOC;
2671 }
2672 MYDB_BEGIN_ALLOW_THREADS;
2673 err = self->db->get(self->db, NULL, &key, &data, 0);
2674 MYDB_END_ALLOW_THREADS;
2675 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2676 PyErr_SetObject(PyExc_KeyError, keyobj);
2677 retval = NULL;
2678 }
2679 else if (makeDBError(err)) {
2680 retval = NULL;
2681 }
2682 else {
2683 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2684 FREE_DBT(data);
2685 }
2686
2687 FREE_DBT(key);
2688 return retval;
2689}
2690
2691
2692static int
2693DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2694{
2695 DBT key, data;
2696 int retval;
2697 int flags = 0;
2698
2699 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002700 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2701 PyErr_SetObject(DBError, t);
2702 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703 return -1;
2704 }
2705
2706 if (!make_key_dbt(self, keyobj, &key, NULL))
2707 return -1;
2708
2709 if (dataobj != NULL) {
2710 if (!make_dbt(dataobj, &data))
2711 retval = -1;
2712 else {
2713 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002714 /* dictionaries shouldn't have duplicate keys */
2715 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716 retval = _DB_put(self, NULL, &key, &data, flags);
2717
2718 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002719 /* try deleting any old record that matches and then PUT it
2720 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721 _DB_delete(self, NULL, &key, 0);
2722 PyErr_Clear();
2723 retval = _DB_put(self, NULL, &key, &data, flags);
2724 }
2725 }
2726 }
2727 else {
2728 /* dataobj == NULL, so delete the key */
2729 retval = _DB_delete(self, NULL, &key, 0);
2730 }
2731 FREE_DBT(key);
2732 return retval;
2733}
2734
2735
2736static PyObject*
2737DB_has_key(DBObject* self, PyObject* args)
2738{
2739 int err;
2740 PyObject* keyobj;
2741 DBT key, data;
2742 PyObject* txnobj = NULL;
2743 DB_TXN *txn = NULL;
2744
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002745 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746 return NULL;
2747 CHECK_DB_NOT_CLOSED(self);
2748 if (!make_key_dbt(self, keyobj, &key, NULL))
2749 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002750 if (!checkTxnObj(txnobj, &txn)) {
2751 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002752 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002753 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002755 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002756 it has a record but can't allocate a buffer for the data. This saves
2757 having to deal with data we won't be using.
2758 */
2759 CLEAR_DBT(data);
2760 data.flags = DB_DBT_USERMEM;
2761
2762 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002763 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002764 MYDB_END_ALLOW_THREADS;
2765 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002766
2767 if (err == DB_BUFFER_SMALL || err == 0) {
2768 return PyInt_FromLong(1);
2769 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2770 return PyInt_FromLong(0);
2771 }
2772
2773 makeDBError(err);
2774 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002775}
2776
2777
2778#define _KEYS_LIST 1
2779#define _VALUES_LIST 2
2780#define _ITEMS_LIST 3
2781
2782static PyObject*
2783_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2784{
2785 int err, dbtype;
2786 DBT key;
2787 DBT data;
2788 DBC *cursor;
2789 PyObject* list;
2790 PyObject* item = NULL;
2791
2792 CHECK_DB_NOT_CLOSED(self);
2793 CLEAR_DBT(key);
2794 CLEAR_DBT(data);
2795
2796 dbtype = _DB_get_type(self);
2797 if (dbtype == -1)
2798 return NULL;
2799
2800 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002801 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803
2804 /* get a cursor */
2805 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002806 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002807 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002808 if (makeDBError(err)) {
2809 Py_DECREF(list);
2810 return NULL;
2811 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002812
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;
Thomas Woutersb3153832006-03-08 01:47:19 +00002862 default:
2863 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2864 item = NULL;
2865 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 }
2867 if (item == NULL) {
2868 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 list = NULL;
2870 goto done;
2871 }
2872 PyList_Append(list, item);
2873 Py_DECREF(item);
2874 }
2875
Gregory P. Smithe9477062005-06-04 06:46:59 +00002876 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2877 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002878 Py_DECREF(list);
2879 list = NULL;
2880 }
2881
2882 done:
2883 FREE_DBT(key);
2884 FREE_DBT(data);
2885 MYDB_BEGIN_ALLOW_THREADS;
2886 cursor->c_close(cursor);
2887 MYDB_END_ALLOW_THREADS;
2888 return list;
2889}
2890
2891
2892static PyObject*
2893DB_keys(DBObject* self, PyObject* args)
2894{
2895 PyObject* txnobj = NULL;
2896 DB_TXN *txn = NULL;
2897
Georg Brandl96a8c392006-05-29 21:04:52 +00002898 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002899 return NULL;
2900 if (!checkTxnObj(txnobj, &txn))
2901 return NULL;
2902 return _DB_make_list(self, txn, _KEYS_LIST);
2903}
2904
2905
2906static PyObject*
2907DB_items(DBObject* self, PyObject* args)
2908{
2909 PyObject* txnobj = NULL;
2910 DB_TXN *txn = NULL;
2911
Georg Brandl96a8c392006-05-29 21:04:52 +00002912 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 return NULL;
2914 if (!checkTxnObj(txnobj, &txn))
2915 return NULL;
2916 return _DB_make_list(self, txn, _ITEMS_LIST);
2917}
2918
2919
2920static PyObject*
2921DB_values(DBObject* self, PyObject* args)
2922{
2923 PyObject* txnobj = NULL;
2924 DB_TXN *txn = NULL;
2925
Georg Brandl96a8c392006-05-29 21:04:52 +00002926 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927 return NULL;
2928 if (!checkTxnObj(txnobj, &txn))
2929 return NULL;
2930 return _DB_make_list(self, txn, _VALUES_LIST);
2931}
2932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002933/* --------------------------------------------------------------------- */
2934/* DBCursor methods */
2935
2936
2937static PyObject*
2938DBC_close(DBCursorObject* self, PyObject* args)
2939{
2940 int err = 0;
2941
2942 if (!PyArg_ParseTuple(args, ":close"))
2943 return NULL;
2944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002945 if (self->dbc != NULL) {
2946 MYDB_BEGIN_ALLOW_THREADS;
2947 err = self->dbc->c_close(self->dbc);
2948 self->dbc = NULL;
2949 MYDB_END_ALLOW_THREADS;
2950 }
2951 RETURN_IF_ERR();
2952 RETURN_NONE();
2953}
2954
2955
2956static PyObject*
2957DBC_count(DBCursorObject* self, PyObject* args)
2958{
2959 int err = 0;
2960 db_recno_t count;
2961 int flags = 0;
2962
2963 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2964 return NULL;
2965
2966 CHECK_CURSOR_NOT_CLOSED(self);
2967
2968 MYDB_BEGIN_ALLOW_THREADS;
2969 err = self->dbc->c_count(self->dbc, &count, flags);
2970 MYDB_END_ALLOW_THREADS;
2971 RETURN_IF_ERR();
2972
2973 return PyInt_FromLong(count);
2974}
2975
2976
2977static PyObject*
2978DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2979{
2980 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2981}
2982
2983
2984static PyObject*
2985DBC_delete(DBCursorObject* self, PyObject* args)
2986{
2987 int err, flags=0;
2988
2989 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2990 return NULL;
2991
2992 CHECK_CURSOR_NOT_CLOSED(self);
2993
2994 MYDB_BEGIN_ALLOW_THREADS;
2995 err = self->dbc->c_del(self->dbc, flags);
2996 MYDB_END_ALLOW_THREADS;
2997 RETURN_IF_ERR();
2998
2999 self->mydb->haveStat = 0;
3000 RETURN_NONE();
3001}
3002
3003
3004static PyObject*
3005DBC_dup(DBCursorObject* self, PyObject* args)
3006{
3007 int err, flags =0;
3008 DBC* dbc = NULL;
3009
3010 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3011 return NULL;
3012
3013 CHECK_CURSOR_NOT_CLOSED(self);
3014
3015 MYDB_BEGIN_ALLOW_THREADS;
3016 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3017 MYDB_END_ALLOW_THREADS;
3018 RETURN_IF_ERR();
3019
3020 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3021}
3022
3023static PyObject*
3024DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3025{
3026 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3027}
3028
3029
3030static PyObject*
3031DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3032{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003033 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034 PyObject* keyobj = NULL;
3035 PyObject* dataobj = NULL;
3036 PyObject* retval = NULL;
3037 int dlen = -1;
3038 int doff = -1;
3039 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003040 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003041 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003042
3043 CLEAR_DBT(key);
3044 CLEAR_DBT(data);
3045 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003046 &flags, &dlen, &doff))
3047 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003048 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003049 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3050 &kwnames[1],
3051 &keyobj, &flags, &dlen, &doff))
3052 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003054 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3055 kwnames, &keyobj, &dataobj,
3056 &flags, &dlen, &doff))
3057 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003058 return NULL;
3059 }
3060 }
3061 }
3062
3063 CHECK_CURSOR_NOT_CLOSED(self);
3064
3065 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3066 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003067 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3068 (!add_partial_dbt(&data, dlen, doff)) )
3069 {
3070 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003072 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003073
3074 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3075 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003076 if (!(key.flags & DB_DBT_REALLOC)) {
3077 key.flags |= DB_DBT_MALLOC;
3078 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 }
3080
3081 MYDB_BEGIN_ALLOW_THREADS;
3082 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3083 MYDB_END_ALLOW_THREADS;
3084
Gregory P. Smithe9477062005-06-04 06:46:59 +00003085 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3086 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003087 Py_INCREF(Py_None);
3088 retval = Py_None;
3089 }
3090 else if (makeDBError(err)) {
3091 retval = NULL;
3092 }
3093 else {
3094 switch (_DB_get_type(self->mydb)) {
3095 case -1:
3096 retval = NULL;
3097 break;
3098 case DB_BTREE:
3099 case DB_HASH:
3100 default:
3101 retval = Py_BuildValue("s#s#", key.data, key.size,
3102 data.data, data.size);
3103 break;
3104 case DB_RECNO:
3105 case DB_QUEUE:
3106 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3107 data.data, data.size);
3108 break;
3109 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003110 FREE_DBT(data);
3111 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003112 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003113 return retval;
3114}
3115
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003116#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003117static PyObject*
3118DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3119{
3120 int err, flags=0;
3121 PyObject* keyobj = NULL;
3122 PyObject* dataobj = NULL;
3123 PyObject* retval = NULL;
3124 int dlen = -1;
3125 int doff = -1;
3126 DBT key, pkey, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003127 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003128 NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003129
3130 CLEAR_DBT(key);
3131 CLEAR_DBT(data);
3132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3133 &flags, &dlen, &doff))
3134 {
3135 PyErr_Clear();
3136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3137 &kwnames[1],
3138 &keyobj, &flags, &dlen, &doff))
3139 {
3140 PyErr_Clear();
3141 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3142 kwnames, &keyobj, &dataobj,
3143 &flags, &dlen, &doff))
3144 {
3145 return NULL;
3146 }
3147 }
3148 }
3149
3150 CHECK_CURSOR_NOT_CLOSED(self);
3151
3152 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3153 return NULL;
3154 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3155 (!add_partial_dbt(&data, dlen, doff)) ) {
3156 FREE_DBT(key);
3157 return NULL;
3158 }
3159
3160 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3161 data.flags = DB_DBT_MALLOC;
3162 if (!(key.flags & DB_DBT_REALLOC)) {
3163 key.flags |= DB_DBT_MALLOC;
3164 }
3165 }
3166
3167 CLEAR_DBT(pkey);
3168 pkey.flags = DB_DBT_MALLOC;
3169
3170 MYDB_BEGIN_ALLOW_THREADS;
3171 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3172 MYDB_END_ALLOW_THREADS;
3173
Gregory P. Smithe9477062005-06-04 06:46:59 +00003174 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3175 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003176 Py_INCREF(Py_None);
3177 retval = Py_None;
3178 }
3179 else if (makeDBError(err)) {
3180 retval = NULL;
3181 }
3182 else {
3183 PyObject *pkeyObj;
3184 PyObject *dataObj;
3185 dataObj = PyString_FromStringAndSize(data.data, data.size);
3186
3187 if (self->mydb->primaryDBType == DB_RECNO ||
3188 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003189 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003190 else
3191 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3192
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003193 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003194 {
3195 PyObject *keyObj;
3196 int type = _DB_get_type(self->mydb);
3197 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003198 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199 else
3200 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003201#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003202 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003203#else
3204 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3205#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003206 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003207 FREE_DBT(key);
3208 }
3209 else /* return just the pkey and data */
3210 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003211#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003212 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003213#else
3214 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3215#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003216 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003217 Py_DECREF(dataObj);
3218 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003219 FREE_DBT(pkey);
3220 FREE_DBT(data);
3221 }
3222 /* the only time REALLOC should be set is if we used an integer
3223 * key that make_key_dbt malloc'd for us. always free these. */
3224 if (key.flags & DB_DBT_REALLOC) {
3225 FREE_DBT(key);
3226 }
3227 return retval;
3228}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003229#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003231
3232static PyObject*
3233DBC_get_recno(DBCursorObject* self, PyObject* args)
3234{
3235 int err;
3236 db_recno_t recno;
3237 DBT key;
3238 DBT data;
3239
3240 if (!PyArg_ParseTuple(args, ":get_recno"))
3241 return NULL;
3242
3243 CHECK_CURSOR_NOT_CLOSED(self);
3244
3245 CLEAR_DBT(key);
3246 CLEAR_DBT(data);
3247 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3248 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3249 data.flags = DB_DBT_MALLOC;
3250 key.flags = DB_DBT_MALLOC;
3251 }
3252
3253 MYDB_BEGIN_ALLOW_THREADS;
3254 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3255 MYDB_END_ALLOW_THREADS;
3256 RETURN_IF_ERR();
3257
3258 recno = *((db_recno_t*)data.data);
3259 FREE_DBT(key);
3260 FREE_DBT(data);
3261 return PyInt_FromLong(recno);
3262}
3263
3264
3265static PyObject*
3266DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3267{
3268 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3269}
3270
3271
3272static PyObject*
3273DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3274{
3275 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3276}
3277
3278
3279static PyObject*
3280DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3281{
3282 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3283}
3284
3285
3286static PyObject*
3287DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3288{
3289 int err, flags = 0;
3290 PyObject* keyobj, *dataobj;
3291 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003292 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003293 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003294 int dlen = -1;
3295 int doff = -1;
3296
3297 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3298 &keyobj, &dataobj, &flags, &dlen, &doff))
3299 return NULL;
3300
3301 CHECK_CURSOR_NOT_CLOSED(self);
3302
3303 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3304 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003305 if (!make_dbt(dataobj, &data) ||
3306 !add_partial_dbt(&data, dlen, doff) )
3307 {
3308 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003309 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003310 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003311
3312 MYDB_BEGIN_ALLOW_THREADS;
3313 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3314 MYDB_END_ALLOW_THREADS;
3315 FREE_DBT(key);
3316 RETURN_IF_ERR();
3317 self->mydb->haveStat = 0;
3318 RETURN_NONE();
3319}
3320
3321
3322static PyObject*
3323DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3324{
3325 int err, flags = 0;
3326 DBT key, data;
3327 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003328 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003329 int dlen = -1;
3330 int doff = -1;
3331
3332 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3333 &keyobj, &flags, &dlen, &doff))
3334 return NULL;
3335
3336 CHECK_CURSOR_NOT_CLOSED(self);
3337
3338 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3339 return NULL;
3340
3341 CLEAR_DBT(data);
3342 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3343 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3344 data.flags = DB_DBT_MALLOC;
3345 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003346 if (!add_partial_dbt(&data, dlen, doff)) {
3347 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003349 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003350
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3353 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003354 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3355 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003356 Py_INCREF(Py_None);
3357 retval = Py_None;
3358 }
3359 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360 retval = NULL;
3361 }
3362 else {
3363 switch (_DB_get_type(self->mydb)) {
3364 case -1:
3365 retval = NULL;
3366 break;
3367 case DB_BTREE:
3368 case DB_HASH:
3369 default:
3370 retval = Py_BuildValue("s#s#", key.data, key.size,
3371 data.data, data.size);
3372 break;
3373 case DB_RECNO:
3374 case DB_QUEUE:
3375 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3376 data.data, data.size);
3377 break;
3378 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003380 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003381 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003382 /* the only time REALLOC should be set is if we used an integer
3383 * key that make_key_dbt malloc'd for us. always free these. */
3384 if (key.flags & DB_DBT_REALLOC) {
3385 FREE_DBT(key);
3386 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003387
3388 return retval;
3389}
3390
3391
3392static PyObject*
3393DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3394{
3395 int err, flags = 0;
3396 DBT key, data;
3397 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003398 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003399 int dlen = -1;
3400 int doff = -1;
3401
3402 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3403 &keyobj, &flags, &dlen, &doff))
3404 return NULL;
3405
3406 CHECK_CURSOR_NOT_CLOSED(self);
3407
3408 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3409 return NULL;
3410
3411 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003412 if (!add_partial_dbt(&data, dlen, doff)) {
3413 FREE_DBT(key);
3414 return NULL;
3415 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003416 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3417 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003418 data.flags |= DB_DBT_MALLOC;
3419 /* only BTREE databases will return anything in the key */
3420 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3421 key.flags |= DB_DBT_MALLOC;
3422 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003423 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003424 MYDB_BEGIN_ALLOW_THREADS;
3425 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3426 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003427 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3428 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003429 Py_INCREF(Py_None);
3430 retval = Py_None;
3431 }
3432 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433 retval = NULL;
3434 }
3435 else {
3436 switch (_DB_get_type(self->mydb)) {
3437 case -1:
3438 retval = NULL;
3439 break;
3440 case DB_BTREE:
3441 case DB_HASH:
3442 default:
3443 retval = Py_BuildValue("s#s#", key.data, key.size,
3444 data.data, data.size);
3445 break;
3446 case DB_RECNO:
3447 case DB_QUEUE:
3448 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3449 data.data, data.size);
3450 break;
3451 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003452 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003453 FREE_DBT(data);
3454 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003455 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003456 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003457 if (key.flags & DB_DBT_REALLOC) {
3458 FREE_DBT(key);
3459 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461 return retval;
3462}
3463
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003465_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3466 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003468 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003470 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471
Gregory P. Smith7441e652003-11-03 21:35:31 +00003472 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3474 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003475 if (!make_dbt(dataobj, &data)) {
3476 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003478 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479
3480 MYDB_BEGIN_ALLOW_THREADS;
3481 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3482 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003483 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003484 Py_INCREF(Py_None);
3485 retval = Py_None;
3486 }
3487 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003488 retval = NULL;
3489 }
3490 else {
3491 switch (_DB_get_type(self->mydb)) {
3492 case -1:
3493 retval = NULL;
3494 break;
3495 case DB_BTREE:
3496 case DB_HASH:
3497 default:
3498 retval = Py_BuildValue("s#s#", key.data, key.size,
3499 data.data, data.size);
3500 break;
3501 case DB_RECNO:
3502 case DB_QUEUE:
3503 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3504 data.data, data.size);
3505 break;
3506 }
3507 }
3508
3509 FREE_DBT(key);
3510 return retval;
3511}
3512
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003513static PyObject*
3514DBC_get_both(DBCursorObject* self, PyObject* args)
3515{
3516 int flags=0;
3517 PyObject *keyobj, *dataobj;
3518
3519 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3520 return NULL;
3521
Gregory P. Smith7441e652003-11-03 21:35:31 +00003522 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003523 CHECK_CURSOR_NOT_CLOSED(self);
3524
3525 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3526 self->mydb->moduleFlags.getReturnsNone);
3527}
3528
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003529/* Return size of entry */
3530static PyObject*
3531DBC_get_current_size(DBCursorObject* self, PyObject* args)
3532{
3533 int err, flags=DB_CURRENT;
3534 PyObject* retval = NULL;
3535 DBT key, data;
3536
3537 if (!PyArg_ParseTuple(args, ":get_current_size"))
3538 return NULL;
3539 CHECK_CURSOR_NOT_CLOSED(self);
3540 CLEAR_DBT(key);
3541 CLEAR_DBT(data);
3542
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003543 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003544 getting the record size. */
3545 data.flags = DB_DBT_USERMEM;
3546 data.ulen = 0;
3547 MYDB_BEGIN_ALLOW_THREADS;
3548 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3549 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003550 if (err == DB_BUFFER_SMALL || !err) {
3551 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003552 retval = PyInt_FromLong((long)data.size);
3553 err = 0;
3554 }
3555
3556 FREE_DBT(key);
3557 FREE_DBT(data);
3558 RETURN_IF_ERR();
3559 return retval;
3560}
3561
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003562static PyObject*
3563DBC_set_both(DBCursorObject* self, PyObject* args)
3564{
3565 int flags=0;
3566 PyObject *keyobj, *dataobj;
3567
3568 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3569 return NULL;
3570
Gregory P. Smith7441e652003-11-03 21:35:31 +00003571 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003572 CHECK_CURSOR_NOT_CLOSED(self);
3573
3574 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3575 self->mydb->moduleFlags.cursorSetReturnsNone);
3576}
3577
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578
3579static PyObject*
3580DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3581{
3582 int err, irecno, flags=0;
3583 db_recno_t recno;
3584 DBT key, data;
3585 PyObject* retval;
3586 int dlen = -1;
3587 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003588 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589
3590 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3591 &irecno, &flags, &dlen, &doff))
3592 return NULL;
3593
3594 CHECK_CURSOR_NOT_CLOSED(self);
3595
3596 CLEAR_DBT(key);
3597 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003598 /* use allocated space so DB will be able to realloc room for the real
3599 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600 key.data = malloc(sizeof(db_recno_t));
3601 if (key.data == NULL) {
3602 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3603 return NULL;
3604 }
3605 key.size = sizeof(db_recno_t);
3606 key.ulen = key.size;
3607 memcpy(key.data, &recno, sizeof(db_recno_t));
3608 key.flags = DB_DBT_REALLOC;
3609
3610 CLEAR_DBT(data);
3611 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3612 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3613 data.flags = DB_DBT_MALLOC;
3614 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003615 if (!add_partial_dbt(&data, dlen, doff)) {
3616 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003617 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003618 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619
3620 MYDB_BEGIN_ALLOW_THREADS;
3621 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3622 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3624 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003625 Py_INCREF(Py_None);
3626 retval = Py_None;
3627 }
3628 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003629 retval = NULL;
3630 }
3631 else { /* Can only be used for BTrees, so no need to return int key */
3632 retval = Py_BuildValue("s#s#", key.data, key.size,
3633 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003634 FREE_DBT(data);
3635 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003636 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003637
3638 return retval;
3639}
3640
3641
3642static PyObject*
3643DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3644{
3645 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3646}
3647
3648
3649static PyObject*
3650DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3651{
3652 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3653}
3654
3655
3656static PyObject*
3657DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3658{
3659 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3660}
3661
3662
3663static PyObject*
3664DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3665{
3666 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3667}
3668
3669
3670static PyObject*
3671DBC_join_item(DBCursorObject* self, PyObject* args)
3672{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003673 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003674 DBT key, data;
3675 PyObject* retval;
3676
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003677 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003678 return NULL;
3679
3680 CHECK_CURSOR_NOT_CLOSED(self);
3681
3682 CLEAR_DBT(key);
3683 CLEAR_DBT(data);
3684 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3685 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3686 key.flags = DB_DBT_MALLOC;
3687 }
3688
3689 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003690 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003691 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003692 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3693 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003694 Py_INCREF(Py_None);
3695 retval = Py_None;
3696 }
3697 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003698 retval = NULL;
3699 }
3700 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003701 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702 FREE_DBT(key);
3703 }
3704
3705 return retval;
3706}
3707
3708
3709
3710/* --------------------------------------------------------------------- */
3711/* DBEnv methods */
3712
3713
3714static PyObject*
3715DBEnv_close(DBEnvObject* self, PyObject* args)
3716{
3717 int err, flags = 0;
3718
3719 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3720 return NULL;
3721 if (!self->closed) { /* Don't close more than once */
3722 MYDB_BEGIN_ALLOW_THREADS;
3723 err = self->db_env->close(self->db_env, flags);
3724 MYDB_END_ALLOW_THREADS;
3725 /* after calling DBEnv->close, regardless of error, this DBEnv
3726 * may not be accessed again (BerkeleyDB docs). */
3727 self->closed = 1;
3728 self->db_env = NULL;
3729 RETURN_IF_ERR();
3730 }
3731 RETURN_NONE();
3732}
3733
3734
3735static PyObject*
3736DBEnv_open(DBEnvObject* self, PyObject* args)
3737{
3738 int err, flags=0, mode=0660;
3739 char *db_home;
3740
3741 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3742 return NULL;
3743
3744 CHECK_ENV_NOT_CLOSED(self);
3745
3746 MYDB_BEGIN_ALLOW_THREADS;
3747 err = self->db_env->open(self->db_env, db_home, flags, mode);
3748 MYDB_END_ALLOW_THREADS;
3749 RETURN_IF_ERR();
3750 self->closed = 0;
3751 self->flags = flags;
3752 RETURN_NONE();
3753}
3754
3755
3756static PyObject*
3757DBEnv_remove(DBEnvObject* self, PyObject* args)
3758{
3759 int err, flags=0;
3760 char *db_home;
3761
3762 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3763 return NULL;
3764 CHECK_ENV_NOT_CLOSED(self);
3765 MYDB_BEGIN_ALLOW_THREADS;
3766 err = self->db_env->remove(self->db_env, db_home, flags);
3767 MYDB_END_ALLOW_THREADS;
3768 RETURN_IF_ERR();
3769 RETURN_NONE();
3770}
3771
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003772#if (DBVER >= 41)
3773static PyObject*
3774DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3775{
3776 int err;
3777 u_int32_t flags=0;
3778 char *file = NULL;
3779 char *database = NULL;
3780 PyObject *txnobj = NULL;
3781 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003782 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003783 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003784
3785 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3786 &file, &database, &txnobj, &flags)) {
3787 return NULL;
3788 }
3789 if (!checkTxnObj(txnobj, &txn)) {
3790 return NULL;
3791 }
3792 CHECK_ENV_NOT_CLOSED(self);
3793 MYDB_BEGIN_ALLOW_THREADS;
3794 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3795 MYDB_END_ALLOW_THREADS;
3796 RETURN_IF_ERR();
3797 RETURN_NONE();
3798}
3799
3800static PyObject*
3801DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3802{
3803 int err;
3804 u_int32_t flags=0;
3805 char *file = NULL;
3806 char *database = NULL;
3807 char *newname = NULL;
3808 PyObject *txnobj = NULL;
3809 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003810 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003811 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003812
3813 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3814 &file, &database, &newname, &txnobj, &flags)) {
3815 return NULL;
3816 }
3817 if (!checkTxnObj(txnobj, &txn)) {
3818 return NULL;
3819 }
3820 CHECK_ENV_NOT_CLOSED(self);
3821 MYDB_BEGIN_ALLOW_THREADS;
3822 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3823 flags);
3824 MYDB_END_ALLOW_THREADS;
3825 RETURN_IF_ERR();
3826 RETURN_NONE();
3827}
3828
3829static PyObject*
3830DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3831{
3832 int err;
3833 u_int32_t flags=0;
3834 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003835 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003836
3837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3838 &passwd, &flags)) {
3839 return NULL;
3840 }
3841
3842 MYDB_BEGIN_ALLOW_THREADS;
3843 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3844 MYDB_END_ALLOW_THREADS;
3845
3846 RETURN_IF_ERR();
3847 RETURN_NONE();
3848}
3849#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003850
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003851#if (DBVER >= 40)
3852static PyObject*
3853DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3854{
3855 int err;
3856 u_int32_t flags=0;
3857 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003858 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003859
3860 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3861 &timeout, &flags)) {
3862 return NULL;
3863 }
3864
3865 MYDB_BEGIN_ALLOW_THREADS;
3866 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3867 MYDB_END_ALLOW_THREADS;
3868
3869 RETURN_IF_ERR();
3870 RETURN_NONE();
3871}
3872#endif /* DBVER >= 40 */
3873
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003874static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003875DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3876{
3877 int err;
3878 long shm_key = 0;
3879
3880 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3881 return NULL;
3882 CHECK_ENV_NOT_CLOSED(self);
3883
3884 err = self->db_env->set_shm_key(self->db_env, shm_key);
3885 RETURN_IF_ERR();
3886 RETURN_NONE();
3887}
3888
3889static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003890DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3891{
3892 int err, gbytes=0, bytes=0, ncache=0;
3893
3894 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3895 &gbytes, &bytes, &ncache))
3896 return NULL;
3897 CHECK_ENV_NOT_CLOSED(self);
3898
3899 MYDB_BEGIN_ALLOW_THREADS;
3900 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3901 MYDB_END_ALLOW_THREADS;
3902 RETURN_IF_ERR();
3903 RETURN_NONE();
3904}
3905
3906
3907#if (DBVER >= 32)
3908static PyObject*
3909DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3910{
3911 int err, flags=0, onoff=0;
3912
3913 if (!PyArg_ParseTuple(args, "ii:set_flags",
3914 &flags, &onoff))
3915 return NULL;
3916 CHECK_ENV_NOT_CLOSED(self);
3917
3918 MYDB_BEGIN_ALLOW_THREADS;
3919 err = self->db_env->set_flags(self->db_env, flags, onoff);
3920 MYDB_END_ALLOW_THREADS;
3921 RETURN_IF_ERR();
3922 RETURN_NONE();
3923}
3924#endif
3925
3926
3927static PyObject*
3928DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3929{
3930 int err;
3931 char *dir;
3932
3933 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3934 return NULL;
3935 CHECK_ENV_NOT_CLOSED(self);
3936
3937 MYDB_BEGIN_ALLOW_THREADS;
3938 err = self->db_env->set_data_dir(self->db_env, dir);
3939 MYDB_END_ALLOW_THREADS;
3940 RETURN_IF_ERR();
3941 RETURN_NONE();
3942}
3943
3944
3945static PyObject*
3946DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3947{
3948 int err, lg_bsize;
3949
3950 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3951 return NULL;
3952 CHECK_ENV_NOT_CLOSED(self);
3953
3954 MYDB_BEGIN_ALLOW_THREADS;
3955 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3956 MYDB_END_ALLOW_THREADS;
3957 RETURN_IF_ERR();
3958 RETURN_NONE();
3959}
3960
3961
3962static PyObject*
3963DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3964{
3965 int err;
3966 char *dir;
3967
3968 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3969 return NULL;
3970 CHECK_ENV_NOT_CLOSED(self);
3971
3972 MYDB_BEGIN_ALLOW_THREADS;
3973 err = self->db_env->set_lg_dir(self->db_env, dir);
3974 MYDB_END_ALLOW_THREADS;
3975 RETURN_IF_ERR();
3976 RETURN_NONE();
3977}
3978
3979static PyObject*
3980DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3981{
3982 int err, lg_max;
3983
3984 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3985 return NULL;
3986 CHECK_ENV_NOT_CLOSED(self);
3987
3988 MYDB_BEGIN_ALLOW_THREADS;
3989 err = self->db_env->set_lg_max(self->db_env, lg_max);
3990 MYDB_END_ALLOW_THREADS;
3991 RETURN_IF_ERR();
3992 RETURN_NONE();
3993}
3994
3995
Neal Norwitz84562352005-10-20 04:30:15 +00003996#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003997static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003998DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3999{
4000 int err, lg_max;
4001
4002 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4003 return NULL;
4004 CHECK_ENV_NOT_CLOSED(self);
4005
4006 MYDB_BEGIN_ALLOW_THREADS;
4007 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4008 MYDB_END_ALLOW_THREADS;
4009 RETURN_IF_ERR();
4010 RETURN_NONE();
4011}
Neal Norwitz84562352005-10-20 04:30:15 +00004012#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004013
4014
4015static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004016DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4017{
4018 int err, lk_detect;
4019
4020 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4021 return NULL;
4022 CHECK_ENV_NOT_CLOSED(self);
4023
4024 MYDB_BEGIN_ALLOW_THREADS;
4025 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4026 MYDB_END_ALLOW_THREADS;
4027 RETURN_IF_ERR();
4028 RETURN_NONE();
4029}
4030
4031
4032static PyObject*
4033DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4034{
4035 int err, max;
4036
4037 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4038 return NULL;
4039 CHECK_ENV_NOT_CLOSED(self);
4040
4041 MYDB_BEGIN_ALLOW_THREADS;
4042 err = self->db_env->set_lk_max(self->db_env, max);
4043 MYDB_END_ALLOW_THREADS;
4044 RETURN_IF_ERR();
4045 RETURN_NONE();
4046}
4047
4048
4049#if (DBVER >= 32)
4050
4051static PyObject*
4052DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4053{
4054 int err, max;
4055
4056 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4057 return NULL;
4058 CHECK_ENV_NOT_CLOSED(self);
4059
4060 MYDB_BEGIN_ALLOW_THREADS;
4061 err = self->db_env->set_lk_max_locks(self->db_env, max);
4062 MYDB_END_ALLOW_THREADS;
4063 RETURN_IF_ERR();
4064 RETURN_NONE();
4065}
4066
4067
4068static PyObject*
4069DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4070{
4071 int err, max;
4072
4073 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4074 return NULL;
4075 CHECK_ENV_NOT_CLOSED(self);
4076
4077 MYDB_BEGIN_ALLOW_THREADS;
4078 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4079 MYDB_END_ALLOW_THREADS;
4080 RETURN_IF_ERR();
4081 RETURN_NONE();
4082}
4083
4084
4085static PyObject*
4086DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4087{
4088 int err, max;
4089
4090 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4091 return NULL;
4092 CHECK_ENV_NOT_CLOSED(self);
4093
4094 MYDB_BEGIN_ALLOW_THREADS;
4095 err = self->db_env->set_lk_max_objects(self->db_env, max);
4096 MYDB_END_ALLOW_THREADS;
4097 RETURN_IF_ERR();
4098 RETURN_NONE();
4099}
4100
4101#endif
4102
4103
4104static PyObject*
4105DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4106{
4107 int err, mp_mmapsize;
4108
4109 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4110 return NULL;
4111 CHECK_ENV_NOT_CLOSED(self);
4112
4113 MYDB_BEGIN_ALLOW_THREADS;
4114 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4115 MYDB_END_ALLOW_THREADS;
4116 RETURN_IF_ERR();
4117 RETURN_NONE();
4118}
4119
4120
4121static PyObject*
4122DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4123{
4124 int err;
4125 char *dir;
4126
4127 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4128 return NULL;
4129 CHECK_ENV_NOT_CLOSED(self);
4130
4131 MYDB_BEGIN_ALLOW_THREADS;
4132 err = self->db_env->set_tmp_dir(self->db_env, dir);
4133 MYDB_END_ALLOW_THREADS;
4134 RETURN_IF_ERR();
4135 RETURN_NONE();
4136}
4137
4138
4139static PyObject*
4140DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4141{
4142 int flags = 0;
4143 PyObject* txnobj = NULL;
4144 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004145 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004146
4147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4148 &txnobj, &flags))
4149 return NULL;
4150
4151 if (!checkTxnObj(txnobj, &txn))
4152 return NULL;
4153 CHECK_ENV_NOT_CLOSED(self);
4154
4155 return (PyObject*)newDBTxnObject(self, txn, flags);
4156}
4157
4158
4159static PyObject*
4160DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4161{
4162 int err, kbyte=0, min=0, flags=0;
4163
4164 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4165 return NULL;
4166 CHECK_ENV_NOT_CLOSED(self);
4167
4168 MYDB_BEGIN_ALLOW_THREADS;
4169#if (DBVER >= 40)
4170 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4171#else
4172 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4173#endif
4174 MYDB_END_ALLOW_THREADS;
4175 RETURN_IF_ERR();
4176 RETURN_NONE();
4177}
4178
4179
4180static PyObject*
4181DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4182{
4183 int err, max;
4184
4185 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4186 return NULL;
4187 CHECK_ENV_NOT_CLOSED(self);
4188
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004189 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004190 RETURN_IF_ERR();
4191 RETURN_NONE();
4192}
4193
4194
4195static PyObject*
4196DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4197{
4198 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004199 long stamp;
4200 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004201
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004202 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004203 return NULL;
4204 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004205 timestamp = (time_t)stamp;
4206 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004207 RETURN_IF_ERR();
4208 RETURN_NONE();
4209}
4210
4211
4212static PyObject*
4213DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4214{
4215 int err, atype, flags=0;
4216 int aborted = 0;
4217
4218 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4219 return NULL;
4220 CHECK_ENV_NOT_CLOSED(self);
4221
4222 MYDB_BEGIN_ALLOW_THREADS;
4223#if (DBVER >= 40)
4224 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4225#else
4226 err = lock_detect(self->db_env, flags, atype, &aborted);
4227#endif
4228 MYDB_END_ALLOW_THREADS;
4229 RETURN_IF_ERR();
4230 return PyInt_FromLong(aborted);
4231}
4232
4233
4234static PyObject*
4235DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4236{
4237 int flags=0;
4238 int locker, lock_mode;
4239 DBT obj;
4240 PyObject* objobj;
4241
4242 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4243 return NULL;
4244
4245
4246 if (!make_dbt(objobj, &obj))
4247 return NULL;
4248
4249 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4250}
4251
4252
4253static PyObject*
4254DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4255{
4256 int err;
4257 u_int32_t theID;
4258
4259 if (!PyArg_ParseTuple(args, ":lock_id"))
4260 return NULL;
4261
4262 CHECK_ENV_NOT_CLOSED(self);
4263 MYDB_BEGIN_ALLOW_THREADS;
4264#if (DBVER >= 40)
4265 err = self->db_env->lock_id(self->db_env, &theID);
4266#else
4267 err = lock_id(self->db_env, &theID);
4268#endif
4269 MYDB_END_ALLOW_THREADS;
4270 RETURN_IF_ERR();
4271
4272 return PyInt_FromLong((long)theID);
4273}
4274
4275
4276static PyObject*
4277DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4278{
4279 int err;
4280 DBLockObject* dblockobj;
4281
4282 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4283 return NULL;
4284
4285 CHECK_ENV_NOT_CLOSED(self);
4286 MYDB_BEGIN_ALLOW_THREADS;
4287#if (DBVER >= 40)
4288 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4289#else
4290 err = lock_put(self->db_env, &dblockobj->lock);
4291#endif
4292 MYDB_END_ALLOW_THREADS;
4293 RETURN_IF_ERR();
4294 RETURN_NONE();
4295}
4296
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004297#if (DBVER >= 40)
4298static PyObject*
4299DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4300{
4301 int err;
4302 DB_LOG_STAT* statp = NULL;
4303 PyObject* d = NULL;
4304 u_int32_t flags = 0;
4305
4306 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4307 return NULL;
4308 CHECK_ENV_NOT_CLOSED(self);
4309
4310 MYDB_BEGIN_ALLOW_THREADS;
4311 err = self->db_env->log_stat(self->db_env, &statp, flags);
4312 MYDB_END_ALLOW_THREADS;
4313 RETURN_IF_ERR();
4314
4315 /* Turn the stat structure into a dictionary */
4316 d = PyDict_New();
4317 if (d == NULL) {
4318 if (statp)
4319 free(statp);
4320 return NULL;
4321 }
4322
4323#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4324
4325 MAKE_ENTRY(magic);
4326 MAKE_ENTRY(version);
4327 MAKE_ENTRY(mode);
4328 MAKE_ENTRY(lg_bsize);
4329#if (DBVER >= 44)
4330 MAKE_ENTRY(lg_size);
4331 MAKE_ENTRY(record);
4332#endif
4333#if (DBVER <= 40)
4334 MAKE_ENTRY(lg_max);
4335#endif
4336 MAKE_ENTRY(w_mbytes);
4337 MAKE_ENTRY(w_bytes);
4338 MAKE_ENTRY(wc_mbytes);
4339 MAKE_ENTRY(wc_bytes);
4340 MAKE_ENTRY(wcount);
4341 MAKE_ENTRY(wcount_fill);
4342#if (DBVER >= 44)
4343 MAKE_ENTRY(rcount);
4344#endif
4345 MAKE_ENTRY(scount);
4346 MAKE_ENTRY(cur_file);
4347 MAKE_ENTRY(cur_offset);
4348 MAKE_ENTRY(disk_file);
4349 MAKE_ENTRY(disk_offset);
4350 MAKE_ENTRY(maxcommitperflush);
4351 MAKE_ENTRY(mincommitperflush);
4352 MAKE_ENTRY(regsize);
4353 MAKE_ENTRY(region_wait);
4354 MAKE_ENTRY(region_nowait);
4355
4356#undef MAKE_ENTRY
4357 free(statp);
4358 return d;
4359} /* DBEnv_log_stat */
4360#endif /* DBVER >= 4.0 for log_stat method */
4361
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004362
4363static PyObject*
4364DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4365{
4366 int err;
4367 DB_LOCK_STAT* sp;
4368 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004369 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004370
4371 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4372 return NULL;
4373 CHECK_ENV_NOT_CLOSED(self);
4374
4375 MYDB_BEGIN_ALLOW_THREADS;
4376#if (DBVER >= 40)
4377 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4378#else
4379#if (DBVER >= 33)
4380 err = lock_stat(self->db_env, &sp);
4381#else
4382 err = lock_stat(self->db_env, &sp, NULL);
4383#endif
4384#endif
4385 MYDB_END_ALLOW_THREADS;
4386 RETURN_IF_ERR();
4387
4388 /* Turn the stat structure into a dictionary */
4389 d = PyDict_New();
4390 if (d == NULL) {
4391 free(sp);
4392 return NULL;
4393 }
4394
4395#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4396
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004397#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004398 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004399#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004400 MAKE_ENTRY(nmodes);
4401#if (DBVER >= 32)
4402 MAKE_ENTRY(maxlocks);
4403 MAKE_ENTRY(maxlockers);
4404 MAKE_ENTRY(maxobjects);
4405 MAKE_ENTRY(nlocks);
4406 MAKE_ENTRY(maxnlocks);
4407#endif
4408 MAKE_ENTRY(nlockers);
4409 MAKE_ENTRY(maxnlockers);
4410#if (DBVER >= 32)
4411 MAKE_ENTRY(nobjects);
4412 MAKE_ENTRY(maxnobjects);
4413#endif
4414 MAKE_ENTRY(nrequests);
4415 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004416#if (DBVER < 44)
4417 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004418 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004419#else
4420 MAKE_ENTRY(lock_nowait);
4421 MAKE_ENTRY(lock_wait);
4422#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004423 MAKE_ENTRY(ndeadlocks);
4424 MAKE_ENTRY(regsize);
4425 MAKE_ENTRY(region_wait);
4426 MAKE_ENTRY(region_nowait);
4427
4428#undef MAKE_ENTRY
4429 free(sp);
4430 return d;
4431}
4432
4433
4434static PyObject*
4435DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4436{
4437 int flags=0;
4438 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004439 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004440 PyObject* list;
4441 PyObject* item = NULL;
4442
4443 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4444 return NULL;
4445
4446 CHECK_ENV_NOT_CLOSED(self);
4447 MYDB_BEGIN_ALLOW_THREADS;
4448#if (DBVER >= 40)
4449 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4450#elif (DBVER == 33)
4451 err = log_archive(self->db_env, &log_list, flags);
4452#else
4453 err = log_archive(self->db_env, &log_list, flags, NULL);
4454#endif
4455 MYDB_END_ALLOW_THREADS;
4456 RETURN_IF_ERR();
4457
Gregory P. Smithbad47452006-06-05 00:33:35 +00004458 list = PyList_New(0);
4459 if (list == NULL) {
4460 if (log_list)
4461 free(log_list);
4462 return NULL;
4463 }
4464
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004465 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004466 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004467 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4468 item = PyString_FromString (*log_list);
4469 if (item == NULL) {
4470 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004471 list = NULL;
4472 break;
4473 }
4474 PyList_Append(list, item);
4475 Py_DECREF(item);
4476 }
4477 free(log_list_start);
4478 }
4479 return list;
4480}
4481
4482
4483static PyObject*
4484DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4485{
4486 int err;
4487 DB_TXN_STAT* sp;
4488 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004489 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490
4491 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4492 return NULL;
4493 CHECK_ENV_NOT_CLOSED(self);
4494
4495 MYDB_BEGIN_ALLOW_THREADS;
4496#if (DBVER >= 40)
4497 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4498#elif (DBVER == 33)
4499 err = txn_stat(self->db_env, &sp);
4500#else
4501 err = txn_stat(self->db_env, &sp, NULL);
4502#endif
4503 MYDB_END_ALLOW_THREADS;
4504 RETURN_IF_ERR();
4505
4506 /* Turn the stat structure into a dictionary */
4507 d = PyDict_New();
4508 if (d == NULL) {
4509 free(sp);
4510 return NULL;
4511 }
4512
4513#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4514
4515 MAKE_ENTRY(time_ckp);
4516 MAKE_ENTRY(last_txnid);
4517 MAKE_ENTRY(maxtxns);
4518 MAKE_ENTRY(nactive);
4519 MAKE_ENTRY(maxnactive);
4520 MAKE_ENTRY(nbegins);
4521 MAKE_ENTRY(naborts);
4522 MAKE_ENTRY(ncommits);
4523 MAKE_ENTRY(regsize);
4524 MAKE_ENTRY(region_wait);
4525 MAKE_ENTRY(region_nowait);
4526
4527#undef MAKE_ENTRY
4528 free(sp);
4529 return d;
4530}
4531
4532
4533static PyObject*
4534DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4535{
4536 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004537 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538
4539 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4540 return NULL;
4541 CHECK_ENV_NOT_CLOSED(self);
4542
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004543 if (self->moduleFlags.getReturnsNone)
4544 ++oldValue;
4545 if (self->moduleFlags.cursorSetReturnsNone)
4546 ++oldValue;
4547 self->moduleFlags.getReturnsNone = (flags >= 1);
4548 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004549 return PyInt_FromLong(oldValue);
4550}
4551
4552
4553/* --------------------------------------------------------------------- */
4554/* DBTxn methods */
4555
4556
4557static PyObject*
4558DBTxn_commit(DBTxnObject* self, PyObject* args)
4559{
4560 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004561 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562
4563 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4564 return NULL;
4565
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004566 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004567 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4568 "after txn_commit or txn_abort");
4569 PyErr_SetObject(DBError, t);
4570 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004571 return NULL;
4572 }
4573 txn = self->txn;
4574 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004575 MYDB_BEGIN_ALLOW_THREADS;
4576#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004577 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004578#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004579 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004580#endif
4581 MYDB_END_ALLOW_THREADS;
4582 RETURN_IF_ERR();
4583 RETURN_NONE();
4584}
4585
4586static PyObject*
4587DBTxn_prepare(DBTxnObject* self, PyObject* args)
4588{
4589#if (DBVER >= 33)
4590 int err;
4591 char* gid=NULL;
4592 int gid_size=0;
4593
4594 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4595 return NULL;
4596
4597 if (gid_size != DB_XIDDATASIZE) {
4598 PyErr_SetString(PyExc_TypeError,
4599 "gid must be DB_XIDDATASIZE bytes long");
4600 return NULL;
4601 }
4602
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004603 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004604 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4605 "after txn_commit or txn_abort");
4606 PyErr_SetObject(DBError, t);
4607 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004608 return NULL;
4609 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 MYDB_BEGIN_ALLOW_THREADS;
4611#if (DBVER >= 40)
4612 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4613#else
4614 err = txn_prepare(self->txn, (u_int8_t*)gid);
4615#endif
4616 MYDB_END_ALLOW_THREADS;
4617 RETURN_IF_ERR();
4618 RETURN_NONE();
4619#else
4620 int err;
4621
4622 if (!PyArg_ParseTuple(args, ":prepare"))
4623 return NULL;
4624
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004625 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004626 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4627 "after txn_commit or txn_abort");
4628 PyErr_SetObject(DBError, t);
4629 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004630 return NULL;
4631 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004632 MYDB_BEGIN_ALLOW_THREADS;
4633 err = txn_prepare(self->txn);
4634 MYDB_END_ALLOW_THREADS;
4635 RETURN_IF_ERR();
4636 RETURN_NONE();
4637#endif
4638}
4639
4640
4641static PyObject*
4642DBTxn_abort(DBTxnObject* self, PyObject* args)
4643{
4644 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004645 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004646
4647 if (!PyArg_ParseTuple(args, ":abort"))
4648 return NULL;
4649
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004650 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004651 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4652 "after txn_commit or txn_abort");
4653 PyErr_SetObject(DBError, t);
4654 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004655 return NULL;
4656 }
4657 txn = self->txn;
4658 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004659 MYDB_BEGIN_ALLOW_THREADS;
4660#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004661 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004662#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004663 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664#endif
4665 MYDB_END_ALLOW_THREADS;
4666 RETURN_IF_ERR();
4667 RETURN_NONE();
4668}
4669
4670
4671static PyObject*
4672DBTxn_id(DBTxnObject* self, PyObject* args)
4673{
4674 int id;
4675
4676 if (!PyArg_ParseTuple(args, ":id"))
4677 return NULL;
4678
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004679 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004680 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4681 "after txn_commit or txn_abort");
4682 PyErr_SetObject(DBError, t);
4683 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 return NULL;
4685 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004686 MYDB_BEGIN_ALLOW_THREADS;
4687#if (DBVER >= 40)
4688 id = self->txn->id(self->txn);
4689#else
4690 id = txn_id(self->txn);
4691#endif
4692 MYDB_END_ALLOW_THREADS;
4693 return PyInt_FromLong(id);
4694}
4695
4696/* --------------------------------------------------------------------- */
4697/* Method definition tables and type objects */
4698
4699static PyMethodDef DB_methods[] = {
4700 {"append", (PyCFunction)DB_append, METH_VARARGS},
4701#if (DBVER >= 33)
4702 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4703#endif
4704 {"close", (PyCFunction)DB_close, METH_VARARGS},
4705#if (DBVER >= 32)
4706 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4707 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4708#endif
4709 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4710 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4711 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4712 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004713#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004714 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004715#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004716 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4717 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4718 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4719 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4720 {"join", (PyCFunction)DB_join, METH_VARARGS},
4721 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4722 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4723 {"items", (PyCFunction)DB_items, METH_VARARGS},
4724 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4725 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4726 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4727 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4728 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4729 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004730#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004731 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004732#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004733 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004734#if (DBVER >= 41)
4735 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4736#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004737 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4738 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4739 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4740 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4741 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4742 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4743 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4744 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4745 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4746#if (DBVER >= 32)
4747 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4748#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004749 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004750 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4751#if (DBVER >= 33)
4752 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4753#endif
4754 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4755 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4756 {"values", (PyCFunction)DB_values, METH_VARARGS},
4757 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4758 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4759 {NULL, NULL} /* sentinel */
4760};
4761
4762
4763static PyMappingMethods DB_mapping = {
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00004764#if (PY_VERSION_HEX < 0x02050000)
4765 (inquiry)DB_length, /*mp_length*/
4766#else
Martin v. Löwis18e16552006-02-15 17:27:45 +00004767 (lenfunc)DB_length, /*mp_length*/
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00004768#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769 (binaryfunc)DB_subscript, /*mp_subscript*/
4770 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4771};
4772
4773
4774static PyMethodDef DBCursor_methods[] = {
4775 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4776 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4777 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4778 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4779 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4780 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4781 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004782#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004783 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4786 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4787 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4788 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4789 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4790 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4791 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4792 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004793 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004794 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004795 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4796 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4797 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4798 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4799 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4800 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4801 {NULL, NULL} /* sentinel */
4802};
4803
4804
4805static PyMethodDef DBEnv_methods[] = {
4806 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4807 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4808 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004809#if (DBVER >= 41)
4810 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4811 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4812 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4813#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004814#if (DBVER >= 40)
4815 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4816#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004817 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004818 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4819 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4820#if (DBVER >= 32)
4821 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4822#endif
4823 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4824 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4825 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004826#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00004827 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004828#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004829 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4830 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4831#if (DBVER >= 32)
4832 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4833 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4834 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4835#endif
4836 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4837 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4838 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4839 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4840 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4841 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00004842 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004843 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4844 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4845 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4846 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4847 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4848 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004849#if (DBVER >= 40)
4850 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
4851#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004852 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4853 {NULL, NULL} /* sentinel */
4854};
4855
4856
4857static PyMethodDef DBTxn_methods[] = {
4858 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4859 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4860 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4861 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4862 {NULL, NULL} /* sentinel */
4863};
4864
4865
4866static PyObject*
4867DB_getattr(DBObject* self, char *name)
4868{
4869 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4870}
4871
4872
4873static PyObject*
4874DBEnv_getattr(DBEnvObject* self, char *name)
4875{
4876 if (!strcmp(name, "db_home")) {
4877 CHECK_ENV_NOT_CLOSED(self);
4878 if (self->db_env->db_home == NULL) {
4879 RETURN_NONE();
4880 }
4881 return PyString_FromString(self->db_env->db_home);
4882 }
4883
4884 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4885}
4886
4887
4888static PyObject*
4889DBCursor_getattr(DBCursorObject* self, char *name)
4890{
4891 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4892}
4893
4894static PyObject*
4895DBTxn_getattr(DBTxnObject* self, char *name)
4896{
4897 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4898}
4899
4900static PyObject*
4901DBLock_getattr(DBLockObject* self, char *name)
4902{
4903 return NULL;
4904}
4905
4906statichere PyTypeObject DB_Type = {
4907 PyObject_HEAD_INIT(NULL)
4908 0, /*ob_size*/
4909 "DB", /*tp_name*/
4910 sizeof(DBObject), /*tp_basicsize*/
4911 0, /*tp_itemsize*/
4912 /* methods */
4913 (destructor)DB_dealloc, /*tp_dealloc*/
4914 0, /*tp_print*/
4915 (getattrfunc)DB_getattr, /*tp_getattr*/
4916 0, /*tp_setattr*/
4917 0, /*tp_compare*/
4918 0, /*tp_repr*/
4919 0, /*tp_as_number*/
4920 0, /*tp_as_sequence*/
4921 &DB_mapping,/*tp_as_mapping*/
4922 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004923#ifdef HAVE_WEAKREF
4924 0, /* tp_call */
4925 0, /* tp_str */
4926 0, /* tp_getattro */
4927 0, /* tp_setattro */
4928 0, /* tp_as_buffer */
4929 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4930 0, /* tp_doc */
4931 0, /* tp_traverse */
4932 0, /* tp_clear */
4933 0, /* tp_richcompare */
4934 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4935#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004936};
4937
4938
4939statichere PyTypeObject DBCursor_Type = {
4940 PyObject_HEAD_INIT(NULL)
4941 0, /*ob_size*/
4942 "DBCursor", /*tp_name*/
4943 sizeof(DBCursorObject), /*tp_basicsize*/
4944 0, /*tp_itemsize*/
4945 /* methods */
4946 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4947 0, /*tp_print*/
4948 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4949 0, /*tp_setattr*/
4950 0, /*tp_compare*/
4951 0, /*tp_repr*/
4952 0, /*tp_as_number*/
4953 0, /*tp_as_sequence*/
4954 0, /*tp_as_mapping*/
4955 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004956#ifdef HAVE_WEAKREF
4957 0, /* tp_call */
4958 0, /* tp_str */
4959 0, /* tp_getattro */
4960 0, /* tp_setattro */
4961 0, /* tp_as_buffer */
4962 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4963 0, /* tp_doc */
4964 0, /* tp_traverse */
4965 0, /* tp_clear */
4966 0, /* tp_richcompare */
4967 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4968#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004969};
4970
4971
4972statichere PyTypeObject DBEnv_Type = {
4973 PyObject_HEAD_INIT(NULL)
4974 0, /*ob_size*/
4975 "DBEnv", /*tp_name*/
4976 sizeof(DBEnvObject), /*tp_basicsize*/
4977 0, /*tp_itemsize*/
4978 /* methods */
4979 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4980 0, /*tp_print*/
4981 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4982 0, /*tp_setattr*/
4983 0, /*tp_compare*/
4984 0, /*tp_repr*/
4985 0, /*tp_as_number*/
4986 0, /*tp_as_sequence*/
4987 0, /*tp_as_mapping*/
4988 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004989#ifdef HAVE_WEAKREF
4990 0, /* tp_call */
4991 0, /* tp_str */
4992 0, /* tp_getattro */
4993 0, /* tp_setattro */
4994 0, /* tp_as_buffer */
4995 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4996 0, /* tp_doc */
4997 0, /* tp_traverse */
4998 0, /* tp_clear */
4999 0, /* tp_richcompare */
5000 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5001#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005002};
5003
5004statichere PyTypeObject DBTxn_Type = {
5005 PyObject_HEAD_INIT(NULL)
5006 0, /*ob_size*/
5007 "DBTxn", /*tp_name*/
5008 sizeof(DBTxnObject), /*tp_basicsize*/
5009 0, /*tp_itemsize*/
5010 /* methods */
5011 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5012 0, /*tp_print*/
5013 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5014 0, /*tp_setattr*/
5015 0, /*tp_compare*/
5016 0, /*tp_repr*/
5017 0, /*tp_as_number*/
5018 0, /*tp_as_sequence*/
5019 0, /*tp_as_mapping*/
5020 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005021#ifdef HAVE_WEAKREF
5022 0, /* tp_call */
5023 0, /* tp_str */
5024 0, /* tp_getattro */
5025 0, /* tp_setattro */
5026 0, /* tp_as_buffer */
5027 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5028 0, /* tp_doc */
5029 0, /* tp_traverse */
5030 0, /* tp_clear */
5031 0, /* tp_richcompare */
5032 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5033#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005034};
5035
5036
5037statichere PyTypeObject DBLock_Type = {
5038 PyObject_HEAD_INIT(NULL)
5039 0, /*ob_size*/
5040 "DBLock", /*tp_name*/
5041 sizeof(DBLockObject), /*tp_basicsize*/
5042 0, /*tp_itemsize*/
5043 /* methods */
5044 (destructor)DBLock_dealloc, /*tp_dealloc*/
5045 0, /*tp_print*/
5046 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5047 0, /*tp_setattr*/
5048 0, /*tp_compare*/
5049 0, /*tp_repr*/
5050 0, /*tp_as_number*/
5051 0, /*tp_as_sequence*/
5052 0, /*tp_as_mapping*/
5053 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005054#ifdef HAVE_WEAKREF
5055 0, /* tp_call */
5056 0, /* tp_str */
5057 0, /* tp_getattro */
5058 0, /* tp_setattro */
5059 0, /* tp_as_buffer */
5060 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5061 0, /* tp_doc */
5062 0, /* tp_traverse */
5063 0, /* tp_clear */
5064 0, /* tp_richcompare */
5065 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5066#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005067};
5068
5069
5070/* --------------------------------------------------------------------- */
5071/* Module-level functions */
5072
5073static PyObject*
5074DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5075{
5076 PyObject* dbenvobj = NULL;
5077 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005078 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005079
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005080 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5081 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005082 return NULL;
5083 if (dbenvobj == Py_None)
5084 dbenvobj = NULL;
5085 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5086 makeTypeError("DBEnv", dbenvobj);
5087 return NULL;
5088 }
5089
5090 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5091}
5092
5093
5094static PyObject*
5095DBEnv_construct(PyObject* self, PyObject* args)
5096{
5097 int flags = 0;
5098 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5099 return (PyObject* )newDBEnvObject(flags);
5100}
5101
5102
5103static char bsddb_version_doc[] =
5104"Returns a tuple of major, minor, and patch release numbers of the\n\
5105underlying DB library.";
5106
5107static PyObject*
5108bsddb_version(PyObject* self, PyObject* args)
5109{
5110 int major, minor, patch;
5111
5112 if (!PyArg_ParseTuple(args, ":version"))
5113 return NULL;
5114 db_version(&major, &minor, &patch);
5115 return Py_BuildValue("(iii)", major, minor, patch);
5116}
5117
5118
5119/* List of functions defined in the module */
5120
5121static PyMethodDef bsddb_methods[] = {
5122 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5123 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5124 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5125 {NULL, NULL} /* sentinel */
5126};
5127
5128
5129/* --------------------------------------------------------------------- */
5130/* Module initialization */
5131
5132
5133/* Convenience routine to export an integer value.
5134 * Errors are silently ignored, for better or for worse...
5135 */
5136#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5137
Gregory P. Smith41631e82003-09-21 00:08:14 +00005138#define MODULE_NAME_MAX_LEN 11
5139static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005140
5141DL_EXPORT(void) init_bsddb(void)
5142{
5143 PyObject* m;
5144 PyObject* d;
5145 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5146 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5147 PyObject* cvsid_s = PyString_FromString( rcs_id );
5148
5149 /* Initialize the type of the new type objects here; doing it here
5150 is required for portability to Windows without requiring C++. */
5151 DB_Type.ob_type = &PyType_Type;
5152 DBCursor_Type.ob_type = &PyType_Type;
5153 DBEnv_Type.ob_type = &PyType_Type;
5154 DBTxn_Type.ob_type = &PyType_Type;
5155 DBLock_Type.ob_type = &PyType_Type;
5156
5157
Mark Hammonda69d4092003-04-22 23:13:27 +00005158#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005159 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005160 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005161#endif
5162
5163 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005164 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005165 if (m == NULL)
5166 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005167
5168 /* Add some symbolic constants to the module */
5169 d = PyModule_GetDict(m);
5170 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5171 PyDict_SetItemString(d, "cvsid", cvsid_s);
5172 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5173 Py_DECREF(pybsddb_version_s);
5174 pybsddb_version_s = NULL;
5175 Py_DECREF(cvsid_s);
5176 cvsid_s = NULL;
5177 Py_DECREF(db_version_s);
5178 db_version_s = NULL;
5179
5180 ADD_INT(d, DB_VERSION_MAJOR);
5181 ADD_INT(d, DB_VERSION_MINOR);
5182 ADD_INT(d, DB_VERSION_PATCH);
5183
5184 ADD_INT(d, DB_MAX_PAGES);
5185 ADD_INT(d, DB_MAX_RECORDS);
5186
Gregory P. Smith41631e82003-09-21 00:08:14 +00005187#if (DBVER >= 42)
5188 ADD_INT(d, DB_RPCCLIENT);
5189#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005190 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005191 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5192 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005194 ADD_INT(d, DB_XA_CREATE);
5195
5196 ADD_INT(d, DB_CREATE);
5197 ADD_INT(d, DB_NOMMAP);
5198 ADD_INT(d, DB_THREAD);
5199
5200 ADD_INT(d, DB_FORCE);
5201 ADD_INT(d, DB_INIT_CDB);
5202 ADD_INT(d, DB_INIT_LOCK);
5203 ADD_INT(d, DB_INIT_LOG);
5204 ADD_INT(d, DB_INIT_MPOOL);
5205 ADD_INT(d, DB_INIT_TXN);
5206#if (DBVER >= 32)
5207 ADD_INT(d, DB_JOINENV);
5208#endif
5209
5210 ADD_INT(d, DB_RECOVER);
5211 ADD_INT(d, DB_RECOVER_FATAL);
5212 ADD_INT(d, DB_TXN_NOSYNC);
5213 ADD_INT(d, DB_USE_ENVIRON);
5214 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5215
5216 ADD_INT(d, DB_LOCKDOWN);
5217 ADD_INT(d, DB_PRIVATE);
5218 ADD_INT(d, DB_SYSTEM_MEM);
5219
5220 ADD_INT(d, DB_TXN_SYNC);
5221 ADD_INT(d, DB_TXN_NOWAIT);
5222
5223 ADD_INT(d, DB_EXCL);
5224 ADD_INT(d, DB_FCNTL_LOCKING);
5225 ADD_INT(d, DB_ODDFILESIZE);
5226 ADD_INT(d, DB_RDWRMASTER);
5227 ADD_INT(d, DB_RDONLY);
5228 ADD_INT(d, DB_TRUNCATE);
5229#if (DBVER >= 32)
5230 ADD_INT(d, DB_EXTENT);
5231 ADD_INT(d, DB_CDB_ALLDB);
5232 ADD_INT(d, DB_VERIFY);
5233#endif
5234 ADD_INT(d, DB_UPGRADE);
5235
5236 ADD_INT(d, DB_AGGRESSIVE);
5237 ADD_INT(d, DB_NOORDERCHK);
5238 ADD_INT(d, DB_ORDERCHKONLY);
5239 ADD_INT(d, DB_PR_PAGE);
5240#if ! (DBVER >= 33)
5241 ADD_INT(d, DB_VRFY_FLAGMASK);
5242 ADD_INT(d, DB_PR_HEADERS);
5243#endif
5244 ADD_INT(d, DB_PR_RECOVERYTEST);
5245 ADD_INT(d, DB_SALVAGE);
5246
5247 ADD_INT(d, DB_LOCK_NORUN);
5248 ADD_INT(d, DB_LOCK_DEFAULT);
5249 ADD_INT(d, DB_LOCK_OLDEST);
5250 ADD_INT(d, DB_LOCK_RANDOM);
5251 ADD_INT(d, DB_LOCK_YOUNGEST);
5252#if (DBVER >= 33)
5253 ADD_INT(d, DB_LOCK_MAXLOCKS);
5254 ADD_INT(d, DB_LOCK_MINLOCKS);
5255 ADD_INT(d, DB_LOCK_MINWRITE);
5256#endif
5257
5258
5259#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005260 /* docs say to use zero instead */
5261 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262#else
5263 ADD_INT(d, DB_LOCK_CONFLICT);
5264#endif
5265
5266 ADD_INT(d, DB_LOCK_DUMP);
5267 ADD_INT(d, DB_LOCK_GET);
5268 ADD_INT(d, DB_LOCK_INHERIT);
5269 ADD_INT(d, DB_LOCK_PUT);
5270 ADD_INT(d, DB_LOCK_PUT_ALL);
5271 ADD_INT(d, DB_LOCK_PUT_OBJ);
5272
5273 ADD_INT(d, DB_LOCK_NG);
5274 ADD_INT(d, DB_LOCK_READ);
5275 ADD_INT(d, DB_LOCK_WRITE);
5276 ADD_INT(d, DB_LOCK_NOWAIT);
5277#if (DBVER >= 32)
5278 ADD_INT(d, DB_LOCK_WAIT);
5279#endif
5280 ADD_INT(d, DB_LOCK_IWRITE);
5281 ADD_INT(d, DB_LOCK_IREAD);
5282 ADD_INT(d, DB_LOCK_IWR);
5283#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005284#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005285 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005286#else
5287 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005289 ADD_INT(d, DB_LOCK_WWRITE);
5290#endif
5291
5292 ADD_INT(d, DB_LOCK_RECORD);
5293 ADD_INT(d, DB_LOCK_UPGRADE);
5294#if (DBVER >= 32)
5295 ADD_INT(d, DB_LOCK_SWITCH);
5296#endif
5297#if (DBVER >= 33)
5298 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5299#endif
5300
5301 ADD_INT(d, DB_LOCK_NOWAIT);
5302 ADD_INT(d, DB_LOCK_RECORD);
5303 ADD_INT(d, DB_LOCK_UPGRADE);
5304
5305#if (DBVER >= 33)
5306 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005307#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005308 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005309#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005310 ADD_INT(d, DB_LSTAT_FREE);
5311 ADD_INT(d, DB_LSTAT_HELD);
5312#if (DBVER == 33)
5313 ADD_INT(d, DB_LSTAT_NOGRANT);
5314#endif
5315 ADD_INT(d, DB_LSTAT_PENDING);
5316 ADD_INT(d, DB_LSTAT_WAITING);
5317#endif
5318
5319 ADD_INT(d, DB_ARCH_ABS);
5320 ADD_INT(d, DB_ARCH_DATA);
5321 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005322#if (DBVER >= 42)
5323 ADD_INT(d, DB_ARCH_REMOVE);
5324#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005325
5326 ADD_INT(d, DB_BTREE);
5327 ADD_INT(d, DB_HASH);
5328 ADD_INT(d, DB_RECNO);
5329 ADD_INT(d, DB_QUEUE);
5330 ADD_INT(d, DB_UNKNOWN);
5331
5332 ADD_INT(d, DB_DUP);
5333 ADD_INT(d, DB_DUPSORT);
5334 ADD_INT(d, DB_RECNUM);
5335 ADD_INT(d, DB_RENUMBER);
5336 ADD_INT(d, DB_REVSPLITOFF);
5337 ADD_INT(d, DB_SNAPSHOT);
5338
5339 ADD_INT(d, DB_JOIN_NOSORT);
5340
5341 ADD_INT(d, DB_AFTER);
5342 ADD_INT(d, DB_APPEND);
5343 ADD_INT(d, DB_BEFORE);
5344 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005345#if (DBVER >= 41)
5346 _addIntToDict(d, "DB_CHECKPOINT", 0);
5347#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005348 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005349 ADD_INT(d, DB_CURLSN);
5350#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005351#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005352 ADD_INT(d, DB_COMMIT);
5353#endif
5354 ADD_INT(d, DB_CONSUME);
5355#if (DBVER >= 32)
5356 ADD_INT(d, DB_CONSUME_WAIT);
5357#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005358 ADD_INT(d, DB_CURRENT);
5359#if (DBVER >= 33)
5360 ADD_INT(d, DB_FAST_STAT);
5361#endif
5362 ADD_INT(d, DB_FIRST);
5363 ADD_INT(d, DB_FLUSH);
5364 ADD_INT(d, DB_GET_BOTH);
5365 ADD_INT(d, DB_GET_RECNO);
5366 ADD_INT(d, DB_JOIN_ITEM);
5367 ADD_INT(d, DB_KEYFIRST);
5368 ADD_INT(d, DB_KEYLAST);
5369 ADD_INT(d, DB_LAST);
5370 ADD_INT(d, DB_NEXT);
5371 ADD_INT(d, DB_NEXT_DUP);
5372 ADD_INT(d, DB_NEXT_NODUP);
5373 ADD_INT(d, DB_NODUPDATA);
5374 ADD_INT(d, DB_NOOVERWRITE);
5375 ADD_INT(d, DB_NOSYNC);
5376 ADD_INT(d, DB_POSITION);
5377 ADD_INT(d, DB_PREV);
5378 ADD_INT(d, DB_PREV_NODUP);
5379 ADD_INT(d, DB_RECORDCOUNT);
5380 ADD_INT(d, DB_SET);
5381 ADD_INT(d, DB_SET_RANGE);
5382 ADD_INT(d, DB_SET_RECNO);
5383 ADD_INT(d, DB_WRITECURSOR);
5384
5385 ADD_INT(d, DB_OPFLAGS_MASK);
5386 ADD_INT(d, DB_RMW);
5387#if (DBVER >= 33)
5388 ADD_INT(d, DB_DIRTY_READ);
5389 ADD_INT(d, DB_MULTIPLE);
5390 ADD_INT(d, DB_MULTIPLE_KEY);
5391#endif
5392
Gregory P. Smith29602d22006-01-24 09:46:48 +00005393#if (DBVER >= 44)
5394 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5395 ADD_INT(d, DB_READ_COMMITTED);
5396#endif
5397
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005398#if (DBVER >= 33)
5399 ADD_INT(d, DB_DONOTINDEX);
5400#endif
5401
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005402#if (DBVER >= 41)
5403 _addIntToDict(d, "DB_INCOMPLETE", 0);
5404#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005405 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005406#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005407 ADD_INT(d, DB_KEYEMPTY);
5408 ADD_INT(d, DB_KEYEXIST);
5409 ADD_INT(d, DB_LOCK_DEADLOCK);
5410 ADD_INT(d, DB_LOCK_NOTGRANTED);
5411 ADD_INT(d, DB_NOSERVER);
5412 ADD_INT(d, DB_NOSERVER_HOME);
5413 ADD_INT(d, DB_NOSERVER_ID);
5414 ADD_INT(d, DB_NOTFOUND);
5415 ADD_INT(d, DB_OLD_VERSION);
5416 ADD_INT(d, DB_RUNRECOVERY);
5417 ADD_INT(d, DB_VERIFY_BAD);
5418#if (DBVER >= 33)
5419 ADD_INT(d, DB_PAGE_NOTFOUND);
5420 ADD_INT(d, DB_SECONDARY_BAD);
5421#endif
5422#if (DBVER >= 40)
5423 ADD_INT(d, DB_STAT_CLEAR);
5424 ADD_INT(d, DB_REGION_INIT);
5425 ADD_INT(d, DB_NOLOCKING);
5426 ADD_INT(d, DB_YIELDCPU);
5427 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5428 ADD_INT(d, DB_NOPANIC);
5429#endif
5430
Gregory P. Smith41631e82003-09-21 00:08:14 +00005431#if (DBVER >= 42)
5432 ADD_INT(d, DB_TIME_NOTGRANTED);
5433 ADD_INT(d, DB_TXN_NOT_DURABLE);
5434 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5435 ADD_INT(d, DB_LOG_AUTOREMOVE);
5436 ADD_INT(d, DB_DIRECT_LOG);
5437 ADD_INT(d, DB_DIRECT_DB);
5438 ADD_INT(d, DB_INIT_REP);
5439 ADD_INT(d, DB_ENCRYPT);
5440 ADD_INT(d, DB_CHKSUM);
5441#endif
5442
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005443#if (DBVER >= 43)
5444 ADD_INT(d, DB_LOG_INMEMORY);
5445 ADD_INT(d, DB_BUFFER_SMALL);
5446#endif
5447
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005448#if (DBVER >= 41)
5449 ADD_INT(d, DB_ENCRYPT_AES);
5450 ADD_INT(d, DB_AUTO_COMMIT);
5451#else
5452 /* allow berkeleydb 4.1 aware apps to run on older versions */
5453 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5454#endif
5455
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005456 ADD_INT(d, EINVAL);
5457 ADD_INT(d, EACCES);
5458 ADD_INT(d, ENOSPC);
5459 ADD_INT(d, ENOMEM);
5460 ADD_INT(d, EAGAIN);
5461 ADD_INT(d, EBUSY);
5462 ADD_INT(d, EEXIST);
5463 ADD_INT(d, ENOENT);
5464 ADD_INT(d, EPERM);
5465
Barry Warsaw1baa9822003-03-31 19:51:29 +00005466#if (DBVER >= 40)
5467 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5468 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5469#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005470
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005471 /* The exception name must be correct for pickled exception *
5472 * objects to unpickle properly. */
5473#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5474#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5475#else
5476#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5477#endif
5478
5479 /* All the rest of the exceptions derive only from DBError */
5480#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5481 PyDict_SetItemString(d, #name, name)
5482
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005483 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005484 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5485 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005486
Gregory P. Smithe9477062005-06-04 06:46:59 +00005487 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5488 * from both DBError and KeyError, since the API only supports
5489 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005490 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005491 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5492 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005493 Py_file_input, d, d);
5494 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005495 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005496 PyDict_DelItemString(d, "KeyError");
5497
5498
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499#if !INCOMPLETE_IS_WARNING
5500 MAKE_EX(DBIncompleteError);
5501#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005502 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005503 MAKE_EX(DBKeyEmptyError);
5504 MAKE_EX(DBKeyExistError);
5505 MAKE_EX(DBLockDeadlockError);
5506 MAKE_EX(DBLockNotGrantedError);
5507 MAKE_EX(DBOldVersionError);
5508 MAKE_EX(DBRunRecoveryError);
5509 MAKE_EX(DBVerifyBadError);
5510 MAKE_EX(DBNoServerError);
5511 MAKE_EX(DBNoServerHomeError);
5512 MAKE_EX(DBNoServerIDError);
5513#if (DBVER >= 33)
5514 MAKE_EX(DBPageNotFoundError);
5515 MAKE_EX(DBSecondaryBadError);
5516#endif
5517
5518 MAKE_EX(DBInvalidArgError);
5519 MAKE_EX(DBAccessError);
5520 MAKE_EX(DBNoSpaceError);
5521 MAKE_EX(DBNoMemoryError);
5522 MAKE_EX(DBAgainError);
5523 MAKE_EX(DBBusyError);
5524 MAKE_EX(DBFileExistsError);
5525 MAKE_EX(DBNoSuchFileError);
5526 MAKE_EX(DBPermissionsError);
5527
5528#undef MAKE_EX
5529
5530 /* Check for errors */
5531 if (PyErr_Occurred()) {
5532 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005533 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005534 }
5535}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005536
5537/* allow this module to be named _pybsddb so that it can be installed
5538 * and imported on top of python >= 2.3 that includes its own older
5539 * copy of the library named _bsddb without importing the old version. */
5540DL_EXPORT(void) init_pybsddb(void)
5541{
5542 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5543 init_bsddb();
5544}