blob: 8e9ec0f0cfc9e593f1c4fe5d430887cdd1df7683 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
Gregory P. Smitha703a212003-11-03 01:04:41 +000087#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000088#include <Python.h>
89#include <db.h>
90
91/* --------------------------------------------------------------------- */
92/* Various macro definitions */
93
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000094/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
95#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000096#if DB_VERSION_MINOR > 9
97#error "eek! DBVER can't handle minor versions > 9"
98#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
Gregory P. Smith8a474042006-01-27 07:05:40 +0000100#define PY_BSDDB_VERSION "4.4.2"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000101static char *rcs_id = "$Id$";
102
103
104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Gregory P. Smitha703a212003-11-03 01:04:41 +0000194#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
195#define HAVE_WEAKREF
196#else
197#undef HAVE_WEAKREF
198#endif
199
Gregory P. Smith31c50652004-06-28 01:20:40 +0000200/* if Python >= 2.1 better support warnings */
201#if PYTHON_API_VERSION >= 1010
202#define HAVE_WARNINGS
203#else
204#undef HAVE_WARNINGS
205#endif
206
Neal Norwitzb4a55812004-07-09 23:30:57 +0000207#if PYTHON_API_VERSION <= 1007
208 /* 1.5 compatibility */
209#define PyObject_New PyObject_NEW
210#define PyObject_Del PyMem_DEL
211#endif
212
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000213struct behaviourFlags {
214 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000215 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000216 unsigned int getReturnsNone : 1;
217 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000218 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000219 unsigned int cursorSetReturnsNone : 1;
220};
221
222#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000223#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000225typedef struct {
226 PyObject_HEAD
227 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000228 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000231#ifdef HAVE_WEAKREF
232 PyObject *in_weakreflist; /* List of weak references */
233#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234} DBEnvObject;
235
236
237typedef struct {
238 PyObject_HEAD
239 DB* db;
240 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000241 u_int32_t flags; /* saved flags from open() */
242 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000244 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245#if (DBVER >= 33)
246 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000247 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int primaryDBType;
249#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000250#ifdef HAVE_WEAKREF
251 PyObject *in_weakreflist; /* List of weak references */
252#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253} DBObject;
254
255
256typedef struct {
257 PyObject_HEAD
258 DBC* dbc;
259 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000260#ifdef HAVE_WEAKREF
261 PyObject *in_weakreflist; /* List of weak references */
262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000263} DBCursorObject;
264
265
266typedef struct {
267 PyObject_HEAD
268 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000269 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000270#ifdef HAVE_WEAKREF
271 PyObject *in_weakreflist; /* List of weak references */
272#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000273} DBTxnObject;
274
275
276typedef struct {
277 PyObject_HEAD
278 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000279#ifdef HAVE_WEAKREF
280 PyObject *in_weakreflist; /* List of weak references */
281#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000282} DBLockObject;
283
284
285
Neal Norwitz227b5332006-03-22 09:28:35 +0000286static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287
288#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
289#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
290#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
291#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
292#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
293
294
295/* --------------------------------------------------------------------- */
296/* Utility macros and functions */
297
298#define RETURN_IF_ERR() \
299 if (makeDBError(err)) { \
300 return NULL; \
301 }
302
303#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
304
Gregory P. Smithe2767172003-11-02 08:06:29 +0000305#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
306 if ((nonNull) == NULL) { \
307 PyObject *errTuple = NULL; \
308 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
309 PyErr_SetObject((pyErrObj), errTuple); \
310 Py_DECREF(errTuple); \
311 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000312 }
313
Gregory P. Smithe2767172003-11-02 08:06:29 +0000314#define CHECK_DB_NOT_CLOSED(dbobj) \
315 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
316
317#define CHECK_ENV_NOT_CLOSED(env) \
318 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000319
320#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000321 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000322
323
324#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
325 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
326
327#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
328
329#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000330 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000331
332
333static int makeDBError(int err);
334
335
336/* Return the access method type of the DBObject */
337static int _DB_get_type(DBObject* self)
338{
339#if (DBVER >= 33)
340 DBTYPE type;
341 int err;
342 err = self->db->get_type(self->db, &type);
343 if (makeDBError(err)) {
344 return -1;
345 }
346 return type;
347#else
348 return self->db->get_type(self->db);
349#endif
350}
351
352
353/* Create a DBT structure (containing key and data values) from Python
354 strings. Returns 1 on success, 0 on an error. */
355static int make_dbt(PyObject* obj, DBT* dbt)
356{
357 CLEAR_DBT(*dbt);
358 if (obj == Py_None) {
359 /* no need to do anything, the structure has already been zeroed */
360 }
361 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
362 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000363 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000364 return 0;
365 }
366 return 1;
367}
368
369
370/* Recno and Queue DBs can have integer keys. This function figures out
371 what's been given, verifies that it's allowed, and then makes the DBT.
372
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000373 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000374static int
375make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000376{
377 db_recno_t recno;
378 int type;
379
380 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000381 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000382 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000383 if (type == -1)
384 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 if (type == DB_RECNO || type == DB_QUEUE) {
386 PyErr_SetString(
387 PyExc_TypeError,
388 "None keys not allowed for Recno and Queue DB's");
389 return 0;
390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000391 /* no need to do anything, the structure has already been zeroed */
392 }
393
394 else if (PyString_Check(keyobj)) {
395 /* verify access method type */
396 type = _DB_get_type(self);
397 if (type == -1)
398 return 0;
399 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000400 PyErr_SetString(
401 PyExc_TypeError,
402 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000403 return 0;
404 }
405
406 key->data = PyString_AS_STRING(keyobj);
407 key->size = PyString_GET_SIZE(keyobj);
408 }
409
410 else if (PyInt_Check(keyobj)) {
411 /* verify access method type */
412 type = _DB_get_type(self);
413 if (type == -1)
414 return 0;
415 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000416 /* if BTREE then an Integer key is allowed with the
417 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000418 *pflags |= DB_SET_RECNO;
419 }
420 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000421 PyErr_SetString(
422 PyExc_TypeError,
423 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000424 return 0;
425 }
426
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000427 /* Make a key out of the requested recno, use allocated space so DB
428 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000429 recno = PyInt_AS_LONG(keyobj);
430 key->data = malloc(sizeof(db_recno_t));
431 if (key->data == NULL) {
432 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
433 return 0;
434 }
435 key->ulen = key->size = sizeof(db_recno_t);
436 memcpy(key->data, &recno, sizeof(db_recno_t));
437 key->flags = DB_DBT_REALLOC;
438 }
439 else {
440 PyErr_Format(PyExc_TypeError,
441 "String or Integer object expected for key, %s found",
442 keyobj->ob_type->tp_name);
443 return 0;
444 }
445
446 return 1;
447}
448
449
450/* Add partial record access to an existing DBT data struct.
451 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
452 and the data storage/retrieval will be done using dlen and doff. */
453static int add_partial_dbt(DBT* d, int dlen, int doff) {
454 /* if neither were set we do nothing (-1 is the default value) */
455 if ((dlen == -1) && (doff == -1)) {
456 return 1;
457 }
458
459 if ((dlen < 0) || (doff < 0)) {
460 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
461 return 0;
462 }
463
464 d->flags = d->flags | DB_DBT_PARTIAL;
465 d->dlen = (unsigned int) dlen;
466 d->doff = (unsigned int) doff;
467 return 1;
468}
469
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000470/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
471/* TODO: make this use the native libc strlcpy() when available (BSD) */
472unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
473{
474 unsigned int srclen, copylen;
475
476 srclen = strlen(src);
477 if (n <= 0)
478 return srclen;
479 copylen = (srclen > n-1) ? n-1 : srclen;
480 /* populate dest[0] thru dest[copylen-1] */
481 memcpy(dest, src, copylen);
482 /* guarantee null termination */
483 dest[copylen] = 0;
484
485 return srclen;
486}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000487
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000488/* Callback used to save away more information about errors from the DB
489 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000490static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000492static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000493#else
494static void _db_errorCallback(const DB_ENV *db_env,
495 const char* prefix, const char* msg)
496#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000497{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000498 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000499}
500
501
502/* make a nice exception object to raise for errors. */
503static int makeDBError(int err)
504{
505 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000506 PyObject *errObj = NULL;
507 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508 int exceptionRaised = 0;
509
510 switch (err) {
511 case 0: /* successful, no error */ break;
512
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000513#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514 case DB_INCOMPLETE:
515#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000516 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000517 if (_db_errmsg[0]) {
518 strcat(errTxt, " -- ");
519 strcat(errTxt, _db_errmsg);
520 _db_errmsg[0] = 0;
521 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000522#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
524#else
525 fprintf(stderr, errTxt);
526 fprintf(stderr, "\n");
527#endif
528
529#else /* do an exception instead */
530 errObj = DBIncompleteError;
531#endif
532 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000533#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000534
535 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
536 case DB_KEYEXIST: errObj = DBKeyExistError; break;
537 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
538 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
539 case DB_NOTFOUND: errObj = DBNotFoundError; break;
540 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
541 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
542 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
543 case DB_NOSERVER: errObj = DBNoServerError; break;
544 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
545 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
546#if (DBVER >= 33)
547 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
548 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
549#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000550 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000551
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000552#if (DBVER >= 43)
553 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
554 case ENOMEM: errObj = PyExc_MemoryError; break;
555#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556 case EINVAL: errObj = DBInvalidArgError; break;
557 case EACCES: errObj = DBAccessError; break;
558 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000559 case EAGAIN: errObj = DBAgainError; break;
560 case EBUSY : errObj = DBBusyError; break;
561 case EEXIST: errObj = DBFileExistsError; break;
562 case ENOENT: errObj = DBNoSuchFileError; break;
563 case EPERM : errObj = DBPermissionsError; break;
564
565 default: errObj = DBError; break;
566 }
567
568 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000569 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000570 if (_db_errmsg[0]) {
571 strcat(errTxt, " -- ");
572 strcat(errTxt, _db_errmsg);
573 _db_errmsg[0] = 0;
574 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000575
576 errTuple = Py_BuildValue("(is)", err, errTxt);
577 PyErr_SetObject(errObj, errTuple);
578 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000579 }
580
581 return ((errObj != NULL) || exceptionRaised);
582}
583
584
585
586/* set a type exception */
587static void makeTypeError(char* expected, PyObject* found)
588{
589 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
590 expected, found->ob_type->tp_name);
591}
592
593
594/* verify that an obj is either None or a DBTxn, and set the txn pointer */
595static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
596{
597 if (txnobj == Py_None || txnobj == NULL) {
598 *txn = NULL;
599 return 1;
600 }
601 if (DBTxnObject_Check(txnobj)) {
602 *txn = ((DBTxnObject*)txnobj)->txn;
603 return 1;
604 }
605 else
606 makeTypeError("DBTxn", txnobj);
607 return 0;
608}
609
610
611/* Delete a key from a database
612 Returns 0 on success, -1 on an error. */
613static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
614{
615 int err;
616
617 MYDB_BEGIN_ALLOW_THREADS;
618 err = self->db->del(self->db, txn, key, 0);
619 MYDB_END_ALLOW_THREADS;
620 if (makeDBError(err)) {
621 return -1;
622 }
623 self->haveStat = 0;
624 return 0;
625}
626
627
628/* Store a key into a database
629 Returns 0 on success, -1 on an error. */
630static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
631{
632 int err;
633
634 MYDB_BEGIN_ALLOW_THREADS;
635 err = self->db->put(self->db, txn, key, data, flags);
636 MYDB_END_ALLOW_THREADS;
637 if (makeDBError(err)) {
638 return -1;
639 }
640 self->haveStat = 0;
641 return 0;
642}
643
644/* Get a key/data pair from a cursor */
645static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
646 PyObject *args, PyObject *kwargs, char *format)
647{
648 int err;
649 PyObject* retval = NULL;
650 DBT key, data;
651 int dlen = -1;
652 int doff = -1;
653 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000654 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000655
656 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
657 &flags, &dlen, &doff))
658 return NULL;
659
660 CHECK_CURSOR_NOT_CLOSED(self);
661
662 flags |= extra_flags;
663 CLEAR_DBT(key);
664 CLEAR_DBT(data);
665 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
666 /* Tell BerkeleyDB to malloc the return value (thread safe) */
667 data.flags = DB_DBT_MALLOC;
668 key.flags = DB_DBT_MALLOC;
669 }
670 if (!add_partial_dbt(&data, dlen, doff))
671 return NULL;
672
673 MYDB_BEGIN_ALLOW_THREADS;
674 err = self->dbc->c_get(self->dbc, &key, &data, flags);
675 MYDB_END_ALLOW_THREADS;
676
Gregory P. Smithe9477062005-06-04 06:46:59 +0000677 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
678 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679 Py_INCREF(Py_None);
680 retval = Py_None;
681 }
682 else if (makeDBError(err)) {
683 retval = NULL;
684 }
685 else { /* otherwise, success! */
686
687 /* if Recno or Queue, return the key as an Int */
688 switch (_DB_get_type(self->mydb)) {
689 case -1:
690 retval = NULL;
691 break;
692
693 case DB_RECNO:
694 case DB_QUEUE:
695 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
696 data.data, data.size);
697 break;
698 case DB_HASH:
699 case DB_BTREE:
700 default:
701 retval = Py_BuildValue("s#s#", key.data, key.size,
702 data.data, data.size);
703 break;
704 }
705 }
706 if (!err) {
707 FREE_DBT(key);
708 FREE_DBT(data);
709 }
710 return retval;
711}
712
713
714/* add an integer to a dictionary using the given name as a key */
715static void _addIntToDict(PyObject* dict, char *name, int value)
716{
717 PyObject* v = PyInt_FromLong((long) value);
718 if (!v || PyDict_SetItemString(dict, name, v))
719 PyErr_Clear();
720
721 Py_XDECREF(v);
722}
723
724
725
726
727/* --------------------------------------------------------------------- */
728/* Allocators and deallocators */
729
730static DBObject*
731newDBObject(DBEnvObject* arg, int flags)
732{
733 DBObject* self;
734 DB_ENV* db_env = NULL;
735 int err;
736
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738 if (self == NULL)
739 return NULL;
740
741 self->haveStat = 0;
742 self->flags = 0;
743 self->setflags = 0;
744 self->myenvobj = NULL;
745#if (DBVER >= 33)
746 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000747 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000748 self->primaryDBType = 0;
749#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000750#ifdef HAVE_WEAKREF
751 self->in_weakreflist = NULL;
752#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000753
754 /* keep a reference to our python DBEnv object */
755 if (arg) {
756 Py_INCREF(arg);
757 self->myenvobj = arg;
758 db_env = arg->db_env;
759 }
760
761 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000762 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000764 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
765 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000766
767 MYDB_BEGIN_ALLOW_THREADS;
768 err = db_create(&self->db, db_env, flags);
769 self->db->set_errcall(self->db, _db_errorCallback);
770#if (DBVER >= 33)
771 self->db->app_private = (void*)self;
772#endif
773 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000774 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
775 * list so that a DBEnv can refuse to close without aborting any open
776 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (makeDBError(err)) {
778 if (self->myenvobj) {
779 Py_DECREF(self->myenvobj);
780 self->myenvobj = NULL;
781 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000782 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 self = NULL;
784 }
785 return self;
786}
787
788
789static void
790DB_dealloc(DBObject* self)
791{
792 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000793 /* avoid closing a DB when its DBEnv has been closed out from under
794 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000796 (self->myenvobj && self->myenvobj->db_env))
797 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000798 MYDB_BEGIN_ALLOW_THREADS;
799 self->db->close(self->db, 0);
800 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000801#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802 } else {
803 PyErr_Warn(PyExc_RuntimeWarning,
804 "DB could not be closed in destructor: DBEnv already closed");
805#endif
806 }
807 self->db = NULL;
808 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000809#ifdef HAVE_WEAKREF
810 if (self->in_weakreflist != NULL) {
811 PyObject_ClearWeakRefs((PyObject *) self);
812 }
813#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 if (self->myenvobj) {
815 Py_DECREF(self->myenvobj);
816 self->myenvobj = NULL;
817 }
818#if (DBVER >= 33)
819 if (self->associateCallback != NULL) {
820 Py_DECREF(self->associateCallback);
821 self->associateCallback = NULL;
822 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000823 if (self->btCompareCallback != NULL) {
824 Py_DECREF(self->btCompareCallback);
825 self->btCompareCallback = NULL;
826 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000829}
830
831
832static DBCursorObject*
833newDBCursorObject(DBC* dbc, DBObject* db)
834{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000835 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (self == NULL)
837 return NULL;
838
839 self->dbc = dbc;
840 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000841#ifdef HAVE_WEAKREF
842 self->in_weakreflist = NULL;
843#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000844 Py_INCREF(self->mydb);
845 return self;
846}
847
848
849static void
850DBCursor_dealloc(DBCursorObject* self)
851{
852 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000853
854#ifdef HAVE_WEAKREF
855 if (self->in_weakreflist != NULL) {
856 PyObject_ClearWeakRefs((PyObject *) self);
857 }
858#endif
859
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860 if (self->dbc != NULL) {
861 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000862 /* If the underlying database has been closed, we don't
863 need to do anything. If the environment has been closed
864 we need to leak, as BerkeleyDB will crash trying to access
865 the environment. There was an exception when the
866 user closed the environment even though there still was
867 a database open. */
868 if (self->mydb->db && self->mydb->myenvobj &&
869 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000870 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000871 self->dbc = NULL;
872 MYDB_END_ALLOW_THREADS;
873 }
874 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876}
877
878
879static DBEnvObject*
880newDBEnvObject(int flags)
881{
882 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000883 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000884 if (self == NULL)
885 return NULL;
886
887 self->closed = 1;
888 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000889 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
890 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000891#ifdef HAVE_WEAKREF
892 self->in_weakreflist = NULL;
893#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894
895 MYDB_BEGIN_ALLOW_THREADS;
896 err = db_env_create(&self->db_env, flags);
897 MYDB_END_ALLOW_THREADS;
898 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000899 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000900 self = NULL;
901 }
902 else {
903 self->db_env->set_errcall(self->db_env, _db_errorCallback);
904 }
905 return self;
906}
907
908
909static void
910DBEnv_dealloc(DBEnvObject* self)
911{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000912#ifdef HAVE_WEAKREF
913 if (self->in_weakreflist != NULL) {
914 PyObject_ClearWeakRefs((PyObject *) self);
915 }
916#endif
917
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000918 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919 MYDB_BEGIN_ALLOW_THREADS;
920 self->db_env->close(self->db_env, 0);
921 MYDB_END_ALLOW_THREADS;
922 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000923 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924}
925
926
927static DBTxnObject*
928newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
929{
930 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000931 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 if (self == NULL)
933 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000934 Py_INCREF(myenv);
935 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000936#ifdef HAVE_WEAKREF
937 self->in_weakreflist = NULL;
938#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939
940 MYDB_BEGIN_ALLOW_THREADS;
941#if (DBVER >= 40)
942 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
943#else
944 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
945#endif
946 MYDB_END_ALLOW_THREADS;
947 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000948 Py_DECREF(self->env);
949 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000950 self = NULL;
951 }
952 return self;
953}
954
955
956static void
957DBTxn_dealloc(DBTxnObject* self)
958{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000959#ifdef HAVE_WEAKREF
960 if (self->in_weakreflist != NULL) {
961 PyObject_ClearWeakRefs((PyObject *) self);
962 }
963#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964
Gregory P. Smith31c50652004-06-28 01:20:40 +0000965#ifdef HAVE_WARNINGS
966 if (self->txn) {
967 /* it hasn't been finalized, abort it! */
968 MYDB_BEGIN_ALLOW_THREADS;
969#if (DBVER >= 40)
970 self->txn->abort(self->txn);
971#else
972 txn_abort(self->txn);
973#endif
974 MYDB_END_ALLOW_THREADS;
975 PyErr_Warn(PyExc_RuntimeWarning,
976 "DBTxn aborted in destructor. No prior commit() or abort().");
977 }
978#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979
Neal Norwitz62a21122006-01-25 05:21:55 +0000980 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000981 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982}
983
984
985static DBLockObject*
986newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
987 db_lockmode_t lock_mode, int flags)
988{
989 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000990 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 if (self == NULL)
992 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000993#ifdef HAVE_WEAKREF
994 self->in_weakreflist = NULL;
995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996
997 MYDB_BEGIN_ALLOW_THREADS;
998#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000999 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1000 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001001#else
1002 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1003#endif
1004 MYDB_END_ALLOW_THREADS;
1005 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001006 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001007 self = NULL;
1008 }
1009
1010 return self;
1011}
1012
1013
1014static void
1015DBLock_dealloc(DBLockObject* self)
1016{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001017#ifdef HAVE_WEAKREF
1018 if (self->in_weakreflist != NULL) {
1019 PyObject_ClearWeakRefs((PyObject *) self);
1020 }
1021#endif
1022 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025}
1026
1027
1028/* --------------------------------------------------------------------- */
1029/* DB methods */
1030
1031static PyObject*
1032DB_append(DBObject* self, PyObject* args)
1033{
1034 PyObject* txnobj = NULL;
1035 PyObject* dataobj;
1036 db_recno_t recno;
1037 DBT key, data;
1038 DB_TXN *txn = NULL;
1039
1040 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1041 return NULL;
1042
1043 CHECK_DB_NOT_CLOSED(self);
1044
1045 /* make a dummy key out of a recno */
1046 recno = 0;
1047 CLEAR_DBT(key);
1048 key.data = &recno;
1049 key.size = sizeof(recno);
1050 key.ulen = key.size;
1051 key.flags = DB_DBT_USERMEM;
1052
1053 if (!make_dbt(dataobj, &data)) return NULL;
1054 if (!checkTxnObj(txnobj, &txn)) return NULL;
1055
1056 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1057 return NULL;
1058
1059 return PyInt_FromLong(recno);
1060}
1061
1062
1063#if (DBVER >= 33)
1064
1065static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001066_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1067 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001068{
1069 int retval = DB_DONOTINDEX;
1070 DBObject* secondaryDB = (DBObject*)db->app_private;
1071 PyObject* callback = secondaryDB->associateCallback;
1072 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001073 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001074 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001075
1076
1077 if (callback != NULL) {
1078 MYDB_BEGIN_BLOCK_THREADS;
1079
Thomas Woutersb3153832006-03-08 01:47:19 +00001080 if (type == DB_RECNO || type == DB_QUEUE)
1081 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1082 priData->data, priData->size);
1083 else
1084 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1085 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001086 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001087 result = PyEval_CallObject(callback, args);
1088 }
1089 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001090 PyErr_Print();
1091 }
1092 else if (result == Py_None) {
1093 retval = DB_DONOTINDEX;
1094 }
1095 else if (PyInt_Check(result)) {
1096 retval = PyInt_AsLong(result);
1097 }
1098 else if (PyString_Check(result)) {
1099 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001100 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001101
1102 CLEAR_DBT(*secKey);
1103#if PYTHON_API_VERSION <= 1007
1104 /* 1.5 compatibility */
1105 size = PyString_Size(result);
1106 data = PyString_AsString(result);
1107#else
1108 PyString_AsStringAndSize(result, &data, &size);
1109#endif
1110 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1111 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001112 if (secKey->data) {
1113 memcpy(secKey->data, data, size);
1114 secKey->size = size;
1115 retval = 0;
1116 }
1117 else {
1118 PyErr_SetString(PyExc_MemoryError,
1119 "malloc failed in _db_associateCallback");
1120 PyErr_Print();
1121 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001122 }
1123 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001124 PyErr_SetString(
1125 PyExc_TypeError,
1126 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 PyErr_Print();
1128 }
1129
Thomas Woutersb3153832006-03-08 01:47:19 +00001130 Py_XDECREF(args);
1131 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132
1133 MYDB_END_BLOCK_THREADS;
1134 }
1135 return retval;
1136}
1137
1138
1139static PyObject*
1140DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1141{
1142 int err, flags=0;
1143 DBObject* secondaryDB;
1144 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001145#if (DBVER >= 41)
1146 PyObject *txnobj = NULL;
1147 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001148 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001149 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001150#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001151 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001152#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001153
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001154#if (DBVER >= 41)
1155 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1156 &secondaryDB, &callback, &flags,
1157 &txnobj)) {
1158#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001159 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001160 &secondaryDB, &callback, &flags)) {
1161#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001162 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001163 }
1164
1165#if (DBVER >= 41)
1166 if (!checkTxnObj(txnobj, &txn)) return NULL;
1167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001168
1169 CHECK_DB_NOT_CLOSED(self);
1170 if (!DBObject_Check(secondaryDB)) {
1171 makeTypeError("DB", (PyObject*)secondaryDB);
1172 return NULL;
1173 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001174 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 if (callback == Py_None) {
1176 callback = NULL;
1177 }
1178 else if (!PyCallable_Check(callback)) {
1179 makeTypeError("Callable", callback);
1180 return NULL;
1181 }
1182
1183 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001184 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001185 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001186 secondaryDB->associateCallback = callback;
1187 secondaryDB->primaryDBType = _DB_get_type(self);
1188
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001189 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1190 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1191 * The global interepreter lock is not initialized until the first
1192 * thread is created using thread.start_new_thread() or fork() is
1193 * called. that would cause the ALLOW_THREADS here to segfault due
1194 * to a null pointer reference if no threads or child processes
1195 * have been created. This works around that and is a no-op if
1196 * threads have already been initialized.
1197 * (see pybsddb-users mailing list post on 2002-08-07)
1198 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001199#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001200 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001201#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001202 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001203#if (DBVER >= 41)
1204 err = self->db->associate(self->db,
1205 txn,
1206 secondaryDB->db,
1207 _db_associateCallback,
1208 flags);
1209#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 err = self->db->associate(self->db,
1211 secondaryDB->db,
1212 _db_associateCallback,
1213 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001214#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001215 MYDB_END_ALLOW_THREADS;
1216
1217 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001218 Py_XDECREF(secondaryDB->associateCallback);
1219 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001220 secondaryDB->primaryDBType = 0;
1221 }
1222
1223 RETURN_IF_ERR();
1224 RETURN_NONE();
1225}
1226
1227
1228#endif
1229
1230
1231static PyObject*
1232DB_close(DBObject* self, PyObject* args)
1233{
1234 int err, flags=0;
1235 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1236 return NULL;
1237 if (self->db != NULL) {
1238 if (self->myenvobj)
1239 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001240 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241 self->db = NULL;
1242 RETURN_IF_ERR();
1243 }
1244 RETURN_NONE();
1245}
1246
1247
1248#if (DBVER >= 32)
1249static PyObject*
1250_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1251{
1252 int err, flags=0, type;
1253 PyObject* txnobj = NULL;
1254 PyObject* retval = NULL;
1255 DBT key, data;
1256 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001257 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258
1259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1260 &txnobj, &flags))
1261 return NULL;
1262
1263 CHECK_DB_NOT_CLOSED(self);
1264 type = _DB_get_type(self);
1265 if (type == -1)
1266 return NULL;
1267 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001268 PyErr_SetString(PyExc_TypeError,
1269 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001270 return NULL;
1271 }
1272 if (!checkTxnObj(txnobj, &txn))
1273 return NULL;
1274
1275 CLEAR_DBT(key);
1276 CLEAR_DBT(data);
1277 if (CHECK_DBFLAG(self, DB_THREAD)) {
1278 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1279 data.flags = DB_DBT_MALLOC;
1280 key.flags = DB_DBT_MALLOC;
1281 }
1282
1283 MYDB_BEGIN_ALLOW_THREADS;
1284 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1285 MYDB_END_ALLOW_THREADS;
1286
Gregory P. Smithe9477062005-06-04 06:46:59 +00001287 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1288 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289 err = 0;
1290 Py_INCREF(Py_None);
1291 retval = Py_None;
1292 }
1293 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001294 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1295 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001296 FREE_DBT(key);
1297 FREE_DBT(data);
1298 }
1299
1300 RETURN_IF_ERR();
1301 return retval;
1302}
1303
1304static PyObject*
1305DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1306{
1307 return _DB_consume(self, args, kwargs, DB_CONSUME);
1308}
1309
1310static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001311DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1312 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001313{
1314 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1315}
1316#endif
1317
1318
1319
1320static PyObject*
1321DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1322{
1323 int err, flags=0;
1324 DBC* dbc;
1325 PyObject* txnobj = NULL;
1326 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001327 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001328
1329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1330 &txnobj, &flags))
1331 return NULL;
1332 CHECK_DB_NOT_CLOSED(self);
1333 if (!checkTxnObj(txnobj, &txn))
1334 return NULL;
1335
1336 MYDB_BEGIN_ALLOW_THREADS;
1337 err = self->db->cursor(self->db, txn, &dbc, flags);
1338 MYDB_END_ALLOW_THREADS;
1339 RETURN_IF_ERR();
1340 return (PyObject*) newDBCursorObject(dbc, self);
1341}
1342
1343
1344static PyObject*
1345DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1346{
1347 PyObject* txnobj = NULL;
1348 int flags = 0;
1349 PyObject* keyobj;
1350 DBT key;
1351 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001352 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001353
1354 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1355 &keyobj, &txnobj, &flags))
1356 return NULL;
1357 CHECK_DB_NOT_CLOSED(self);
1358 if (!make_key_dbt(self, keyobj, &key, NULL))
1359 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001360 if (!checkTxnObj(txnobj, &txn)) {
1361 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001363 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001365 if (-1 == _DB_delete(self, txn, &key, 0)) {
1366 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001367 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001368 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369
1370 FREE_DBT(key);
1371 RETURN_NONE();
1372}
1373
1374
1375static PyObject*
1376DB_fd(DBObject* self, PyObject* args)
1377{
1378 int err, the_fd;
1379
1380 if (!PyArg_ParseTuple(args,":fd"))
1381 return NULL;
1382 CHECK_DB_NOT_CLOSED(self);
1383
1384 MYDB_BEGIN_ALLOW_THREADS;
1385 err = self->db->fd(self->db, &the_fd);
1386 MYDB_END_ALLOW_THREADS;
1387 RETURN_IF_ERR();
1388 return PyInt_FromLong(the_fd);
1389}
1390
1391
1392static PyObject*
1393DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1394{
1395 int err, flags=0;
1396 PyObject* txnobj = NULL;
1397 PyObject* keyobj;
1398 PyObject* dfltobj = NULL;
1399 PyObject* retval = NULL;
1400 int dlen = -1;
1401 int doff = -1;
1402 DBT key, data;
1403 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001404 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001405 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001406
1407 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001408 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1409 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410 return NULL;
1411
1412 CHECK_DB_NOT_CLOSED(self);
1413 if (!make_key_dbt(self, keyobj, &key, &flags))
1414 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001415 if (!checkTxnObj(txnobj, &txn)) {
1416 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001417 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419
1420 CLEAR_DBT(data);
1421 if (CHECK_DBFLAG(self, DB_THREAD)) {
1422 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1423 data.flags = DB_DBT_MALLOC;
1424 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001425 if (!add_partial_dbt(&data, dlen, doff)) {
1426 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001428 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 MYDB_BEGIN_ALLOW_THREADS;
1431 err = self->db->get(self->db, txn, &key, &data, flags);
1432 MYDB_END_ALLOW_THREADS;
1433
Gregory P. Smithe9477062005-06-04 06:46:59 +00001434 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435 err = 0;
1436 Py_INCREF(dfltobj);
1437 retval = dfltobj;
1438 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001439 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1440 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441 err = 0;
1442 Py_INCREF(Py_None);
1443 retval = Py_None;
1444 }
1445 else if (!err) {
1446 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001447 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1448 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001449 else /* return just the data */
1450 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001451 FREE_DBT(data);
1452 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001453 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454
1455 RETURN_IF_ERR();
1456 return retval;
1457}
1458
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001459#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001460static PyObject*
1461DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1462{
1463 int err, flags=0;
1464 PyObject* txnobj = NULL;
1465 PyObject* keyobj;
1466 PyObject* dfltobj = NULL;
1467 PyObject* retval = NULL;
1468 int dlen = -1;
1469 int doff = -1;
1470 DBT key, pkey, data;
1471 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001472 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001473 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001474
1475 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1476 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1477 &doff))
1478 return NULL;
1479
1480 CHECK_DB_NOT_CLOSED(self);
1481 if (!make_key_dbt(self, keyobj, &key, &flags))
1482 return NULL;
1483 if (!checkTxnObj(txnobj, &txn)) {
1484 FREE_DBT(key);
1485 return NULL;
1486 }
1487
1488 CLEAR_DBT(data);
1489 if (CHECK_DBFLAG(self, DB_THREAD)) {
1490 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1491 data.flags = DB_DBT_MALLOC;
1492 }
1493 if (!add_partial_dbt(&data, dlen, doff)) {
1494 FREE_DBT(key);
1495 return NULL;
1496 }
1497
1498 CLEAR_DBT(pkey);
1499 pkey.flags = DB_DBT_MALLOC;
1500
1501 MYDB_BEGIN_ALLOW_THREADS;
1502 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1503 MYDB_END_ALLOW_THREADS;
1504
Gregory P. Smithe9477062005-06-04 06:46:59 +00001505 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001506 err = 0;
1507 Py_INCREF(dfltobj);
1508 retval = dfltobj;
1509 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001510 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1511 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001512 err = 0;
1513 Py_INCREF(Py_None);
1514 retval = Py_None;
1515 }
1516 else if (!err) {
1517 PyObject *pkeyObj;
1518 PyObject *dataObj;
1519 dataObj = PyString_FromStringAndSize(data.data, data.size);
1520
1521 if (self->primaryDBType == DB_RECNO ||
1522 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001523 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001524 else
1525 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1526
1527 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1528 {
1529 PyObject *keyObj;
1530 int type = _DB_get_type(self);
1531 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001532 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001533 else
1534 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001535#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001536 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001537#else
1538 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1539#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001540 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001541 }
1542 else /* return just the pkey and data */
1543 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001544#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001545 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001546#else
1547 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1548#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001549 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001550 Py_DECREF(dataObj);
1551 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001552 FREE_DBT(pkey);
1553 FREE_DBT(data);
1554 }
1555 FREE_DBT(key);
1556
1557 RETURN_IF_ERR();
1558 return retval;
1559}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001560#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001561
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001562
1563/* Return size of entry */
1564static PyObject*
1565DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1566{
1567 int err, flags=0;
1568 PyObject* txnobj = NULL;
1569 PyObject* keyobj;
1570 PyObject* retval = NULL;
1571 DBT key, data;
1572 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001573 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001574
1575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1576 &keyobj, &txnobj))
1577 return NULL;
1578 CHECK_DB_NOT_CLOSED(self);
1579 if (!make_key_dbt(self, keyobj, &key, &flags))
1580 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001581 if (!checkTxnObj(txnobj, &txn)) {
1582 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001583 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001584 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001585 CLEAR_DBT(data);
1586
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001587 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1588 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589 data.flags = DB_DBT_USERMEM;
1590 data.ulen = 0;
1591 MYDB_BEGIN_ALLOW_THREADS;
1592 err = self->db->get(self->db, txn, &key, &data, flags);
1593 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001594 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001595 retval = PyInt_FromLong((long)data.size);
1596 err = 0;
1597 }
1598
1599 FREE_DBT(key);
1600 FREE_DBT(data);
1601 RETURN_IF_ERR();
1602 return retval;
1603}
1604
1605
1606static PyObject*
1607DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1608{
1609 int err, flags=0;
1610 PyObject* txnobj = NULL;
1611 PyObject* keyobj;
1612 PyObject* dataobj;
1613 PyObject* retval = NULL;
1614 DBT key, data;
1615 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001616 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617
1618
1619 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1620 &keyobj, &dataobj, &txnobj, &flags))
1621 return NULL;
1622
1623 CHECK_DB_NOT_CLOSED(self);
1624 if (!make_key_dbt(self, keyobj, &key, NULL))
1625 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001626 if ( !make_dbt(dataobj, &data) ||
1627 !checkTxnObj(txnobj, &txn) )
1628 {
1629 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001630 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001631 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001632
1633 flags |= DB_GET_BOTH;
1634
1635 if (CHECK_DBFLAG(self, DB_THREAD)) {
1636 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1637 data.flags = DB_DBT_MALLOC;
1638 /* TODO: Is this flag needed? We're passing a data object that should
1639 match what's in the DB, so there should be no need to malloc.
1640 We run the risk of freeing something twice! Check this. */
1641 }
1642
1643 MYDB_BEGIN_ALLOW_THREADS;
1644 err = self->db->get(self->db, txn, &key, &data, flags);
1645 MYDB_END_ALLOW_THREADS;
1646
Gregory P. Smithe9477062005-06-04 06:46:59 +00001647 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1648 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649 err = 0;
1650 Py_INCREF(Py_None);
1651 retval = Py_None;
1652 }
1653 else if (!err) {
1654 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1655 FREE_DBT(data); /* Only if retrieval was successful */
1656 }
1657
1658 FREE_DBT(key);
1659 RETURN_IF_ERR();
1660 return retval;
1661}
1662
1663
1664static PyObject*
1665DB_get_byteswapped(DBObject* self, PyObject* args)
1666{
1667#if (DBVER >= 33)
1668 int err = 0;
1669#endif
1670 int retval = -1;
1671
1672 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1673 return NULL;
1674 CHECK_DB_NOT_CLOSED(self);
1675
1676#if (DBVER >= 33)
1677 MYDB_BEGIN_ALLOW_THREADS;
1678 err = self->db->get_byteswapped(self->db, &retval);
1679 MYDB_END_ALLOW_THREADS;
1680 RETURN_IF_ERR();
1681#else
1682 MYDB_BEGIN_ALLOW_THREADS;
1683 retval = self->db->get_byteswapped(self->db);
1684 MYDB_END_ALLOW_THREADS;
1685#endif
1686 return PyInt_FromLong(retval);
1687}
1688
1689
1690static PyObject*
1691DB_get_type(DBObject* self, PyObject* args)
1692{
1693 int type;
1694
1695 if (!PyArg_ParseTuple(args,":get_type"))
1696 return NULL;
1697 CHECK_DB_NOT_CLOSED(self);
1698
1699 MYDB_BEGIN_ALLOW_THREADS;
1700 type = _DB_get_type(self);
1701 MYDB_END_ALLOW_THREADS;
1702 if (type == -1)
1703 return NULL;
1704 return PyInt_FromLong(type);
1705}
1706
1707
1708static PyObject*
1709DB_join(DBObject* self, PyObject* args)
1710{
1711 int err, flags=0;
1712 int length, x;
1713 PyObject* cursorsObj;
1714 DBC** cursors;
1715 DBC* dbc;
1716
1717
1718 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1719 return NULL;
1720
1721 CHECK_DB_NOT_CLOSED(self);
1722
1723 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001724 PyErr_SetString(PyExc_TypeError,
1725 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001726 return NULL;
1727 }
1728
1729 length = PyObject_Length(cursorsObj);
1730 cursors = malloc((length+1) * sizeof(DBC*));
1731 cursors[length] = NULL;
1732 for (x=0; x<length; x++) {
1733 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001734 if (item == NULL) {
1735 free(cursors);
1736 return NULL;
1737 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001738 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001739 PyErr_SetString(PyExc_TypeError,
1740 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001741 free(cursors);
1742 return NULL;
1743 }
1744 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001745 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746 }
1747
1748 MYDB_BEGIN_ALLOW_THREADS;
1749 err = self->db->join(self->db, cursors, &dbc, flags);
1750 MYDB_END_ALLOW_THREADS;
1751 free(cursors);
1752 RETURN_IF_ERR();
1753
Gregory P. Smith7441e652003-11-03 21:35:31 +00001754 /* FIXME: this is a buggy interface. The returned cursor
1755 contains internal references to the passed in cursors
1756 but does not hold python references to them or prevent
1757 them from being closed prematurely. This can cause
1758 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001759 return (PyObject*) newDBCursorObject(dbc, self);
1760}
1761
1762
1763static PyObject*
1764DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1765{
1766 int err, flags=0;
1767 PyObject* txnobj = NULL;
1768 PyObject* keyobj;
1769 DBT key;
1770 DB_TXN *txn = NULL;
1771 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001772 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001773
1774 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1775 &keyobj, &txnobj, &flags))
1776 return NULL;
1777 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001778 if (!make_dbt(keyobj, &key))
1779 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001780 return NULL;
1781 if (!checkTxnObj(txnobj, &txn))
1782 return NULL;
1783
1784 MYDB_BEGIN_ALLOW_THREADS;
1785 err = self->db->key_range(self->db, txn, &key, &range, flags);
1786 MYDB_END_ALLOW_THREADS;
1787
1788 RETURN_IF_ERR();
1789 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1790}
1791
1792
1793static PyObject*
1794DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1795{
1796 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1797 char* filename = NULL;
1798 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001799#if (DBVER >= 41)
1800 PyObject *txnobj = NULL;
1801 DB_TXN *txn = NULL;
1802 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001803 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001804 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1805 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001806 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001807 "filename", "dbtype", "flags", "mode", "txn", NULL};
1808#else
1809 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001810 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001811 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1812 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001813 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001814 "filename", "dbtype", "flags", "mode", NULL};
1815#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001817#if (DBVER >= 41)
1818 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1819 &filename, &dbname, &type, &flags, &mode,
1820 &txnobj))
1821#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001822 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001823 &filename, &dbname, &type, &flags,
1824 &mode))
1825#endif
1826 {
1827 PyErr_Clear();
1828 type = DB_UNKNOWN; flags = 0; mode = 0660;
1829 filename = NULL; dbname = NULL;
1830#if (DBVER >= 41)
1831 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1832 kwnames_basic,
1833 &filename, &type, &flags, &mode,
1834 &txnobj))
1835 return NULL;
1836#else
1837 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1838 kwnames_basic,
1839 &filename, &type, &flags, &mode))
1840 return NULL;
1841#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 }
1843
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001844#if (DBVER >= 41)
1845 if (!checkTxnObj(txnobj, &txn)) return NULL;
1846#endif
1847
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001849 PyObject *t = Py_BuildValue("(is)", 0,
1850 "Cannot call open() twice for DB object");
1851 PyErr_SetObject(DBError, t);
1852 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 return NULL;
1854 }
1855
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001856#if 0 && (DBVER >= 41)
1857 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1858 && (self->myenvobj->flags & DB_INIT_TXN))
1859 {
1860 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1861 * explicitly passed) but we are in a transaction ready environment:
1862 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1863 * to work on BerkeleyDB 4.1 without needing to modify their
1864 * DBEnv or DB open calls.
1865 * TODO make this behaviour of the library configurable.
1866 */
1867 flags |= DB_AUTO_COMMIT;
1868 }
1869#endif
1870
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001871 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001872#if (DBVER >= 41)
1873 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1874#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001876#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001877 MYDB_END_ALLOW_THREADS;
1878 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001879 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001880 self->db = NULL;
1881 return NULL;
1882 }
1883
1884 self->flags = flags;
1885 RETURN_NONE();
1886}
1887
1888
1889static PyObject*
1890DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1891{
1892 int flags=0;
1893 PyObject* txnobj = NULL;
1894 int dlen = -1;
1895 int doff = -1;
1896 PyObject* keyobj, *dataobj, *retval;
1897 DBT key, data;
1898 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001899 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001900 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001901
1902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1903 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1904 return NULL;
1905
1906 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001907 if (!make_key_dbt(self, keyobj, &key, NULL))
1908 return NULL;
1909 if ( !make_dbt(dataobj, &data) ||
1910 !add_partial_dbt(&data, dlen, doff) ||
1911 !checkTxnObj(txnobj, &txn) )
1912 {
1913 FREE_DBT(key);
1914 return NULL;
1915 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916
1917 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1918 FREE_DBT(key);
1919 return NULL;
1920 }
1921
1922 if (flags & DB_APPEND)
1923 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1924 else {
1925 retval = Py_None;
1926 Py_INCREF(retval);
1927 }
1928 FREE_DBT(key);
1929 return retval;
1930}
1931
1932
1933
1934static PyObject*
1935DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1936{
1937 char* filename;
1938 char* database = NULL;
1939 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001940 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001941
1942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1943 &filename, &database, &flags))
1944 return NULL;
1945 CHECK_DB_NOT_CLOSED(self);
1946
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001948 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 RETURN_IF_ERR();
1950 RETURN_NONE();
1951}
1952
1953
1954
1955static PyObject*
1956DB_rename(DBObject* self, PyObject* args)
1957{
1958 char* filename;
1959 char* database;
1960 char* newname;
1961 int err, flags=0;
1962
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001963 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1964 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 return NULL;
1966 CHECK_DB_NOT_CLOSED(self);
1967
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->rename(self->db, filename, database, newname, flags);
1970 MYDB_END_ALLOW_THREADS;
1971 RETURN_IF_ERR();
1972 RETURN_NONE();
1973}
1974
1975
1976static PyObject*
1977DB_set_bt_minkey(DBObject* self, PyObject* args)
1978{
1979 int err, minkey;
1980
1981 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1982 return NULL;
1983 CHECK_DB_NOT_CLOSED(self);
1984
1985 MYDB_BEGIN_ALLOW_THREADS;
1986 err = self->db->set_bt_minkey(self->db, minkey);
1987 MYDB_END_ALLOW_THREADS;
1988 RETURN_IF_ERR();
1989 RETURN_NONE();
1990}
1991
Neal Norwitz84562352005-10-20 04:30:15 +00001992#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001993static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001994_default_cmp(const DBT *leftKey,
1995 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001996{
1997 int res;
1998 int lsize = leftKey->size, rsize = rightKey->size;
1999
Georg Brandlef1701f2006-03-07 14:57:48 +00002000 res = memcmp(leftKey->data, rightKey->data,
2001 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002002
2003 if (res == 0) {
2004 if (lsize < rsize) {
2005 res = -1;
2006 }
2007 else if (lsize > rsize) {
2008 res = 1;
2009 }
2010 }
2011 return res;
2012}
2013
2014static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002015_db_compareCallback(DB* db,
2016 const DBT *leftKey,
2017 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002018{
2019 int res = 0;
2020 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002021 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002022 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002023
2024 if (self == NULL || self->btCompareCallback == NULL) {
2025 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002026 PyErr_SetString(PyExc_TypeError,
2027 (self == 0
2028 ? "DB_bt_compare db is NULL."
2029 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002030 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002031 PyErr_Print();
2032 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002033 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002034 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002035 MYDB_BEGIN_BLOCK_THREADS;
2036
Thomas Woutersb3153832006-03-08 01:47:19 +00002037 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2038 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002039 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002040 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002041 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002042 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002043 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002044 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002045 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002046 PyErr_Print();
2047 res = _default_cmp(leftKey, rightKey);
2048 } else if (PyInt_Check(result)) {
2049 res = PyInt_AsLong(result);
2050 } else {
2051 PyErr_SetString(PyExc_TypeError,
2052 "DB_bt_compare callback MUST return an int.");
2053 /* we're in a callback within the DB code, we can't raise */
2054 PyErr_Print();
2055 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002056 }
2057
Thomas Woutersb3153832006-03-08 01:47:19 +00002058 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002059 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002060
2061 MYDB_END_BLOCK_THREADS;
2062 }
2063 return res;
2064}
2065
2066static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002067DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002068{
2069 int err;
2070 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002071 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002072
Georg Brandlef1701f2006-03-07 14:57:48 +00002073 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002074 return NULL;
2075
Georg Brandlef1701f2006-03-07 14:57:48 +00002076 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077
Georg Brandlef1701f2006-03-07 14:57:48 +00002078 if (!PyCallable_Check(comparator)) {
2079 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080 return NULL;
2081 }
2082
2083 /*
2084 * Perform a test call of the comparator function with two empty
2085 * string objects here. verify that it returns an int (0).
2086 * err if not.
2087 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002088 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002089 result = PyEval_CallObject(comparator, tuple);
2090 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002091 if (result == NULL)
2092 return NULL;
2093 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002094 PyErr_SetString(PyExc_TypeError,
2095 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002097 } else if (PyInt_AsLong(result) != 0) {
2098 PyErr_SetString(PyExc_TypeError,
2099 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100 return NULL;
2101 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002102 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103
2104 /* We don't accept multiple set_bt_compare operations, in order to
2105 * simplify the code. This would have no real use, as one cannot
2106 * change the function once the db is opened anyway */
2107 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109 return NULL;
2110 }
2111
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002113 self->btCompareCallback = comparator;
2114
2115 /* This is to workaround a problem with un-initialized threads (see
2116 comment in DB_associate) */
2117#ifdef WITH_THREAD
2118 PyEval_InitThreads();
2119#endif
2120
Thomas Woutersb3153832006-03-08 01:47:19 +00002121 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122
2123 if (err) {
2124 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126 self->btCompareCallback = NULL;
2127 }
2128
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 RETURN_IF_ERR();
2130 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131}
Neal Norwitz84562352005-10-20 04:30:15 +00002132#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002133
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002134
2135static PyObject*
2136DB_set_cachesize(DBObject* self, PyObject* args)
2137{
2138 int err;
2139 int gbytes = 0, bytes = 0, ncache = 0;
2140
2141 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2142 &gbytes,&bytes,&ncache))
2143 return NULL;
2144 CHECK_DB_NOT_CLOSED(self);
2145
2146 MYDB_BEGIN_ALLOW_THREADS;
2147 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2148 MYDB_END_ALLOW_THREADS;
2149 RETURN_IF_ERR();
2150 RETURN_NONE();
2151}
2152
2153
2154static PyObject*
2155DB_set_flags(DBObject* self, PyObject* args)
2156{
2157 int err, flags;
2158
2159 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2160 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2162
2163 MYDB_BEGIN_ALLOW_THREADS;
2164 err = self->db->set_flags(self->db, flags);
2165 MYDB_END_ALLOW_THREADS;
2166 RETURN_IF_ERR();
2167
2168 self->setflags |= flags;
2169 RETURN_NONE();
2170}
2171
2172
2173static PyObject*
2174DB_set_h_ffactor(DBObject* self, PyObject* args)
2175{
2176 int err, ffactor;
2177
2178 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2179 return NULL;
2180 CHECK_DB_NOT_CLOSED(self);
2181
2182 MYDB_BEGIN_ALLOW_THREADS;
2183 err = self->db->set_h_ffactor(self->db, ffactor);
2184 MYDB_END_ALLOW_THREADS;
2185 RETURN_IF_ERR();
2186 RETURN_NONE();
2187}
2188
2189
2190static PyObject*
2191DB_set_h_nelem(DBObject* self, PyObject* args)
2192{
2193 int err, nelem;
2194
2195 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2196 return NULL;
2197 CHECK_DB_NOT_CLOSED(self);
2198
2199 MYDB_BEGIN_ALLOW_THREADS;
2200 err = self->db->set_h_nelem(self->db, nelem);
2201 MYDB_END_ALLOW_THREADS;
2202 RETURN_IF_ERR();
2203 RETURN_NONE();
2204}
2205
2206
2207static PyObject*
2208DB_set_lorder(DBObject* self, PyObject* args)
2209{
2210 int err, lorder;
2211
2212 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2213 return NULL;
2214 CHECK_DB_NOT_CLOSED(self);
2215
2216 MYDB_BEGIN_ALLOW_THREADS;
2217 err = self->db->set_lorder(self->db, lorder);
2218 MYDB_END_ALLOW_THREADS;
2219 RETURN_IF_ERR();
2220 RETURN_NONE();
2221}
2222
2223
2224static PyObject*
2225DB_set_pagesize(DBObject* self, PyObject* args)
2226{
2227 int err, pagesize;
2228
2229 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2230 return NULL;
2231 CHECK_DB_NOT_CLOSED(self);
2232
2233 MYDB_BEGIN_ALLOW_THREADS;
2234 err = self->db->set_pagesize(self->db, pagesize);
2235 MYDB_END_ALLOW_THREADS;
2236 RETURN_IF_ERR();
2237 RETURN_NONE();
2238}
2239
2240
2241static PyObject*
2242DB_set_re_delim(DBObject* self, PyObject* args)
2243{
2244 int err;
2245 char delim;
2246
2247 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2248 PyErr_Clear();
2249 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2250 return NULL;
2251 }
2252
2253 CHECK_DB_NOT_CLOSED(self);
2254
2255 MYDB_BEGIN_ALLOW_THREADS;
2256 err = self->db->set_re_delim(self->db, delim);
2257 MYDB_END_ALLOW_THREADS;
2258 RETURN_IF_ERR();
2259 RETURN_NONE();
2260}
2261
2262static PyObject*
2263DB_set_re_len(DBObject* self, PyObject* args)
2264{
2265 int err, len;
2266
2267 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2268 return NULL;
2269 CHECK_DB_NOT_CLOSED(self);
2270
2271 MYDB_BEGIN_ALLOW_THREADS;
2272 err = self->db->set_re_len(self->db, len);
2273 MYDB_END_ALLOW_THREADS;
2274 RETURN_IF_ERR();
2275 RETURN_NONE();
2276}
2277
2278
2279static PyObject*
2280DB_set_re_pad(DBObject* self, PyObject* args)
2281{
2282 int err;
2283 char pad;
2284
2285 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2286 PyErr_Clear();
2287 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2288 return NULL;
2289 }
2290 CHECK_DB_NOT_CLOSED(self);
2291
2292 MYDB_BEGIN_ALLOW_THREADS;
2293 err = self->db->set_re_pad(self->db, pad);
2294 MYDB_END_ALLOW_THREADS;
2295 RETURN_IF_ERR();
2296 RETURN_NONE();
2297}
2298
2299
2300static PyObject*
2301DB_set_re_source(DBObject* self, PyObject* args)
2302{
2303 int err;
2304 char *re_source;
2305
2306 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2307 return NULL;
2308 CHECK_DB_NOT_CLOSED(self);
2309
2310 MYDB_BEGIN_ALLOW_THREADS;
2311 err = self->db->set_re_source(self->db, re_source);
2312 MYDB_END_ALLOW_THREADS;
2313 RETURN_IF_ERR();
2314 RETURN_NONE();
2315}
2316
2317
2318#if (DBVER >= 32)
2319static PyObject*
2320DB_set_q_extentsize(DBObject* self, PyObject* args)
2321{
2322 int err;
2323 int extentsize;
2324
2325 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2326 return NULL;
2327 CHECK_DB_NOT_CLOSED(self);
2328
2329 MYDB_BEGIN_ALLOW_THREADS;
2330 err = self->db->set_q_extentsize(self->db, extentsize);
2331 MYDB_END_ALLOW_THREADS;
2332 RETURN_IF_ERR();
2333 RETURN_NONE();
2334}
2335#endif
2336
2337static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002338DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002339{
2340 int err, flags = 0, type;
2341 void* sp;
2342 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002343#if (DBVER >= 43)
2344 PyObject* txnobj = NULL;
2345 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002346 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002347#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002348 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002349#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002350
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002351#if (DBVER >= 43)
2352 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2353 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002354 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002355 if (!checkTxnObj(txnobj, &txn))
2356 return NULL;
2357#else
2358 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2359 return NULL;
2360#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002361 CHECK_DB_NOT_CLOSED(self);
2362
2363 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002364#if (DBVER >= 43)
2365 err = self->db->stat(self->db, txn, &sp, flags);
2366#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002367 err = self->db->stat(self->db, &sp, flags);
2368#else
2369 err = self->db->stat(self->db, &sp, NULL, flags);
2370#endif
2371 MYDB_END_ALLOW_THREADS;
2372 RETURN_IF_ERR();
2373
2374 self->haveStat = 1;
2375
2376 /* Turn the stat structure into a dictionary */
2377 type = _DB_get_type(self);
2378 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2379 free(sp);
2380 return NULL;
2381 }
2382
2383#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2384#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2385#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2386
2387 switch (type) {
2388 case DB_HASH:
2389 MAKE_HASH_ENTRY(magic);
2390 MAKE_HASH_ENTRY(version);
2391 MAKE_HASH_ENTRY(nkeys);
2392 MAKE_HASH_ENTRY(ndata);
2393 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002394#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002395 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002396#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002397 MAKE_HASH_ENTRY(ffactor);
2398 MAKE_HASH_ENTRY(buckets);
2399 MAKE_HASH_ENTRY(free);
2400 MAKE_HASH_ENTRY(bfree);
2401 MAKE_HASH_ENTRY(bigpages);
2402 MAKE_HASH_ENTRY(big_bfree);
2403 MAKE_HASH_ENTRY(overflows);
2404 MAKE_HASH_ENTRY(ovfl_free);
2405 MAKE_HASH_ENTRY(dup);
2406 MAKE_HASH_ENTRY(dup_free);
2407 break;
2408
2409 case DB_BTREE:
2410 case DB_RECNO:
2411 MAKE_BT_ENTRY(magic);
2412 MAKE_BT_ENTRY(version);
2413 MAKE_BT_ENTRY(nkeys);
2414 MAKE_BT_ENTRY(ndata);
2415 MAKE_BT_ENTRY(pagesize);
2416 MAKE_BT_ENTRY(minkey);
2417 MAKE_BT_ENTRY(re_len);
2418 MAKE_BT_ENTRY(re_pad);
2419 MAKE_BT_ENTRY(levels);
2420 MAKE_BT_ENTRY(int_pg);
2421 MAKE_BT_ENTRY(leaf_pg);
2422 MAKE_BT_ENTRY(dup_pg);
2423 MAKE_BT_ENTRY(over_pg);
2424 MAKE_BT_ENTRY(free);
2425 MAKE_BT_ENTRY(int_pgfree);
2426 MAKE_BT_ENTRY(leaf_pgfree);
2427 MAKE_BT_ENTRY(dup_pgfree);
2428 MAKE_BT_ENTRY(over_pgfree);
2429 break;
2430
2431 case DB_QUEUE:
2432 MAKE_QUEUE_ENTRY(magic);
2433 MAKE_QUEUE_ENTRY(version);
2434 MAKE_QUEUE_ENTRY(nkeys);
2435 MAKE_QUEUE_ENTRY(ndata);
2436 MAKE_QUEUE_ENTRY(pagesize);
2437 MAKE_QUEUE_ENTRY(pages);
2438 MAKE_QUEUE_ENTRY(re_len);
2439 MAKE_QUEUE_ENTRY(re_pad);
2440 MAKE_QUEUE_ENTRY(pgfree);
2441#if (DBVER == 31)
2442 MAKE_QUEUE_ENTRY(start);
2443#endif
2444 MAKE_QUEUE_ENTRY(first_recno);
2445 MAKE_QUEUE_ENTRY(cur_recno);
2446 break;
2447
2448 default:
2449 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2450 Py_DECREF(d);
2451 d = NULL;
2452 }
2453
2454#undef MAKE_HASH_ENTRY
2455#undef MAKE_BT_ENTRY
2456#undef MAKE_QUEUE_ENTRY
2457
2458 free(sp);
2459 return d;
2460}
2461
2462static PyObject*
2463DB_sync(DBObject* self, PyObject* args)
2464{
2465 int err;
2466 int flags = 0;
2467
2468 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2469 return NULL;
2470 CHECK_DB_NOT_CLOSED(self);
2471
2472 MYDB_BEGIN_ALLOW_THREADS;
2473 err = self->db->sync(self->db, flags);
2474 MYDB_END_ALLOW_THREADS;
2475 RETURN_IF_ERR();
2476 RETURN_NONE();
2477}
2478
2479
2480#if (DBVER >= 33)
2481static PyObject*
2482DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2483{
2484 int err, flags=0;
2485 u_int32_t count=0;
2486 PyObject* txnobj = NULL;
2487 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002488 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002489
2490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2491 &txnobj, &flags))
2492 return NULL;
2493 CHECK_DB_NOT_CLOSED(self);
2494 if (!checkTxnObj(txnobj, &txn))
2495 return NULL;
2496
2497 MYDB_BEGIN_ALLOW_THREADS;
2498 err = self->db->truncate(self->db, txn, &count, flags);
2499 MYDB_END_ALLOW_THREADS;
2500 RETURN_IF_ERR();
2501 return PyInt_FromLong(count);
2502}
2503#endif
2504
2505
2506static PyObject*
2507DB_upgrade(DBObject* self, PyObject* args)
2508{
2509 int err, flags=0;
2510 char *filename;
2511
2512 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2513 return NULL;
2514 CHECK_DB_NOT_CLOSED(self);
2515
2516 MYDB_BEGIN_ALLOW_THREADS;
2517 err = self->db->upgrade(self->db, filename, flags);
2518 MYDB_END_ALLOW_THREADS;
2519 RETURN_IF_ERR();
2520 RETURN_NONE();
2521}
2522
2523
2524static PyObject*
2525DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2526{
2527 int err, flags=0;
2528 char* fileName;
2529 char* dbName=NULL;
2530 char* outFileName=NULL;
2531 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002532 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002533 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002534
2535 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2536 &fileName, &dbName, &outFileName, &flags))
2537 return NULL;
2538
2539 CHECK_DB_NOT_CLOSED(self);
2540 if (outFileName)
2541 outFile = fopen(outFileName, "w");
2542
2543 MYDB_BEGIN_ALLOW_THREADS;
2544 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2545 MYDB_END_ALLOW_THREADS;
2546 if (outFileName)
2547 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002548
2549 /* DB.verify acts as a DB handle destructor (like close); this was
2550 * documented in BerkeleyDB 4.2 but had the undocumented effect
2551 * of not being safe in prior versions while still requiring an explicit
2552 * DB.close call afterwards. Lets call close for the user to emulate
2553 * the safe 4.2 behaviour. */
2554#if (DBVER <= 41)
2555 self->db->close(self->db, 0);
2556#endif
2557 self->db = NULL;
2558
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002559 RETURN_IF_ERR();
2560 RETURN_NONE();
2561}
2562
2563
2564static PyObject*
2565DB_set_get_returns_none(DBObject* self, PyObject* args)
2566{
2567 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002568 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002569
2570 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2571 return NULL;
2572 CHECK_DB_NOT_CLOSED(self);
2573
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002574 if (self->moduleFlags.getReturnsNone)
2575 ++oldValue;
2576 if (self->moduleFlags.cursorSetReturnsNone)
2577 ++oldValue;
2578 self->moduleFlags.getReturnsNone = (flags >= 1);
2579 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002580 return PyInt_FromLong(oldValue);
2581}
2582
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002583#if (DBVER >= 41)
2584static PyObject*
2585DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2586{
2587 int err;
2588 u_int32_t flags=0;
2589 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002590 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002591
2592 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2593 &passwd, &flags)) {
2594 return NULL;
2595 }
2596
2597 MYDB_BEGIN_ALLOW_THREADS;
2598 err = self->db->set_encrypt(self->db, passwd, flags);
2599 MYDB_END_ALLOW_THREADS;
2600
2601 RETURN_IF_ERR();
2602 RETURN_NONE();
2603}
2604#endif /* DBVER >= 41 */
2605
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002606
2607/*-------------------------------------------------------------- */
2608/* Mapping and Dictionary-like access routines */
2609
Martin v. Löwis18e16552006-02-15 17:27:45 +00002610Py_ssize_t DB_length(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002611{
2612 int err;
2613 long size = 0;
2614 int flags = 0;
2615 void* sp;
2616
2617 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002618 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2619 PyErr_SetObject(DBError, t);
2620 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002621 return -1;
2622 }
2623
2624 if (self->haveStat) { /* Has the stat function been called recently? If
2625 so, we can use the cached value. */
2626 flags = DB_CACHED_COUNTS;
2627 }
2628
2629 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002630#if (DBVER >= 43)
2631 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2632#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002633 err = self->db->stat(self->db, &sp, flags);
2634#else
2635 err = self->db->stat(self->db, &sp, NULL, flags);
2636#endif
2637 MYDB_END_ALLOW_THREADS;
2638
2639 if (err)
2640 return -1;
2641
2642 self->haveStat = 1;
2643
2644 /* All the stat structures have matching fields upto the ndata field,
2645 so we can use any of them for the type cast */
2646 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2647 free(sp);
2648 return size;
2649}
2650
2651
2652PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2653{
2654 int err;
2655 PyObject* retval;
2656 DBT key;
2657 DBT data;
2658
2659 CHECK_DB_NOT_CLOSED(self);
2660 if (!make_key_dbt(self, keyobj, &key, NULL))
2661 return NULL;
2662
2663 CLEAR_DBT(data);
2664 if (CHECK_DBFLAG(self, DB_THREAD)) {
2665 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2666 data.flags = DB_DBT_MALLOC;
2667 }
2668 MYDB_BEGIN_ALLOW_THREADS;
2669 err = self->db->get(self->db, NULL, &key, &data, 0);
2670 MYDB_END_ALLOW_THREADS;
2671 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2672 PyErr_SetObject(PyExc_KeyError, keyobj);
2673 retval = NULL;
2674 }
2675 else if (makeDBError(err)) {
2676 retval = NULL;
2677 }
2678 else {
2679 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2680 FREE_DBT(data);
2681 }
2682
2683 FREE_DBT(key);
2684 return retval;
2685}
2686
2687
2688static int
2689DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2690{
2691 DBT key, data;
2692 int retval;
2693 int flags = 0;
2694
2695 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002696 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2697 PyErr_SetObject(DBError, t);
2698 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699 return -1;
2700 }
2701
2702 if (!make_key_dbt(self, keyobj, &key, NULL))
2703 return -1;
2704
2705 if (dataobj != NULL) {
2706 if (!make_dbt(dataobj, &data))
2707 retval = -1;
2708 else {
2709 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002710 /* dictionaries shouldn't have duplicate keys */
2711 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002712 retval = _DB_put(self, NULL, &key, &data, flags);
2713
2714 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002715 /* try deleting any old record that matches and then PUT it
2716 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717 _DB_delete(self, NULL, &key, 0);
2718 PyErr_Clear();
2719 retval = _DB_put(self, NULL, &key, &data, flags);
2720 }
2721 }
2722 }
2723 else {
2724 /* dataobj == NULL, so delete the key */
2725 retval = _DB_delete(self, NULL, &key, 0);
2726 }
2727 FREE_DBT(key);
2728 return retval;
2729}
2730
2731
2732static PyObject*
2733DB_has_key(DBObject* self, PyObject* args)
2734{
2735 int err;
2736 PyObject* keyobj;
2737 DBT key, data;
2738 PyObject* txnobj = NULL;
2739 DB_TXN *txn = NULL;
2740
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002741 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002742 return NULL;
2743 CHECK_DB_NOT_CLOSED(self);
2744 if (!make_key_dbt(self, keyobj, &key, NULL))
2745 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002746 if (!checkTxnObj(txnobj, &txn)) {
2747 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002748 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002749 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002751 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002752 it has a record but can't allocate a buffer for the data. This saves
2753 having to deal with data we won't be using.
2754 */
2755 CLEAR_DBT(data);
2756 data.flags = DB_DBT_USERMEM;
2757
2758 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002759 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002760 MYDB_END_ALLOW_THREADS;
2761 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002762
2763 if (err == DB_BUFFER_SMALL || err == 0) {
2764 return PyInt_FromLong(1);
2765 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2766 return PyInt_FromLong(0);
2767 }
2768
2769 makeDBError(err);
2770 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002771}
2772
2773
2774#define _KEYS_LIST 1
2775#define _VALUES_LIST 2
2776#define _ITEMS_LIST 3
2777
2778static PyObject*
2779_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2780{
2781 int err, dbtype;
2782 DBT key;
2783 DBT data;
2784 DBC *cursor;
2785 PyObject* list;
2786 PyObject* item = NULL;
2787
2788 CHECK_DB_NOT_CLOSED(self);
2789 CLEAR_DBT(key);
2790 CLEAR_DBT(data);
2791
2792 dbtype = _DB_get_type(self);
2793 if (dbtype == -1)
2794 return NULL;
2795
2796 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002797 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002798 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799
2800 /* get a cursor */
2801 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002802 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002804 if (makeDBError(err)) {
2805 Py_DECREF(list);
2806 return NULL;
2807 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002808
2809 if (CHECK_DBFLAG(self, DB_THREAD)) {
2810 key.flags = DB_DBT_REALLOC;
2811 data.flags = DB_DBT_REALLOC;
2812 }
2813
2814 while (1) { /* use the cursor to traverse the DB, collecting items */
2815 MYDB_BEGIN_ALLOW_THREADS;
2816 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2817 MYDB_END_ALLOW_THREADS;
2818
2819 if (err) {
2820 /* for any error, break out of the loop */
2821 break;
2822 }
2823
2824 switch (type) {
2825 case _KEYS_LIST:
2826 switch(dbtype) {
2827 case DB_BTREE:
2828 case DB_HASH:
2829 default:
2830 item = PyString_FromStringAndSize((char*)key.data, key.size);
2831 break;
2832 case DB_RECNO:
2833 case DB_QUEUE:
2834 item = PyInt_FromLong(*((db_recno_t*)key.data));
2835 break;
2836 }
2837 break;
2838
2839 case _VALUES_LIST:
2840 item = PyString_FromStringAndSize((char*)data.data, data.size);
2841 break;
2842
2843 case _ITEMS_LIST:
2844 switch(dbtype) {
2845 case DB_BTREE:
2846 case DB_HASH:
2847 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002848 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2849 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 break;
2851 case DB_RECNO:
2852 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002853 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2854 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855 break;
2856 }
2857 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002858 default:
2859 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2860 item = NULL;
2861 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002862 }
2863 if (item == NULL) {
2864 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002865 list = NULL;
2866 goto done;
2867 }
2868 PyList_Append(list, item);
2869 Py_DECREF(item);
2870 }
2871
Gregory P. Smithe9477062005-06-04 06:46:59 +00002872 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2873 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002874 Py_DECREF(list);
2875 list = NULL;
2876 }
2877
2878 done:
2879 FREE_DBT(key);
2880 FREE_DBT(data);
2881 MYDB_BEGIN_ALLOW_THREADS;
2882 cursor->c_close(cursor);
2883 MYDB_END_ALLOW_THREADS;
2884 return list;
2885}
2886
2887
2888static PyObject*
2889DB_keys(DBObject* self, PyObject* args)
2890{
2891 PyObject* txnobj = NULL;
2892 DB_TXN *txn = NULL;
2893
2894 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2895 return NULL;
2896 if (!checkTxnObj(txnobj, &txn))
2897 return NULL;
2898 return _DB_make_list(self, txn, _KEYS_LIST);
2899}
2900
2901
2902static PyObject*
2903DB_items(DBObject* self, PyObject* args)
2904{
2905 PyObject* txnobj = NULL;
2906 DB_TXN *txn = NULL;
2907
2908 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2909 return NULL;
2910 if (!checkTxnObj(txnobj, &txn))
2911 return NULL;
2912 return _DB_make_list(self, txn, _ITEMS_LIST);
2913}
2914
2915
2916static PyObject*
2917DB_values(DBObject* self, PyObject* args)
2918{
2919 PyObject* txnobj = NULL;
2920 DB_TXN *txn = NULL;
2921
2922 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2923 return NULL;
2924 if (!checkTxnObj(txnobj, &txn))
2925 return NULL;
2926 return _DB_make_list(self, txn, _VALUES_LIST);
2927}
2928
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929/* --------------------------------------------------------------------- */
2930/* DBCursor methods */
2931
2932
2933static PyObject*
2934DBC_close(DBCursorObject* self, PyObject* args)
2935{
2936 int err = 0;
2937
2938 if (!PyArg_ParseTuple(args, ":close"))
2939 return NULL;
2940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002941 if (self->dbc != NULL) {
2942 MYDB_BEGIN_ALLOW_THREADS;
2943 err = self->dbc->c_close(self->dbc);
2944 self->dbc = NULL;
2945 MYDB_END_ALLOW_THREADS;
2946 }
2947 RETURN_IF_ERR();
2948 RETURN_NONE();
2949}
2950
2951
2952static PyObject*
2953DBC_count(DBCursorObject* self, PyObject* args)
2954{
2955 int err = 0;
2956 db_recno_t count;
2957 int flags = 0;
2958
2959 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2960 return NULL;
2961
2962 CHECK_CURSOR_NOT_CLOSED(self);
2963
2964 MYDB_BEGIN_ALLOW_THREADS;
2965 err = self->dbc->c_count(self->dbc, &count, flags);
2966 MYDB_END_ALLOW_THREADS;
2967 RETURN_IF_ERR();
2968
2969 return PyInt_FromLong(count);
2970}
2971
2972
2973static PyObject*
2974DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2975{
2976 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2977}
2978
2979
2980static PyObject*
2981DBC_delete(DBCursorObject* self, PyObject* args)
2982{
2983 int err, flags=0;
2984
2985 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2986 return NULL;
2987
2988 CHECK_CURSOR_NOT_CLOSED(self);
2989
2990 MYDB_BEGIN_ALLOW_THREADS;
2991 err = self->dbc->c_del(self->dbc, flags);
2992 MYDB_END_ALLOW_THREADS;
2993 RETURN_IF_ERR();
2994
2995 self->mydb->haveStat = 0;
2996 RETURN_NONE();
2997}
2998
2999
3000static PyObject*
3001DBC_dup(DBCursorObject* self, PyObject* args)
3002{
3003 int err, flags =0;
3004 DBC* dbc = NULL;
3005
3006 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3007 return NULL;
3008
3009 CHECK_CURSOR_NOT_CLOSED(self);
3010
3011 MYDB_BEGIN_ALLOW_THREADS;
3012 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3013 MYDB_END_ALLOW_THREADS;
3014 RETURN_IF_ERR();
3015
3016 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3017}
3018
3019static PyObject*
3020DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3021{
3022 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3023}
3024
3025
3026static PyObject*
3027DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3028{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003029 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030 PyObject* keyobj = NULL;
3031 PyObject* dataobj = NULL;
3032 PyObject* retval = NULL;
3033 int dlen = -1;
3034 int doff = -1;
3035 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003036 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003037 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003038
3039 CLEAR_DBT(key);
3040 CLEAR_DBT(data);
3041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003042 &flags, &dlen, &doff))
3043 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003045 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3046 &kwnames[1],
3047 &keyobj, &flags, &dlen, &doff))
3048 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003049 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003050 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3051 kwnames, &keyobj, &dataobj,
3052 &flags, &dlen, &doff))
3053 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003054 return NULL;
3055 }
3056 }
3057 }
3058
3059 CHECK_CURSOR_NOT_CLOSED(self);
3060
3061 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3062 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003063 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3064 (!add_partial_dbt(&data, dlen, doff)) )
3065 {
3066 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003068 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003069
3070 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3071 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003072 if (!(key.flags & DB_DBT_REALLOC)) {
3073 key.flags |= DB_DBT_MALLOC;
3074 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003075 }
3076
3077 MYDB_BEGIN_ALLOW_THREADS;
3078 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3079 MYDB_END_ALLOW_THREADS;
3080
Gregory P. Smithe9477062005-06-04 06:46:59 +00003081 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3082 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003083 Py_INCREF(Py_None);
3084 retval = Py_None;
3085 }
3086 else if (makeDBError(err)) {
3087 retval = NULL;
3088 }
3089 else {
3090 switch (_DB_get_type(self->mydb)) {
3091 case -1:
3092 retval = NULL;
3093 break;
3094 case DB_BTREE:
3095 case DB_HASH:
3096 default:
3097 retval = Py_BuildValue("s#s#", key.data, key.size,
3098 data.data, data.size);
3099 break;
3100 case DB_RECNO:
3101 case DB_QUEUE:
3102 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3103 data.data, data.size);
3104 break;
3105 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003106 FREE_DBT(data);
3107 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003108 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003109 return retval;
3110}
3111
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003112#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003113static PyObject*
3114DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3115{
3116 int err, flags=0;
3117 PyObject* keyobj = NULL;
3118 PyObject* dataobj = NULL;
3119 PyObject* retval = NULL;
3120 int dlen = -1;
3121 int doff = -1;
3122 DBT key, pkey, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003123 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003124 NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003125
3126 CLEAR_DBT(key);
3127 CLEAR_DBT(data);
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3129 &flags, &dlen, &doff))
3130 {
3131 PyErr_Clear();
3132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3133 &kwnames[1],
3134 &keyobj, &flags, &dlen, &doff))
3135 {
3136 PyErr_Clear();
3137 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3138 kwnames, &keyobj, &dataobj,
3139 &flags, &dlen, &doff))
3140 {
3141 return NULL;
3142 }
3143 }
3144 }
3145
3146 CHECK_CURSOR_NOT_CLOSED(self);
3147
3148 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3149 return NULL;
3150 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3151 (!add_partial_dbt(&data, dlen, doff)) ) {
3152 FREE_DBT(key);
3153 return NULL;
3154 }
3155
3156 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3157 data.flags = DB_DBT_MALLOC;
3158 if (!(key.flags & DB_DBT_REALLOC)) {
3159 key.flags |= DB_DBT_MALLOC;
3160 }
3161 }
3162
3163 CLEAR_DBT(pkey);
3164 pkey.flags = DB_DBT_MALLOC;
3165
3166 MYDB_BEGIN_ALLOW_THREADS;
3167 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3168 MYDB_END_ALLOW_THREADS;
3169
Gregory P. Smithe9477062005-06-04 06:46:59 +00003170 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3171 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003172 Py_INCREF(Py_None);
3173 retval = Py_None;
3174 }
3175 else if (makeDBError(err)) {
3176 retval = NULL;
3177 }
3178 else {
3179 PyObject *pkeyObj;
3180 PyObject *dataObj;
3181 dataObj = PyString_FromStringAndSize(data.data, data.size);
3182
3183 if (self->mydb->primaryDBType == DB_RECNO ||
3184 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003185 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003186 else
3187 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3188
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003189 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003190 {
3191 PyObject *keyObj;
3192 int type = _DB_get_type(self->mydb);
3193 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003194 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003195 else
3196 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003197#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003198 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003199#else
3200 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3201#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003202 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003203 FREE_DBT(key);
3204 }
3205 else /* return just the pkey and data */
3206 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003207#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003208 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003209#else
3210 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3211#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003212 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003213 Py_DECREF(dataObj);
3214 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003215 FREE_DBT(pkey);
3216 FREE_DBT(data);
3217 }
3218 /* the only time REALLOC should be set is if we used an integer
3219 * key that make_key_dbt malloc'd for us. always free these. */
3220 if (key.flags & DB_DBT_REALLOC) {
3221 FREE_DBT(key);
3222 }
3223 return retval;
3224}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003225#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003226
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003227
3228static PyObject*
3229DBC_get_recno(DBCursorObject* self, PyObject* args)
3230{
3231 int err;
3232 db_recno_t recno;
3233 DBT key;
3234 DBT data;
3235
3236 if (!PyArg_ParseTuple(args, ":get_recno"))
3237 return NULL;
3238
3239 CHECK_CURSOR_NOT_CLOSED(self);
3240
3241 CLEAR_DBT(key);
3242 CLEAR_DBT(data);
3243 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3244 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3245 data.flags = DB_DBT_MALLOC;
3246 key.flags = DB_DBT_MALLOC;
3247 }
3248
3249 MYDB_BEGIN_ALLOW_THREADS;
3250 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3251 MYDB_END_ALLOW_THREADS;
3252 RETURN_IF_ERR();
3253
3254 recno = *((db_recno_t*)data.data);
3255 FREE_DBT(key);
3256 FREE_DBT(data);
3257 return PyInt_FromLong(recno);
3258}
3259
3260
3261static PyObject*
3262DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3263{
3264 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3265}
3266
3267
3268static PyObject*
3269DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3270{
3271 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3272}
3273
3274
3275static PyObject*
3276DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3277{
3278 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3279}
3280
3281
3282static PyObject*
3283DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3284{
3285 int err, flags = 0;
3286 PyObject* keyobj, *dataobj;
3287 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003288 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003289 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003290 int dlen = -1;
3291 int doff = -1;
3292
3293 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3294 &keyobj, &dataobj, &flags, &dlen, &doff))
3295 return NULL;
3296
3297 CHECK_CURSOR_NOT_CLOSED(self);
3298
3299 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3300 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003301 if (!make_dbt(dataobj, &data) ||
3302 !add_partial_dbt(&data, dlen, doff) )
3303 {
3304 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003306 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003307
3308 MYDB_BEGIN_ALLOW_THREADS;
3309 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3310 MYDB_END_ALLOW_THREADS;
3311 FREE_DBT(key);
3312 RETURN_IF_ERR();
3313 self->mydb->haveStat = 0;
3314 RETURN_NONE();
3315}
3316
3317
3318static PyObject*
3319DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3320{
3321 int err, flags = 0;
3322 DBT key, data;
3323 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003324 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003325 int dlen = -1;
3326 int doff = -1;
3327
3328 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3329 &keyobj, &flags, &dlen, &doff))
3330 return NULL;
3331
3332 CHECK_CURSOR_NOT_CLOSED(self);
3333
3334 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3335 return NULL;
3336
3337 CLEAR_DBT(data);
3338 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3339 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3340 data.flags = DB_DBT_MALLOC;
3341 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003342 if (!add_partial_dbt(&data, dlen, doff)) {
3343 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003344 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003345 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346
3347 MYDB_BEGIN_ALLOW_THREADS;
3348 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3349 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003350 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3351 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003352 Py_INCREF(Py_None);
3353 retval = Py_None;
3354 }
3355 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003356 retval = NULL;
3357 }
3358 else {
3359 switch (_DB_get_type(self->mydb)) {
3360 case -1:
3361 retval = NULL;
3362 break;
3363 case DB_BTREE:
3364 case DB_HASH:
3365 default:
3366 retval = Py_BuildValue("s#s#", key.data, key.size,
3367 data.data, data.size);
3368 break;
3369 case DB_RECNO:
3370 case DB_QUEUE:
3371 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3372 data.data, data.size);
3373 break;
3374 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003375 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003376 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003377 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003378 /* the only time REALLOC should be set is if we used an integer
3379 * key that make_key_dbt malloc'd for us. always free these. */
3380 if (key.flags & DB_DBT_REALLOC) {
3381 FREE_DBT(key);
3382 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003383
3384 return retval;
3385}
3386
3387
3388static PyObject*
3389DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3390{
3391 int err, flags = 0;
3392 DBT key, data;
3393 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003394 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003395 int dlen = -1;
3396 int doff = -1;
3397
3398 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3399 &keyobj, &flags, &dlen, &doff))
3400 return NULL;
3401
3402 CHECK_CURSOR_NOT_CLOSED(self);
3403
3404 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3405 return NULL;
3406
3407 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003408 if (!add_partial_dbt(&data, dlen, doff)) {
3409 FREE_DBT(key);
3410 return NULL;
3411 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3413 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003414 data.flags |= DB_DBT_MALLOC;
3415 /* only BTREE databases will return anything in the key */
3416 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3417 key.flags |= DB_DBT_MALLOC;
3418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003420 MYDB_BEGIN_ALLOW_THREADS;
3421 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3422 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003423 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3424 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003425 Py_INCREF(Py_None);
3426 retval = Py_None;
3427 }
3428 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003429 retval = NULL;
3430 }
3431 else {
3432 switch (_DB_get_type(self->mydb)) {
3433 case -1:
3434 retval = NULL;
3435 break;
3436 case DB_BTREE:
3437 case DB_HASH:
3438 default:
3439 retval = Py_BuildValue("s#s#", key.data, key.size,
3440 data.data, data.size);
3441 break;
3442 case DB_RECNO:
3443 case DB_QUEUE:
3444 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3445 data.data, data.size);
3446 break;
3447 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003448 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 FREE_DBT(data);
3450 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003451 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003452 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003453 if (key.flags & DB_DBT_REALLOC) {
3454 FREE_DBT(key);
3455 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003456
3457 return retval;
3458}
3459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003461_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3462 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003464 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003466 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467
Gregory P. Smith7441e652003-11-03 21:35:31 +00003468 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3470 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003471 if (!make_dbt(dataobj, &data)) {
3472 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003474 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475
3476 MYDB_BEGIN_ALLOW_THREADS;
3477 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3478 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003479 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003480 Py_INCREF(Py_None);
3481 retval = Py_None;
3482 }
3483 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 retval = NULL;
3485 }
3486 else {
3487 switch (_DB_get_type(self->mydb)) {
3488 case -1:
3489 retval = NULL;
3490 break;
3491 case DB_BTREE:
3492 case DB_HASH:
3493 default:
3494 retval = Py_BuildValue("s#s#", key.data, key.size,
3495 data.data, data.size);
3496 break;
3497 case DB_RECNO:
3498 case DB_QUEUE:
3499 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3500 data.data, data.size);
3501 break;
3502 }
3503 }
3504
3505 FREE_DBT(key);
3506 return retval;
3507}
3508
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003509static PyObject*
3510DBC_get_both(DBCursorObject* self, PyObject* args)
3511{
3512 int flags=0;
3513 PyObject *keyobj, *dataobj;
3514
3515 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3516 return NULL;
3517
Gregory P. Smith7441e652003-11-03 21:35:31 +00003518 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003519 CHECK_CURSOR_NOT_CLOSED(self);
3520
3521 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3522 self->mydb->moduleFlags.getReturnsNone);
3523}
3524
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003525/* Return size of entry */
3526static PyObject*
3527DBC_get_current_size(DBCursorObject* self, PyObject* args)
3528{
3529 int err, flags=DB_CURRENT;
3530 PyObject* retval = NULL;
3531 DBT key, data;
3532
3533 if (!PyArg_ParseTuple(args, ":get_current_size"))
3534 return NULL;
3535 CHECK_CURSOR_NOT_CLOSED(self);
3536 CLEAR_DBT(key);
3537 CLEAR_DBT(data);
3538
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003539 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003540 getting the record size. */
3541 data.flags = DB_DBT_USERMEM;
3542 data.ulen = 0;
3543 MYDB_BEGIN_ALLOW_THREADS;
3544 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3545 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003546 if (err == DB_BUFFER_SMALL || !err) {
3547 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003548 retval = PyInt_FromLong((long)data.size);
3549 err = 0;
3550 }
3551
3552 FREE_DBT(key);
3553 FREE_DBT(data);
3554 RETURN_IF_ERR();
3555 return retval;
3556}
3557
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003558static PyObject*
3559DBC_set_both(DBCursorObject* self, PyObject* args)
3560{
3561 int flags=0;
3562 PyObject *keyobj, *dataobj;
3563
3564 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3565 return NULL;
3566
Gregory P. Smith7441e652003-11-03 21:35:31 +00003567 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003568 CHECK_CURSOR_NOT_CLOSED(self);
3569
3570 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3571 self->mydb->moduleFlags.cursorSetReturnsNone);
3572}
3573
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003574
3575static PyObject*
3576DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3577{
3578 int err, irecno, flags=0;
3579 db_recno_t recno;
3580 DBT key, data;
3581 PyObject* retval;
3582 int dlen = -1;
3583 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003584 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585
3586 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3587 &irecno, &flags, &dlen, &doff))
3588 return NULL;
3589
3590 CHECK_CURSOR_NOT_CLOSED(self);
3591
3592 CLEAR_DBT(key);
3593 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003594 /* use allocated space so DB will be able to realloc room for the real
3595 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 key.data = malloc(sizeof(db_recno_t));
3597 if (key.data == NULL) {
3598 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3599 return NULL;
3600 }
3601 key.size = sizeof(db_recno_t);
3602 key.ulen = key.size;
3603 memcpy(key.data, &recno, sizeof(db_recno_t));
3604 key.flags = DB_DBT_REALLOC;
3605
3606 CLEAR_DBT(data);
3607 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3608 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3609 data.flags = DB_DBT_MALLOC;
3610 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003611 if (!add_partial_dbt(&data, dlen, doff)) {
3612 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003614 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003615
3616 MYDB_BEGIN_ALLOW_THREADS;
3617 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3618 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003619 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3620 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003621 Py_INCREF(Py_None);
3622 retval = Py_None;
3623 }
3624 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003625 retval = NULL;
3626 }
3627 else { /* Can only be used for BTrees, so no need to return int key */
3628 retval = Py_BuildValue("s#s#", key.data, key.size,
3629 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003630 FREE_DBT(data);
3631 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003632 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003633
3634 return retval;
3635}
3636
3637
3638static PyObject*
3639DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3640{
3641 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3642}
3643
3644
3645static PyObject*
3646DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3647{
3648 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3649}
3650
3651
3652static PyObject*
3653DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3654{
3655 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3656}
3657
3658
3659static PyObject*
3660DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3661{
3662 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3663}
3664
3665
3666static PyObject*
3667DBC_join_item(DBCursorObject* self, PyObject* args)
3668{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670 DBT key, data;
3671 PyObject* retval;
3672
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003673 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003674 return NULL;
3675
3676 CHECK_CURSOR_NOT_CLOSED(self);
3677
3678 CLEAR_DBT(key);
3679 CLEAR_DBT(data);
3680 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3681 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3682 key.flags = DB_DBT_MALLOC;
3683 }
3684
3685 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003686 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003687 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003688 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3689 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003690 Py_INCREF(Py_None);
3691 retval = Py_None;
3692 }
3693 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694 retval = NULL;
3695 }
3696 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003697 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003698 FREE_DBT(key);
3699 }
3700
3701 return retval;
3702}
3703
3704
3705
3706/* --------------------------------------------------------------------- */
3707/* DBEnv methods */
3708
3709
3710static PyObject*
3711DBEnv_close(DBEnvObject* self, PyObject* args)
3712{
3713 int err, flags = 0;
3714
3715 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3716 return NULL;
3717 if (!self->closed) { /* Don't close more than once */
3718 MYDB_BEGIN_ALLOW_THREADS;
3719 err = self->db_env->close(self->db_env, flags);
3720 MYDB_END_ALLOW_THREADS;
3721 /* after calling DBEnv->close, regardless of error, this DBEnv
3722 * may not be accessed again (BerkeleyDB docs). */
3723 self->closed = 1;
3724 self->db_env = NULL;
3725 RETURN_IF_ERR();
3726 }
3727 RETURN_NONE();
3728}
3729
3730
3731static PyObject*
3732DBEnv_open(DBEnvObject* self, PyObject* args)
3733{
3734 int err, flags=0, mode=0660;
3735 char *db_home;
3736
3737 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3738 return NULL;
3739
3740 CHECK_ENV_NOT_CLOSED(self);
3741
3742 MYDB_BEGIN_ALLOW_THREADS;
3743 err = self->db_env->open(self->db_env, db_home, flags, mode);
3744 MYDB_END_ALLOW_THREADS;
3745 RETURN_IF_ERR();
3746 self->closed = 0;
3747 self->flags = flags;
3748 RETURN_NONE();
3749}
3750
3751
3752static PyObject*
3753DBEnv_remove(DBEnvObject* self, PyObject* args)
3754{
3755 int err, flags=0;
3756 char *db_home;
3757
3758 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3759 return NULL;
3760 CHECK_ENV_NOT_CLOSED(self);
3761 MYDB_BEGIN_ALLOW_THREADS;
3762 err = self->db_env->remove(self->db_env, db_home, flags);
3763 MYDB_END_ALLOW_THREADS;
3764 RETURN_IF_ERR();
3765 RETURN_NONE();
3766}
3767
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003768#if (DBVER >= 41)
3769static PyObject*
3770DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3771{
3772 int err;
3773 u_int32_t flags=0;
3774 char *file = NULL;
3775 char *database = NULL;
3776 PyObject *txnobj = NULL;
3777 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003778 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003779 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003780
3781 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3782 &file, &database, &txnobj, &flags)) {
3783 return NULL;
3784 }
3785 if (!checkTxnObj(txnobj, &txn)) {
3786 return NULL;
3787 }
3788 CHECK_ENV_NOT_CLOSED(self);
3789 MYDB_BEGIN_ALLOW_THREADS;
3790 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3791 MYDB_END_ALLOW_THREADS;
3792 RETURN_IF_ERR();
3793 RETURN_NONE();
3794}
3795
3796static PyObject*
3797DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3798{
3799 int err;
3800 u_int32_t flags=0;
3801 char *file = NULL;
3802 char *database = NULL;
3803 char *newname = NULL;
3804 PyObject *txnobj = NULL;
3805 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003806 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003807 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003808
3809 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3810 &file, &database, &newname, &txnobj, &flags)) {
3811 return NULL;
3812 }
3813 if (!checkTxnObj(txnobj, &txn)) {
3814 return NULL;
3815 }
3816 CHECK_ENV_NOT_CLOSED(self);
3817 MYDB_BEGIN_ALLOW_THREADS;
3818 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3819 flags);
3820 MYDB_END_ALLOW_THREADS;
3821 RETURN_IF_ERR();
3822 RETURN_NONE();
3823}
3824
3825static PyObject*
3826DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3827{
3828 int err;
3829 u_int32_t flags=0;
3830 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003831 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003832
3833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3834 &passwd, &flags)) {
3835 return NULL;
3836 }
3837
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3840 MYDB_END_ALLOW_THREADS;
3841
3842 RETURN_IF_ERR();
3843 RETURN_NONE();
3844}
3845#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003846
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003847#if (DBVER >= 40)
3848static PyObject*
3849DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3850{
3851 int err;
3852 u_int32_t flags=0;
3853 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003854 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003855
3856 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3857 &timeout, &flags)) {
3858 return NULL;
3859 }
3860
3861 MYDB_BEGIN_ALLOW_THREADS;
3862 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3863 MYDB_END_ALLOW_THREADS;
3864
3865 RETURN_IF_ERR();
3866 RETURN_NONE();
3867}
3868#endif /* DBVER >= 40 */
3869
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003870static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003871DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3872{
3873 int err;
3874 long shm_key = 0;
3875
3876 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3877 return NULL;
3878 CHECK_ENV_NOT_CLOSED(self);
3879
3880 err = self->db_env->set_shm_key(self->db_env, shm_key);
3881 RETURN_IF_ERR();
3882 RETURN_NONE();
3883}
3884
3885static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003886DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3887{
3888 int err, gbytes=0, bytes=0, ncache=0;
3889
3890 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3891 &gbytes, &bytes, &ncache))
3892 return NULL;
3893 CHECK_ENV_NOT_CLOSED(self);
3894
3895 MYDB_BEGIN_ALLOW_THREADS;
3896 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3897 MYDB_END_ALLOW_THREADS;
3898 RETURN_IF_ERR();
3899 RETURN_NONE();
3900}
3901
3902
3903#if (DBVER >= 32)
3904static PyObject*
3905DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3906{
3907 int err, flags=0, onoff=0;
3908
3909 if (!PyArg_ParseTuple(args, "ii:set_flags",
3910 &flags, &onoff))
3911 return NULL;
3912 CHECK_ENV_NOT_CLOSED(self);
3913
3914 MYDB_BEGIN_ALLOW_THREADS;
3915 err = self->db_env->set_flags(self->db_env, flags, onoff);
3916 MYDB_END_ALLOW_THREADS;
3917 RETURN_IF_ERR();
3918 RETURN_NONE();
3919}
3920#endif
3921
3922
3923static PyObject*
3924DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3925{
3926 int err;
3927 char *dir;
3928
3929 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3930 return NULL;
3931 CHECK_ENV_NOT_CLOSED(self);
3932
3933 MYDB_BEGIN_ALLOW_THREADS;
3934 err = self->db_env->set_data_dir(self->db_env, dir);
3935 MYDB_END_ALLOW_THREADS;
3936 RETURN_IF_ERR();
3937 RETURN_NONE();
3938}
3939
3940
3941static PyObject*
3942DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3943{
3944 int err, lg_bsize;
3945
3946 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3947 return NULL;
3948 CHECK_ENV_NOT_CLOSED(self);
3949
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3952 MYDB_END_ALLOW_THREADS;
3953 RETURN_IF_ERR();
3954 RETURN_NONE();
3955}
3956
3957
3958static PyObject*
3959DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3960{
3961 int err;
3962 char *dir;
3963
3964 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3965 return NULL;
3966 CHECK_ENV_NOT_CLOSED(self);
3967
3968 MYDB_BEGIN_ALLOW_THREADS;
3969 err = self->db_env->set_lg_dir(self->db_env, dir);
3970 MYDB_END_ALLOW_THREADS;
3971 RETURN_IF_ERR();
3972 RETURN_NONE();
3973}
3974
3975static PyObject*
3976DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3977{
3978 int err, lg_max;
3979
3980 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_lg_max(self->db_env, lg_max);
3986 MYDB_END_ALLOW_THREADS;
3987 RETURN_IF_ERR();
3988 RETURN_NONE();
3989}
3990
3991
Neal Norwitz84562352005-10-20 04:30:15 +00003992#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003994DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3995{
3996 int err, lg_max;
3997
3998 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3999 return NULL;
4000 CHECK_ENV_NOT_CLOSED(self);
4001
4002 MYDB_BEGIN_ALLOW_THREADS;
4003 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4004 MYDB_END_ALLOW_THREADS;
4005 RETURN_IF_ERR();
4006 RETURN_NONE();
4007}
Neal Norwitz84562352005-10-20 04:30:15 +00004008#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004009
4010
4011static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004012DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4013{
4014 int err, lk_detect;
4015
4016 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4017 return NULL;
4018 CHECK_ENV_NOT_CLOSED(self);
4019
4020 MYDB_BEGIN_ALLOW_THREADS;
4021 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
4026
4027
4028static PyObject*
4029DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4030{
4031 int err, max;
4032
4033 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_lk_max(self->db_env, max);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045#if (DBVER >= 32)
4046
4047static PyObject*
4048DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4049{
4050 int err, max;
4051
4052 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4053 return NULL;
4054 CHECK_ENV_NOT_CLOSED(self);
4055
4056 MYDB_BEGIN_ALLOW_THREADS;
4057 err = self->db_env->set_lk_max_locks(self->db_env, max);
4058 MYDB_END_ALLOW_THREADS;
4059 RETURN_IF_ERR();
4060 RETURN_NONE();
4061}
4062
4063
4064static PyObject*
4065DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4066{
4067 int err, max;
4068
4069 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4070 return NULL;
4071 CHECK_ENV_NOT_CLOSED(self);
4072
4073 MYDB_BEGIN_ALLOW_THREADS;
4074 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4075 MYDB_END_ALLOW_THREADS;
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079
4080
4081static PyObject*
4082DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4083{
4084 int err, max;
4085
4086 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4087 return NULL;
4088 CHECK_ENV_NOT_CLOSED(self);
4089
4090 MYDB_BEGIN_ALLOW_THREADS;
4091 err = self->db_env->set_lk_max_objects(self->db_env, max);
4092 MYDB_END_ALLOW_THREADS;
4093 RETURN_IF_ERR();
4094 RETURN_NONE();
4095}
4096
4097#endif
4098
4099
4100static PyObject*
4101DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4102{
4103 int err, mp_mmapsize;
4104
4105 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
4115
4116
4117static PyObject*
4118DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4119{
4120 int err;
4121 char *dir;
4122
4123 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4124 return NULL;
4125 CHECK_ENV_NOT_CLOSED(self);
4126
4127 MYDB_BEGIN_ALLOW_THREADS;
4128 err = self->db_env->set_tmp_dir(self->db_env, dir);
4129 MYDB_END_ALLOW_THREADS;
4130 RETURN_IF_ERR();
4131 RETURN_NONE();
4132}
4133
4134
4135static PyObject*
4136DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4137{
4138 int flags = 0;
4139 PyObject* txnobj = NULL;
4140 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004141 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004142
4143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4144 &txnobj, &flags))
4145 return NULL;
4146
4147 if (!checkTxnObj(txnobj, &txn))
4148 return NULL;
4149 CHECK_ENV_NOT_CLOSED(self);
4150
4151 return (PyObject*)newDBTxnObject(self, txn, flags);
4152}
4153
4154
4155static PyObject*
4156DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4157{
4158 int err, kbyte=0, min=0, flags=0;
4159
4160 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4161 return NULL;
4162 CHECK_ENV_NOT_CLOSED(self);
4163
4164 MYDB_BEGIN_ALLOW_THREADS;
4165#if (DBVER >= 40)
4166 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4167#else
4168 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4169#endif
4170 MYDB_END_ALLOW_THREADS;
4171 RETURN_IF_ERR();
4172 RETURN_NONE();
4173}
4174
4175
4176static PyObject*
4177DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4178{
4179 int err, max;
4180
4181 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4182 return NULL;
4183 CHECK_ENV_NOT_CLOSED(self);
4184
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004185 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004186 RETURN_IF_ERR();
4187 RETURN_NONE();
4188}
4189
4190
4191static PyObject*
4192DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4193{
4194 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004195 long stamp;
4196 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004197
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004198 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004199 return NULL;
4200 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004201 timestamp = (time_t)stamp;
4202 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004203 RETURN_IF_ERR();
4204 RETURN_NONE();
4205}
4206
4207
4208static PyObject*
4209DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4210{
4211 int err, atype, flags=0;
4212 int aborted = 0;
4213
4214 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4215 return NULL;
4216 CHECK_ENV_NOT_CLOSED(self);
4217
4218 MYDB_BEGIN_ALLOW_THREADS;
4219#if (DBVER >= 40)
4220 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4221#else
4222 err = lock_detect(self->db_env, flags, atype, &aborted);
4223#endif
4224 MYDB_END_ALLOW_THREADS;
4225 RETURN_IF_ERR();
4226 return PyInt_FromLong(aborted);
4227}
4228
4229
4230static PyObject*
4231DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4232{
4233 int flags=0;
4234 int locker, lock_mode;
4235 DBT obj;
4236 PyObject* objobj;
4237
4238 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4239 return NULL;
4240
4241
4242 if (!make_dbt(objobj, &obj))
4243 return NULL;
4244
4245 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4246}
4247
4248
4249static PyObject*
4250DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4251{
4252 int err;
4253 u_int32_t theID;
4254
4255 if (!PyArg_ParseTuple(args, ":lock_id"))
4256 return NULL;
4257
4258 CHECK_ENV_NOT_CLOSED(self);
4259 MYDB_BEGIN_ALLOW_THREADS;
4260#if (DBVER >= 40)
4261 err = self->db_env->lock_id(self->db_env, &theID);
4262#else
4263 err = lock_id(self->db_env, &theID);
4264#endif
4265 MYDB_END_ALLOW_THREADS;
4266 RETURN_IF_ERR();
4267
4268 return PyInt_FromLong((long)theID);
4269}
4270
4271
4272static PyObject*
4273DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4274{
4275 int err;
4276 DBLockObject* dblockobj;
4277
4278 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4279 return NULL;
4280
4281 CHECK_ENV_NOT_CLOSED(self);
4282 MYDB_BEGIN_ALLOW_THREADS;
4283#if (DBVER >= 40)
4284 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4285#else
4286 err = lock_put(self->db_env, &dblockobj->lock);
4287#endif
4288 MYDB_END_ALLOW_THREADS;
4289 RETURN_IF_ERR();
4290 RETURN_NONE();
4291}
4292
4293
4294static PyObject*
4295DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4296{
4297 int err;
4298 DB_LOCK_STAT* sp;
4299 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004300 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004301
4302 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
4305
4306 MYDB_BEGIN_ALLOW_THREADS;
4307#if (DBVER >= 40)
4308 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4309#else
4310#if (DBVER >= 33)
4311 err = lock_stat(self->db_env, &sp);
4312#else
4313 err = lock_stat(self->db_env, &sp, NULL);
4314#endif
4315#endif
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318
4319 /* Turn the stat structure into a dictionary */
4320 d = PyDict_New();
4321 if (d == NULL) {
4322 free(sp);
4323 return NULL;
4324 }
4325
4326#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4327
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004328#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004329 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004330#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004331 MAKE_ENTRY(nmodes);
4332#if (DBVER >= 32)
4333 MAKE_ENTRY(maxlocks);
4334 MAKE_ENTRY(maxlockers);
4335 MAKE_ENTRY(maxobjects);
4336 MAKE_ENTRY(nlocks);
4337 MAKE_ENTRY(maxnlocks);
4338#endif
4339 MAKE_ENTRY(nlockers);
4340 MAKE_ENTRY(maxnlockers);
4341#if (DBVER >= 32)
4342 MAKE_ENTRY(nobjects);
4343 MAKE_ENTRY(maxnobjects);
4344#endif
4345 MAKE_ENTRY(nrequests);
4346 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004347#if (DBVER < 44)
4348 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004349 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004350#else
4351 MAKE_ENTRY(lock_nowait);
4352 MAKE_ENTRY(lock_wait);
4353#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004354 MAKE_ENTRY(ndeadlocks);
4355 MAKE_ENTRY(regsize);
4356 MAKE_ENTRY(region_wait);
4357 MAKE_ENTRY(region_nowait);
4358
4359#undef MAKE_ENTRY
4360 free(sp);
4361 return d;
4362}
4363
4364
4365static PyObject*
4366DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4367{
4368 int flags=0;
4369 int err;
4370 char **log_list_start, **log_list;
4371 PyObject* list;
4372 PyObject* item = NULL;
4373
4374 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4375 return NULL;
4376
4377 CHECK_ENV_NOT_CLOSED(self);
4378 MYDB_BEGIN_ALLOW_THREADS;
4379#if (DBVER >= 40)
4380 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4381#elif (DBVER == 33)
4382 err = log_archive(self->db_env, &log_list, flags);
4383#else
4384 err = log_archive(self->db_env, &log_list, flags, NULL);
4385#endif
4386 MYDB_END_ALLOW_THREADS;
4387 RETURN_IF_ERR();
4388
4389 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00004390 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004391 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004392
4393 if (log_list) {
4394 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4395 item = PyString_FromString (*log_list);
4396 if (item == NULL) {
4397 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004398 list = NULL;
4399 break;
4400 }
4401 PyList_Append(list, item);
4402 Py_DECREF(item);
4403 }
4404 free(log_list_start);
4405 }
4406 return list;
4407}
4408
4409
4410static PyObject*
4411DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4412{
4413 int err;
4414 DB_TXN_STAT* sp;
4415 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004416 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004417
4418 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4419 return NULL;
4420 CHECK_ENV_NOT_CLOSED(self);
4421
4422 MYDB_BEGIN_ALLOW_THREADS;
4423#if (DBVER >= 40)
4424 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4425#elif (DBVER == 33)
4426 err = txn_stat(self->db_env, &sp);
4427#else
4428 err = txn_stat(self->db_env, &sp, NULL);
4429#endif
4430 MYDB_END_ALLOW_THREADS;
4431 RETURN_IF_ERR();
4432
4433 /* Turn the stat structure into a dictionary */
4434 d = PyDict_New();
4435 if (d == NULL) {
4436 free(sp);
4437 return NULL;
4438 }
4439
4440#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4441
4442 MAKE_ENTRY(time_ckp);
4443 MAKE_ENTRY(last_txnid);
4444 MAKE_ENTRY(maxtxns);
4445 MAKE_ENTRY(nactive);
4446 MAKE_ENTRY(maxnactive);
4447 MAKE_ENTRY(nbegins);
4448 MAKE_ENTRY(naborts);
4449 MAKE_ENTRY(ncommits);
4450 MAKE_ENTRY(regsize);
4451 MAKE_ENTRY(region_wait);
4452 MAKE_ENTRY(region_nowait);
4453
4454#undef MAKE_ENTRY
4455 free(sp);
4456 return d;
4457}
4458
4459
4460static PyObject*
4461DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4462{
4463 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004464 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004465
4466 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4467 return NULL;
4468 CHECK_ENV_NOT_CLOSED(self);
4469
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004470 if (self->moduleFlags.getReturnsNone)
4471 ++oldValue;
4472 if (self->moduleFlags.cursorSetReturnsNone)
4473 ++oldValue;
4474 self->moduleFlags.getReturnsNone = (flags >= 1);
4475 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004476 return PyInt_FromLong(oldValue);
4477}
4478
4479
4480/* --------------------------------------------------------------------- */
4481/* DBTxn methods */
4482
4483
4484static PyObject*
4485DBTxn_commit(DBTxnObject* self, PyObject* args)
4486{
4487 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004488 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004489
4490 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4491 return NULL;
4492
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004493 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004494 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4495 "after txn_commit or txn_abort");
4496 PyErr_SetObject(DBError, t);
4497 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004498 return NULL;
4499 }
4500 txn = self->txn;
4501 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502 MYDB_BEGIN_ALLOW_THREADS;
4503#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004504 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004505#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004506 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004507#endif
4508 MYDB_END_ALLOW_THREADS;
4509 RETURN_IF_ERR();
4510 RETURN_NONE();
4511}
4512
4513static PyObject*
4514DBTxn_prepare(DBTxnObject* self, PyObject* args)
4515{
4516#if (DBVER >= 33)
4517 int err;
4518 char* gid=NULL;
4519 int gid_size=0;
4520
4521 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4522 return NULL;
4523
4524 if (gid_size != DB_XIDDATASIZE) {
4525 PyErr_SetString(PyExc_TypeError,
4526 "gid must be DB_XIDDATASIZE bytes long");
4527 return NULL;
4528 }
4529
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004530 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004531 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4532 "after txn_commit or txn_abort");
4533 PyErr_SetObject(DBError, t);
4534 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004535 return NULL;
4536 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004537 MYDB_BEGIN_ALLOW_THREADS;
4538#if (DBVER >= 40)
4539 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4540#else
4541 err = txn_prepare(self->txn, (u_int8_t*)gid);
4542#endif
4543 MYDB_END_ALLOW_THREADS;
4544 RETURN_IF_ERR();
4545 RETURN_NONE();
4546#else
4547 int err;
4548
4549 if (!PyArg_ParseTuple(args, ":prepare"))
4550 return NULL;
4551
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004552 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004553 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4554 "after txn_commit or txn_abort");
4555 PyErr_SetObject(DBError, t);
4556 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004557 return NULL;
4558 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 MYDB_BEGIN_ALLOW_THREADS;
4560 err = txn_prepare(self->txn);
4561 MYDB_END_ALLOW_THREADS;
4562 RETURN_IF_ERR();
4563 RETURN_NONE();
4564#endif
4565}
4566
4567
4568static PyObject*
4569DBTxn_abort(DBTxnObject* self, PyObject* args)
4570{
4571 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004572 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004573
4574 if (!PyArg_ParseTuple(args, ":abort"))
4575 return NULL;
4576
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004577 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004578 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4579 "after txn_commit or txn_abort");
4580 PyErr_SetObject(DBError, t);
4581 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004582 return NULL;
4583 }
4584 txn = self->txn;
4585 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004586 MYDB_BEGIN_ALLOW_THREADS;
4587#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004588 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004590 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004591#endif
4592 MYDB_END_ALLOW_THREADS;
4593 RETURN_IF_ERR();
4594 RETURN_NONE();
4595}
4596
4597
4598static PyObject*
4599DBTxn_id(DBTxnObject* self, PyObject* args)
4600{
4601 int id;
4602
4603 if (!PyArg_ParseTuple(args, ":id"))
4604 return NULL;
4605
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004606 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004607 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4608 "after txn_commit or txn_abort");
4609 PyErr_SetObject(DBError, t);
4610 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004611 return NULL;
4612 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613 MYDB_BEGIN_ALLOW_THREADS;
4614#if (DBVER >= 40)
4615 id = self->txn->id(self->txn);
4616#else
4617 id = txn_id(self->txn);
4618#endif
4619 MYDB_END_ALLOW_THREADS;
4620 return PyInt_FromLong(id);
4621}
4622
4623/* --------------------------------------------------------------------- */
4624/* Method definition tables and type objects */
4625
4626static PyMethodDef DB_methods[] = {
4627 {"append", (PyCFunction)DB_append, METH_VARARGS},
4628#if (DBVER >= 33)
4629 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4630#endif
4631 {"close", (PyCFunction)DB_close, METH_VARARGS},
4632#if (DBVER >= 32)
4633 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4634 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4635#endif
4636 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4637 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4638 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4639 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004640#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004641 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004642#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004643 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4644 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4645 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4646 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4647 {"join", (PyCFunction)DB_join, METH_VARARGS},
4648 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4649 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4650 {"items", (PyCFunction)DB_items, METH_VARARGS},
4651 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4652 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4653 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4654 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4655 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4656 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004657#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00004658 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004659#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004660 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004661#if (DBVER >= 41)
4662 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4663#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4665 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4666 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4667 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4668 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4669 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4670 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4671 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4672 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4673#if (DBVER >= 32)
4674 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4675#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004676 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004677 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4678#if (DBVER >= 33)
4679 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4680#endif
4681 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4682 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4683 {"values", (PyCFunction)DB_values, METH_VARARGS},
4684 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4685 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4686 {NULL, NULL} /* sentinel */
4687};
4688
4689
4690static PyMappingMethods DB_mapping = {
Martin v. Löwis18e16552006-02-15 17:27:45 +00004691 (lenfunc)DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004692 (binaryfunc)DB_subscript, /*mp_subscript*/
4693 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4694};
4695
4696
4697static PyMethodDef DBCursor_methods[] = {
4698 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4699 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4700 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4701 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4702 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4703 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4704 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004705#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004706 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004707#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004708 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4709 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4710 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4711 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4712 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4713 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4714 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4715 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004716 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004717 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4719 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4720 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4721 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4722 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4723 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4724 {NULL, NULL} /* sentinel */
4725};
4726
4727
4728static PyMethodDef DBEnv_methods[] = {
4729 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4730 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4731 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004732#if (DBVER >= 41)
4733 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4734 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4735 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4736#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004737#if (DBVER >= 40)
4738 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4739#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004740 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004741 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4742 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4743#if (DBVER >= 32)
4744 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4745#endif
4746 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4747 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4748 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004749#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00004750 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00004751#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004752 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4753 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4754#if (DBVER >= 32)
4755 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4756 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4757 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4758#endif
4759 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4760 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4761 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4762 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4763 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4764 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00004765 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4767 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4768 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4769 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4770 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4771 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4772 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4773 {NULL, NULL} /* sentinel */
4774};
4775
4776
4777static PyMethodDef DBTxn_methods[] = {
4778 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4779 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4780 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4781 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4782 {NULL, NULL} /* sentinel */
4783};
4784
4785
4786static PyObject*
4787DB_getattr(DBObject* self, char *name)
4788{
4789 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4790}
4791
4792
4793static PyObject*
4794DBEnv_getattr(DBEnvObject* self, char *name)
4795{
4796 if (!strcmp(name, "db_home")) {
4797 CHECK_ENV_NOT_CLOSED(self);
4798 if (self->db_env->db_home == NULL) {
4799 RETURN_NONE();
4800 }
4801 return PyString_FromString(self->db_env->db_home);
4802 }
4803
4804 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4805}
4806
4807
4808static PyObject*
4809DBCursor_getattr(DBCursorObject* self, char *name)
4810{
4811 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4812}
4813
4814static PyObject*
4815DBTxn_getattr(DBTxnObject* self, char *name)
4816{
4817 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4818}
4819
4820static PyObject*
4821DBLock_getattr(DBLockObject* self, char *name)
4822{
4823 return NULL;
4824}
4825
Neal Norwitz227b5332006-03-22 09:28:35 +00004826static PyTypeObject DB_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004827 PyObject_HEAD_INIT(NULL)
4828 0, /*ob_size*/
4829 "DB", /*tp_name*/
4830 sizeof(DBObject), /*tp_basicsize*/
4831 0, /*tp_itemsize*/
4832 /* methods */
4833 (destructor)DB_dealloc, /*tp_dealloc*/
4834 0, /*tp_print*/
4835 (getattrfunc)DB_getattr, /*tp_getattr*/
4836 0, /*tp_setattr*/
4837 0, /*tp_compare*/
4838 0, /*tp_repr*/
4839 0, /*tp_as_number*/
4840 0, /*tp_as_sequence*/
4841 &DB_mapping,/*tp_as_mapping*/
4842 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004843#ifdef HAVE_WEAKREF
4844 0, /* tp_call */
4845 0, /* tp_str */
4846 0, /* tp_getattro */
4847 0, /* tp_setattro */
4848 0, /* tp_as_buffer */
4849 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4850 0, /* tp_doc */
4851 0, /* tp_traverse */
4852 0, /* tp_clear */
4853 0, /* tp_richcompare */
4854 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4855#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004856};
4857
4858
Neal Norwitz227b5332006-03-22 09:28:35 +00004859static PyTypeObject DBCursor_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004860 PyObject_HEAD_INIT(NULL)
4861 0, /*ob_size*/
4862 "DBCursor", /*tp_name*/
4863 sizeof(DBCursorObject), /*tp_basicsize*/
4864 0, /*tp_itemsize*/
4865 /* methods */
4866 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4867 0, /*tp_print*/
4868 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4869 0, /*tp_setattr*/
4870 0, /*tp_compare*/
4871 0, /*tp_repr*/
4872 0, /*tp_as_number*/
4873 0, /*tp_as_sequence*/
4874 0, /*tp_as_mapping*/
4875 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004876#ifdef HAVE_WEAKREF
4877 0, /* tp_call */
4878 0, /* tp_str */
4879 0, /* tp_getattro */
4880 0, /* tp_setattro */
4881 0, /* tp_as_buffer */
4882 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4883 0, /* tp_doc */
4884 0, /* tp_traverse */
4885 0, /* tp_clear */
4886 0, /* tp_richcompare */
4887 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4888#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004889};
4890
4891
Neal Norwitz227b5332006-03-22 09:28:35 +00004892static PyTypeObject DBEnv_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004893 PyObject_HEAD_INIT(NULL)
4894 0, /*ob_size*/
4895 "DBEnv", /*tp_name*/
4896 sizeof(DBEnvObject), /*tp_basicsize*/
4897 0, /*tp_itemsize*/
4898 /* methods */
4899 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4900 0, /*tp_print*/
4901 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4902 0, /*tp_setattr*/
4903 0, /*tp_compare*/
4904 0, /*tp_repr*/
4905 0, /*tp_as_number*/
4906 0, /*tp_as_sequence*/
4907 0, /*tp_as_mapping*/
4908 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004909#ifdef HAVE_WEAKREF
4910 0, /* tp_call */
4911 0, /* tp_str */
4912 0, /* tp_getattro */
4913 0, /* tp_setattro */
4914 0, /* tp_as_buffer */
4915 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4916 0, /* tp_doc */
4917 0, /* tp_traverse */
4918 0, /* tp_clear */
4919 0, /* tp_richcompare */
4920 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4921#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004922};
4923
Neal Norwitz227b5332006-03-22 09:28:35 +00004924static PyTypeObject DBTxn_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004925 PyObject_HEAD_INIT(NULL)
4926 0, /*ob_size*/
4927 "DBTxn", /*tp_name*/
4928 sizeof(DBTxnObject), /*tp_basicsize*/
4929 0, /*tp_itemsize*/
4930 /* methods */
4931 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4932 0, /*tp_print*/
4933 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4934 0, /*tp_setattr*/
4935 0, /*tp_compare*/
4936 0, /*tp_repr*/
4937 0, /*tp_as_number*/
4938 0, /*tp_as_sequence*/
4939 0, /*tp_as_mapping*/
4940 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004941#ifdef HAVE_WEAKREF
4942 0, /* tp_call */
4943 0, /* tp_str */
4944 0, /* tp_getattro */
4945 0, /* tp_setattro */
4946 0, /* tp_as_buffer */
4947 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4948 0, /* tp_doc */
4949 0, /* tp_traverse */
4950 0, /* tp_clear */
4951 0, /* tp_richcompare */
4952 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4953#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004954};
4955
4956
Neal Norwitz227b5332006-03-22 09:28:35 +00004957static PyTypeObject DBLock_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004958 PyObject_HEAD_INIT(NULL)
4959 0, /*ob_size*/
4960 "DBLock", /*tp_name*/
4961 sizeof(DBLockObject), /*tp_basicsize*/
4962 0, /*tp_itemsize*/
4963 /* methods */
4964 (destructor)DBLock_dealloc, /*tp_dealloc*/
4965 0, /*tp_print*/
4966 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4967 0, /*tp_setattr*/
4968 0, /*tp_compare*/
4969 0, /*tp_repr*/
4970 0, /*tp_as_number*/
4971 0, /*tp_as_sequence*/
4972 0, /*tp_as_mapping*/
4973 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004974#ifdef HAVE_WEAKREF
4975 0, /* tp_call */
4976 0, /* tp_str */
4977 0, /* tp_getattro */
4978 0, /* tp_setattro */
4979 0, /* tp_as_buffer */
4980 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4981 0, /* tp_doc */
4982 0, /* tp_traverse */
4983 0, /* tp_clear */
4984 0, /* tp_richcompare */
4985 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4986#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004987};
4988
4989
4990/* --------------------------------------------------------------------- */
4991/* Module-level functions */
4992
4993static PyObject*
4994DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4995{
4996 PyObject* dbenvobj = NULL;
4997 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004998 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004999
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005000 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5001 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005002 return NULL;
5003 if (dbenvobj == Py_None)
5004 dbenvobj = NULL;
5005 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5006 makeTypeError("DBEnv", dbenvobj);
5007 return NULL;
5008 }
5009
5010 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5011}
5012
5013
5014static PyObject*
5015DBEnv_construct(PyObject* self, PyObject* args)
5016{
5017 int flags = 0;
5018 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5019 return (PyObject* )newDBEnvObject(flags);
5020}
5021
5022
5023static char bsddb_version_doc[] =
5024"Returns a tuple of major, minor, and patch release numbers of the\n\
5025underlying DB library.";
5026
5027static PyObject*
5028bsddb_version(PyObject* self, PyObject* args)
5029{
5030 int major, minor, patch;
5031
5032 if (!PyArg_ParseTuple(args, ":version"))
5033 return NULL;
5034 db_version(&major, &minor, &patch);
5035 return Py_BuildValue("(iii)", major, minor, patch);
5036}
5037
5038
5039/* List of functions defined in the module */
5040
5041static PyMethodDef bsddb_methods[] = {
5042 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5043 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5044 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5045 {NULL, NULL} /* sentinel */
5046};
5047
5048
5049/* --------------------------------------------------------------------- */
5050/* Module initialization */
5051
5052
5053/* Convenience routine to export an integer value.
5054 * Errors are silently ignored, for better or for worse...
5055 */
5056#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5057
Gregory P. Smith41631e82003-09-21 00:08:14 +00005058#define MODULE_NAME_MAX_LEN 11
5059static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005060
5061DL_EXPORT(void) init_bsddb(void)
5062{
5063 PyObject* m;
5064 PyObject* d;
5065 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5066 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5067 PyObject* cvsid_s = PyString_FromString( rcs_id );
5068
5069 /* Initialize the type of the new type objects here; doing it here
5070 is required for portability to Windows without requiring C++. */
5071 DB_Type.ob_type = &PyType_Type;
5072 DBCursor_Type.ob_type = &PyType_Type;
5073 DBEnv_Type.ob_type = &PyType_Type;
5074 DBTxn_Type.ob_type = &PyType_Type;
5075 DBLock_Type.ob_type = &PyType_Type;
5076
5077
Mark Hammonda69d4092003-04-22 23:13:27 +00005078#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005079 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005080 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005081#endif
5082
5083 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005084 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005085 if (m == NULL)
5086 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005087
5088 /* Add some symbolic constants to the module */
5089 d = PyModule_GetDict(m);
5090 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5091 PyDict_SetItemString(d, "cvsid", cvsid_s);
5092 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5093 Py_DECREF(pybsddb_version_s);
5094 pybsddb_version_s = NULL;
5095 Py_DECREF(cvsid_s);
5096 cvsid_s = NULL;
5097 Py_DECREF(db_version_s);
5098 db_version_s = NULL;
5099
5100 ADD_INT(d, DB_VERSION_MAJOR);
5101 ADD_INT(d, DB_VERSION_MINOR);
5102 ADD_INT(d, DB_VERSION_PATCH);
5103
5104 ADD_INT(d, DB_MAX_PAGES);
5105 ADD_INT(d, DB_MAX_RECORDS);
5106
Gregory P. Smith41631e82003-09-21 00:08:14 +00005107#if (DBVER >= 42)
5108 ADD_INT(d, DB_RPCCLIENT);
5109#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005110 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005111 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5112 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5113#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005114 ADD_INT(d, DB_XA_CREATE);
5115
5116 ADD_INT(d, DB_CREATE);
5117 ADD_INT(d, DB_NOMMAP);
5118 ADD_INT(d, DB_THREAD);
5119
5120 ADD_INT(d, DB_FORCE);
5121 ADD_INT(d, DB_INIT_CDB);
5122 ADD_INT(d, DB_INIT_LOCK);
5123 ADD_INT(d, DB_INIT_LOG);
5124 ADD_INT(d, DB_INIT_MPOOL);
5125 ADD_INT(d, DB_INIT_TXN);
5126#if (DBVER >= 32)
5127 ADD_INT(d, DB_JOINENV);
5128#endif
5129
5130 ADD_INT(d, DB_RECOVER);
5131 ADD_INT(d, DB_RECOVER_FATAL);
5132 ADD_INT(d, DB_TXN_NOSYNC);
5133 ADD_INT(d, DB_USE_ENVIRON);
5134 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5135
5136 ADD_INT(d, DB_LOCKDOWN);
5137 ADD_INT(d, DB_PRIVATE);
5138 ADD_INT(d, DB_SYSTEM_MEM);
5139
5140 ADD_INT(d, DB_TXN_SYNC);
5141 ADD_INT(d, DB_TXN_NOWAIT);
5142
5143 ADD_INT(d, DB_EXCL);
5144 ADD_INT(d, DB_FCNTL_LOCKING);
5145 ADD_INT(d, DB_ODDFILESIZE);
5146 ADD_INT(d, DB_RDWRMASTER);
5147 ADD_INT(d, DB_RDONLY);
5148 ADD_INT(d, DB_TRUNCATE);
5149#if (DBVER >= 32)
5150 ADD_INT(d, DB_EXTENT);
5151 ADD_INT(d, DB_CDB_ALLDB);
5152 ADD_INT(d, DB_VERIFY);
5153#endif
5154 ADD_INT(d, DB_UPGRADE);
5155
5156 ADD_INT(d, DB_AGGRESSIVE);
5157 ADD_INT(d, DB_NOORDERCHK);
5158 ADD_INT(d, DB_ORDERCHKONLY);
5159 ADD_INT(d, DB_PR_PAGE);
5160#if ! (DBVER >= 33)
5161 ADD_INT(d, DB_VRFY_FLAGMASK);
5162 ADD_INT(d, DB_PR_HEADERS);
5163#endif
5164 ADD_INT(d, DB_PR_RECOVERYTEST);
5165 ADD_INT(d, DB_SALVAGE);
5166
5167 ADD_INT(d, DB_LOCK_NORUN);
5168 ADD_INT(d, DB_LOCK_DEFAULT);
5169 ADD_INT(d, DB_LOCK_OLDEST);
5170 ADD_INT(d, DB_LOCK_RANDOM);
5171 ADD_INT(d, DB_LOCK_YOUNGEST);
5172#if (DBVER >= 33)
5173 ADD_INT(d, DB_LOCK_MAXLOCKS);
5174 ADD_INT(d, DB_LOCK_MINLOCKS);
5175 ADD_INT(d, DB_LOCK_MINWRITE);
5176#endif
5177
5178
5179#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005180 /* docs say to use zero instead */
5181 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005182#else
5183 ADD_INT(d, DB_LOCK_CONFLICT);
5184#endif
5185
5186 ADD_INT(d, DB_LOCK_DUMP);
5187 ADD_INT(d, DB_LOCK_GET);
5188 ADD_INT(d, DB_LOCK_INHERIT);
5189 ADD_INT(d, DB_LOCK_PUT);
5190 ADD_INT(d, DB_LOCK_PUT_ALL);
5191 ADD_INT(d, DB_LOCK_PUT_OBJ);
5192
5193 ADD_INT(d, DB_LOCK_NG);
5194 ADD_INT(d, DB_LOCK_READ);
5195 ADD_INT(d, DB_LOCK_WRITE);
5196 ADD_INT(d, DB_LOCK_NOWAIT);
5197#if (DBVER >= 32)
5198 ADD_INT(d, DB_LOCK_WAIT);
5199#endif
5200 ADD_INT(d, DB_LOCK_IWRITE);
5201 ADD_INT(d, DB_LOCK_IREAD);
5202 ADD_INT(d, DB_LOCK_IWR);
5203#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005204#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005205 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005206#else
5207 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5208#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005209 ADD_INT(d, DB_LOCK_WWRITE);
5210#endif
5211
5212 ADD_INT(d, DB_LOCK_RECORD);
5213 ADD_INT(d, DB_LOCK_UPGRADE);
5214#if (DBVER >= 32)
5215 ADD_INT(d, DB_LOCK_SWITCH);
5216#endif
5217#if (DBVER >= 33)
5218 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5219#endif
5220
5221 ADD_INT(d, DB_LOCK_NOWAIT);
5222 ADD_INT(d, DB_LOCK_RECORD);
5223 ADD_INT(d, DB_LOCK_UPGRADE);
5224
5225#if (DBVER >= 33)
5226 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005227#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005228 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005229#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005230 ADD_INT(d, DB_LSTAT_FREE);
5231 ADD_INT(d, DB_LSTAT_HELD);
5232#if (DBVER == 33)
5233 ADD_INT(d, DB_LSTAT_NOGRANT);
5234#endif
5235 ADD_INT(d, DB_LSTAT_PENDING);
5236 ADD_INT(d, DB_LSTAT_WAITING);
5237#endif
5238
5239 ADD_INT(d, DB_ARCH_ABS);
5240 ADD_INT(d, DB_ARCH_DATA);
5241 ADD_INT(d, DB_ARCH_LOG);
5242
5243 ADD_INT(d, DB_BTREE);
5244 ADD_INT(d, DB_HASH);
5245 ADD_INT(d, DB_RECNO);
5246 ADD_INT(d, DB_QUEUE);
5247 ADD_INT(d, DB_UNKNOWN);
5248
5249 ADD_INT(d, DB_DUP);
5250 ADD_INT(d, DB_DUPSORT);
5251 ADD_INT(d, DB_RECNUM);
5252 ADD_INT(d, DB_RENUMBER);
5253 ADD_INT(d, DB_REVSPLITOFF);
5254 ADD_INT(d, DB_SNAPSHOT);
5255
5256 ADD_INT(d, DB_JOIN_NOSORT);
5257
5258 ADD_INT(d, DB_AFTER);
5259 ADD_INT(d, DB_APPEND);
5260 ADD_INT(d, DB_BEFORE);
5261 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005262#if (DBVER >= 41)
5263 _addIntToDict(d, "DB_CHECKPOINT", 0);
5264#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005265 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005266 ADD_INT(d, DB_CURLSN);
5267#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005268#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005269 ADD_INT(d, DB_COMMIT);
5270#endif
5271 ADD_INT(d, DB_CONSUME);
5272#if (DBVER >= 32)
5273 ADD_INT(d, DB_CONSUME_WAIT);
5274#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005275 ADD_INT(d, DB_CURRENT);
5276#if (DBVER >= 33)
5277 ADD_INT(d, DB_FAST_STAT);
5278#endif
5279 ADD_INT(d, DB_FIRST);
5280 ADD_INT(d, DB_FLUSH);
5281 ADD_INT(d, DB_GET_BOTH);
5282 ADD_INT(d, DB_GET_RECNO);
5283 ADD_INT(d, DB_JOIN_ITEM);
5284 ADD_INT(d, DB_KEYFIRST);
5285 ADD_INT(d, DB_KEYLAST);
5286 ADD_INT(d, DB_LAST);
5287 ADD_INT(d, DB_NEXT);
5288 ADD_INT(d, DB_NEXT_DUP);
5289 ADD_INT(d, DB_NEXT_NODUP);
5290 ADD_INT(d, DB_NODUPDATA);
5291 ADD_INT(d, DB_NOOVERWRITE);
5292 ADD_INT(d, DB_NOSYNC);
5293 ADD_INT(d, DB_POSITION);
5294 ADD_INT(d, DB_PREV);
5295 ADD_INT(d, DB_PREV_NODUP);
5296 ADD_INT(d, DB_RECORDCOUNT);
5297 ADD_INT(d, DB_SET);
5298 ADD_INT(d, DB_SET_RANGE);
5299 ADD_INT(d, DB_SET_RECNO);
5300 ADD_INT(d, DB_WRITECURSOR);
5301
5302 ADD_INT(d, DB_OPFLAGS_MASK);
5303 ADD_INT(d, DB_RMW);
5304#if (DBVER >= 33)
5305 ADD_INT(d, DB_DIRTY_READ);
5306 ADD_INT(d, DB_MULTIPLE);
5307 ADD_INT(d, DB_MULTIPLE_KEY);
5308#endif
5309
Gregory P. Smith29602d22006-01-24 09:46:48 +00005310#if (DBVER >= 44)
5311 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5312 ADD_INT(d, DB_READ_COMMITTED);
5313#endif
5314
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005315#if (DBVER >= 33)
5316 ADD_INT(d, DB_DONOTINDEX);
5317#endif
5318
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005319#if (DBVER >= 41)
5320 _addIntToDict(d, "DB_INCOMPLETE", 0);
5321#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005322 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005323#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005324 ADD_INT(d, DB_KEYEMPTY);
5325 ADD_INT(d, DB_KEYEXIST);
5326 ADD_INT(d, DB_LOCK_DEADLOCK);
5327 ADD_INT(d, DB_LOCK_NOTGRANTED);
5328 ADD_INT(d, DB_NOSERVER);
5329 ADD_INT(d, DB_NOSERVER_HOME);
5330 ADD_INT(d, DB_NOSERVER_ID);
5331 ADD_INT(d, DB_NOTFOUND);
5332 ADD_INT(d, DB_OLD_VERSION);
5333 ADD_INT(d, DB_RUNRECOVERY);
5334 ADD_INT(d, DB_VERIFY_BAD);
5335#if (DBVER >= 33)
5336 ADD_INT(d, DB_PAGE_NOTFOUND);
5337 ADD_INT(d, DB_SECONDARY_BAD);
5338#endif
5339#if (DBVER >= 40)
5340 ADD_INT(d, DB_STAT_CLEAR);
5341 ADD_INT(d, DB_REGION_INIT);
5342 ADD_INT(d, DB_NOLOCKING);
5343 ADD_INT(d, DB_YIELDCPU);
5344 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5345 ADD_INT(d, DB_NOPANIC);
5346#endif
5347
Gregory P. Smith41631e82003-09-21 00:08:14 +00005348#if (DBVER >= 42)
5349 ADD_INT(d, DB_TIME_NOTGRANTED);
5350 ADD_INT(d, DB_TXN_NOT_DURABLE);
5351 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5352 ADD_INT(d, DB_LOG_AUTOREMOVE);
5353 ADD_INT(d, DB_DIRECT_LOG);
5354 ADD_INT(d, DB_DIRECT_DB);
5355 ADD_INT(d, DB_INIT_REP);
5356 ADD_INT(d, DB_ENCRYPT);
5357 ADD_INT(d, DB_CHKSUM);
5358#endif
5359
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005360#if (DBVER >= 43)
5361 ADD_INT(d, DB_LOG_INMEMORY);
5362 ADD_INT(d, DB_BUFFER_SMALL);
5363#endif
5364
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005365#if (DBVER >= 41)
5366 ADD_INT(d, DB_ENCRYPT_AES);
5367 ADD_INT(d, DB_AUTO_COMMIT);
5368#else
5369 /* allow berkeleydb 4.1 aware apps to run on older versions */
5370 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5371#endif
5372
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005373 ADD_INT(d, EINVAL);
5374 ADD_INT(d, EACCES);
5375 ADD_INT(d, ENOSPC);
5376 ADD_INT(d, ENOMEM);
5377 ADD_INT(d, EAGAIN);
5378 ADD_INT(d, EBUSY);
5379 ADD_INT(d, EEXIST);
5380 ADD_INT(d, ENOENT);
5381 ADD_INT(d, EPERM);
5382
Barry Warsaw1baa9822003-03-31 19:51:29 +00005383#if (DBVER >= 40)
5384 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5385 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5386#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005387
5388 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005389 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005390 PyDict_SetItemString(d, "DBError", DBError);
5391
Gregory P. Smithe9477062005-06-04 06:46:59 +00005392 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5393 * from both DBError and KeyError, since the API only supports
5394 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005395 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005396 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5397 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005398 Py_file_input, d, d);
5399 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005400 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005401 PyDict_DelItemString(d, "KeyError");
5402
5403
5404 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005405#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005406 PyDict_SetItemString(d, #name, name)
5407
5408#if !INCOMPLETE_IS_WARNING
5409 MAKE_EX(DBIncompleteError);
5410#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005411 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005412 MAKE_EX(DBKeyEmptyError);
5413 MAKE_EX(DBKeyExistError);
5414 MAKE_EX(DBLockDeadlockError);
5415 MAKE_EX(DBLockNotGrantedError);
5416 MAKE_EX(DBOldVersionError);
5417 MAKE_EX(DBRunRecoveryError);
5418 MAKE_EX(DBVerifyBadError);
5419 MAKE_EX(DBNoServerError);
5420 MAKE_EX(DBNoServerHomeError);
5421 MAKE_EX(DBNoServerIDError);
5422#if (DBVER >= 33)
5423 MAKE_EX(DBPageNotFoundError);
5424 MAKE_EX(DBSecondaryBadError);
5425#endif
5426
5427 MAKE_EX(DBInvalidArgError);
5428 MAKE_EX(DBAccessError);
5429 MAKE_EX(DBNoSpaceError);
5430 MAKE_EX(DBNoMemoryError);
5431 MAKE_EX(DBAgainError);
5432 MAKE_EX(DBBusyError);
5433 MAKE_EX(DBFileExistsError);
5434 MAKE_EX(DBNoSuchFileError);
5435 MAKE_EX(DBPermissionsError);
5436
5437#undef MAKE_EX
5438
5439 /* Check for errors */
5440 if (PyErr_Occurred()) {
5441 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005442 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005443 }
5444}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005445
5446/* allow this module to be named _pybsddb so that it can be installed
5447 * and imported on top of python >= 2.3 that includes its own older
5448 * copy of the library named _bsddb without importing the old version. */
5449DL_EXPORT(void) init_pybsddb(void)
5450{
5451 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5452 init_bsddb();
5453}