blob: 68489e9a48e565b41d9c5d9a836f77043ce209fc [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 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Thomas Wouters89f507f2006-12-13 04:49:30 +0000101#define PY_BSDDB_VERSION "4.4.6"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000106typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298static PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
Neal Norwitz227b5332006-03-22 09:28:35 +0000301static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000548#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000559#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000603 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
Gregory P. Smithe9477062005-06-04 06:46:59 +0000706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000752#if (DBVER >= 43)
753/* add an db_seq_t to a dictionary using the given name as a key */
754static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
755{
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000760 Py_XDECREF(v);
761}
762#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763
764
765
766/* --------------------------------------------------------------------- */
767/* Allocators and deallocators */
768
769static DBObject*
770newDBObject(DBEnvObject* arg, int flags)
771{
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
775
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (self == NULL)
778 return NULL;
779
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784#if (DBVER >= 33)
785 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000786 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 self->primaryDBType = 0;
788#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000789#ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
798 }
799
800 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000801 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000811 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000813 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000817 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
822 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000823 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824 self = NULL;
825 }
826 return self;
827}
828
829
830static void
831DB_dealloc(DBObject* self)
832{
833 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000837 (self->myenvobj && self->myenvobj->db_env))
838 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000842#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846#endif
847 }
848 self->db = NULL;
849 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000850#ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
853 }
854#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
858 }
859#if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
863 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
867 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870}
871
872
873static DBCursorObject*
874newDBCursorObject(DBC* dbc, DBObject* db)
875{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 if (self == NULL)
878 return NULL;
879
880 self->dbc = dbc;
881 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000882#ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 Py_INCREF(self->mydb);
886 return self;
887}
888
889
890static void
891DBCursor_dealloc(DBCursorObject* self)
892{
893 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000894
895#ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
898 }
899#endif
900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000911 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
914 }
915 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917}
918
919
920static DBEnvObject*
921newDBEnvObject(int flags)
922{
923 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925 if (self == NULL)
926 return NULL;
927
928 self->closed = 1;
929 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000932#ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000940 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 self = NULL;
942 }
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
945 }
946 return self;
947}
948
949
950static void
951DBEnv_dealloc(DBEnvObject* self)
952{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953#ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
956 }
957#endif
958
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000959 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
963 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965}
966
967
968static DBTxnObject*
969newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
970{
971 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000973 if (self == NULL)
974 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000977#ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980
981 MYDB_BEGIN_ALLOW_THREADS;
982#if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984#else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000989 Py_DECREF(self->env);
990 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 self = NULL;
992 }
993 return self;
994}
995
996
997static void
998DBTxn_dealloc(DBTxnObject* self)
999{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000#ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1003 }
1004#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005
Gregory P. Smith31c50652004-06-28 01:20:40 +00001006#ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010#if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012#else
1013 txn_abort(self->txn);
1014#endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1018 }
1019#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020
Neal Norwitz62a21122006-01-25 05:21:55 +00001021 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023}
1024
1025
1026static DBLockObject*
1027newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1029{
1030 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032 if (self == NULL)
1033 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001034#ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037
1038 MYDB_BEGIN_ALLOW_THREADS;
1039#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001042#else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044#endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001047 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001048 self = NULL;
1049 }
1050
1051 return self;
1052}
1053
1054
1055static void
1056DBLock_dealloc(DBLockObject* self)
1057{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001058#ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1061 }
1062#endif
1063 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001066}
1067
1068
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001069#if (DBVER >= 43)
1070static DBSequenceObject*
1071newDBSequenceObject(DBObject* mydb, int flags)
1072{
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079#ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081#endif
1082
1083
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1091 }
1092
1093 return self;
1094}
1095
1096
1097static void
1098DBSequence_dealloc(DBSequenceObject* self)
1099{
1100#ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1103 }
1104#endif
1105
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108}
1109#endif
1110
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111/* --------------------------------------------------------------------- */
1112/* DB methods */
1113
1114static PyObject*
1115DB_append(DBObject* self, PyObject* args)
1116{
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1122
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001124 return NULL;
1125
1126 CHECK_DB_NOT_CLOSED(self);
1127
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1135
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1138
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1141
1142 return PyInt_FromLong(recno);
1143}
1144
1145
1146#if (DBVER >= 33)
1147
1148static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151{
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001156 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001157 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001158
1159
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1162
Thomas Woutersb3153832006-03-08 01:47:19 +00001163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001169 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001170 result = PyEval_CallObject(callback, args);
1171 }
1172 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 PyErr_Print();
1174 }
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1177 }
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1180 }
1181 else if (PyString_Check(result)) {
1182 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001183 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184
1185 CLEAR_DBT(*secKey);
1186#if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190#else
1191 PyString_AsStringAndSize(result, &data, &size);
1192#endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1199 }
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1204 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 }
1206 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 PyErr_Print();
1211 }
1212
Thomas Woutersb3153832006-03-08 01:47:19 +00001213 Py_XDECREF(args);
1214 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001215
1216 MYDB_END_BLOCK_THREADS;
1217 }
1218 return retval;
1219}
1220
1221
1222static PyObject*
1223DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1224{
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001232 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001233#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237#if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001243 &secondaryDB, &callback, &flags)) {
1244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246 }
1247
1248#if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1256 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001257 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 if (callback == Py_None) {
1259 callback = NULL;
1260 }
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1264 }
1265
1266 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001267 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001268 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1271
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1281 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001282#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001283 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001284#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001286#if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001297#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 MYDB_END_ALLOW_THREADS;
1299
1300 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 secondaryDB->primaryDBType = 0;
1304 }
1305
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1308}
1309
1310
1311#endif
1312
1313
1314static PyObject*
1315DB_close(DBObject* self, PyObject* args)
1316{
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001324 self->db = NULL;
1325 RETURN_IF_ERR();
1326 }
1327 RETURN_NONE();
1328}
1329
1330
1331#if (DBVER >= 32)
1332static PyObject*
1333_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1334{
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001340 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1345
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001353 return NULL;
1354 }
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1357
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1364 }
1365
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1369
Gregory P. Smithe9477062005-06-04 06:46:59 +00001370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1375 }
1376 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001379 FREE_DBT(key);
1380 FREE_DBT(data);
1381 }
1382
1383 RETURN_IF_ERR();
1384 return retval;
1385}
1386
1387static PyObject*
1388DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1389{
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1391}
1392
1393static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001394DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396{
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1398}
1399#endif
1400
1401
1402
1403static PyObject*
1404DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1405{
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001410 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1418
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1424}
1425
1426
1427static PyObject*
1428DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1429{
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001435 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001446 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001447
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001452
1453 FREE_DBT(key);
1454 RETURN_NONE();
1455}
1456
1457
1458static PyObject*
1459DB_fd(DBObject* self, PyObject* args)
1460{
1461 int err, the_fd;
1462
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1472}
1473
1474
1475static PyObject*
1476DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1477{
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001488 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493 return NULL;
1494
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001500 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1507 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001511 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1516
Gregory P. Smithe9477062005-06-04 06:46:59 +00001517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1521 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1527 }
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 FREE_DBT(data);
1535 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001536 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001537
1538 RETURN_IF_ERR();
1539 return retval;
1540}
1541
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001542#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001543static PyObject*
1544DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1545{
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001556 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001557
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1562
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1569 }
1570
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1575 }
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1579 }
1580
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1583
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1587
Gregory P. Smithe9477062005-06-04 06:46:59 +00001588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1592 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1598 }
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1603
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1609
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1611 {
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001615 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001623 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 }
1625 else /* return just the pkey and data */
1626 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001627#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001629#else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1637 }
1638 FREE_DBT(key);
1639
1640 RETURN_IF_ERR();
1641 return retval;
1642}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001643#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001644
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645
1646/* Return size of entry */
1647static PyObject*
1648DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1649{
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001656 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001667 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668 CLEAR_DBT(data);
1669
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001677 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1680 }
1681
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1686}
1687
1688
1689static PyObject*
1690DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1691{
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700
1701
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1705
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001709 if ( !make_dbt(dataobj, &data) ||
1710 !checkTxnObj(txnobj, &txn) )
1711 {
1712 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001714 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715
1716 flags |= DB_GET_BOTH;
1717
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1720 data.flags = DB_DBT_MALLOC;
1721 /* TODO: Is this flag needed? We're passing a data object that should
1722 match what's in the DB, so there should be no need to malloc.
1723 We run the risk of freeing something twice! Check this. */
1724 }
1725
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1729
Gregory P. Smithe9477062005-06-04 06:46:59 +00001730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1735 }
1736 else if (!err) {
1737 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1738 FREE_DBT(data); /* Only if retrieval was successful */
1739 }
1740
1741 FREE_DBT(key);
1742 RETURN_IF_ERR();
1743 return retval;
1744}
1745
1746
1747static PyObject*
1748DB_get_byteswapped(DBObject* self, PyObject* args)
1749{
1750#if (DBVER >= 33)
1751 int err = 0;
1752#endif
1753 int retval = -1;
1754
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1758
1759#if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764#else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768#endif
1769 return PyInt_FromLong(retval);
1770}
1771
1772
1773static PyObject*
1774DB_get_type(DBObject* self, PyObject* args)
1775{
1776 int type;
1777
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001782 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001783 if (type == -1)
1784 return NULL;
1785 return PyInt_FromLong(type);
1786}
1787
1788
1789static PyObject*
1790DB_join(DBObject* self, PyObject* args)
1791{
1792 int err, flags=0;
1793 int length, x;
1794 PyObject* cursorsObj;
1795 DBC** cursors;
1796 DBC* dbc;
1797
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001798 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1799 return NULL;
1800
1801 CHECK_DB_NOT_CLOSED(self);
1802
1803 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001804 PyErr_SetString(PyExc_TypeError,
1805 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001806 return NULL;
1807 }
1808
1809 length = PyObject_Length(cursorsObj);
1810 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001811 if (!cursors) {
1812 PyErr_NoMemory();
1813 return NULL;
1814 }
1815
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 cursors[length] = NULL;
1817 for (x=0; x<length; x++) {
1818 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001819 if (item == NULL) {
1820 free(cursors);
1821 return NULL;
1822 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001824 PyErr_SetString(PyExc_TypeError,
1825 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001826 free(cursors);
1827 return NULL;
1828 }
1829 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001830 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 }
1832
1833 MYDB_BEGIN_ALLOW_THREADS;
1834 err = self->db->join(self->db, cursors, &dbc, flags);
1835 MYDB_END_ALLOW_THREADS;
1836 free(cursors);
1837 RETURN_IF_ERR();
1838
Gregory P. Smith7441e652003-11-03 21:35:31 +00001839 /* FIXME: this is a buggy interface. The returned cursor
1840 contains internal references to the passed in cursors
1841 but does not hold python references to them or prevent
1842 them from being closed prematurely. This can cause
1843 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 return (PyObject*) newDBCursorObject(dbc, self);
1845}
1846
1847
1848static PyObject*
1849DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1850{
1851 int err, flags=0;
1852 PyObject* txnobj = NULL;
1853 PyObject* keyobj;
1854 DBT key;
1855 DB_TXN *txn = NULL;
1856 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001857 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858
1859 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1860 &keyobj, &txnobj, &flags))
1861 return NULL;
1862 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001863 if (!make_dbt(keyobj, &key))
1864 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 return NULL;
1866 if (!checkTxnObj(txnobj, &txn))
1867 return NULL;
1868
1869 MYDB_BEGIN_ALLOW_THREADS;
1870 err = self->db->key_range(self->db, txn, &key, &range, flags);
1871 MYDB_END_ALLOW_THREADS;
1872
1873 RETURN_IF_ERR();
1874 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1875}
1876
1877
1878static PyObject*
1879DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1880{
1881 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1882 char* filename = NULL;
1883 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001884#if (DBVER >= 41)
1885 PyObject *txnobj = NULL;
1886 DB_TXN *txn = NULL;
1887 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001888 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001889 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1890 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001891 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001892 "filename", "dbtype", "flags", "mode", "txn", NULL};
1893#else
1894 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001895 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001896 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1897 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001898 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001899 "filename", "dbtype", "flags", "mode", NULL};
1900#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001901
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001902#if (DBVER >= 41)
1903 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1904 &filename, &dbname, &type, &flags, &mode,
1905 &txnobj))
1906#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001908 &filename, &dbname, &type, &flags,
1909 &mode))
1910#endif
1911 {
1912 PyErr_Clear();
1913 type = DB_UNKNOWN; flags = 0; mode = 0660;
1914 filename = NULL; dbname = NULL;
1915#if (DBVER >= 41)
1916 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1917 kwnames_basic,
1918 &filename, &type, &flags, &mode,
1919 &txnobj))
1920 return NULL;
1921#else
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1923 kwnames_basic,
1924 &filename, &type, &flags, &mode))
1925 return NULL;
1926#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001927 }
1928
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001929#if (DBVER >= 41)
1930 if (!checkTxnObj(txnobj, &txn)) return NULL;
1931#endif
1932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001933 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001934 PyObject *t = Py_BuildValue("(is)", 0,
1935 "Cannot call open() twice for DB object");
1936 PyErr_SetObject(DBError, t);
1937 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001938 return NULL;
1939 }
1940
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001941#if 0 && (DBVER >= 41)
1942 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1943 && (self->myenvobj->flags & DB_INIT_TXN))
1944 {
1945 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1946 * explicitly passed) but we are in a transaction ready environment:
1947 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1948 * to work on BerkeleyDB 4.1 without needing to modify their
1949 * DBEnv or DB open calls.
1950 * TODO make this behaviour of the library configurable.
1951 */
1952 flags |= DB_AUTO_COMMIT;
1953 }
1954#endif
1955
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001957#if (DBVER >= 41)
1958 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1959#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001961#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962 MYDB_END_ALLOW_THREADS;
1963 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001964 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 self->db = NULL;
1966 return NULL;
1967 }
1968
1969 self->flags = flags;
1970 RETURN_NONE();
1971}
1972
1973
1974static PyObject*
1975DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1976{
1977 int flags=0;
1978 PyObject* txnobj = NULL;
1979 int dlen = -1;
1980 int doff = -1;
1981 PyObject* keyobj, *dataobj, *retval;
1982 DBT key, data;
1983 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001984 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001985 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001986
1987 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1988 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1989 return NULL;
1990
1991 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001992 if (!make_key_dbt(self, keyobj, &key, NULL))
1993 return NULL;
1994 if ( !make_dbt(dataobj, &data) ||
1995 !add_partial_dbt(&data, dlen, doff) ||
1996 !checkTxnObj(txnobj, &txn) )
1997 {
1998 FREE_DBT(key);
1999 return NULL;
2000 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002001
2002 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2003 FREE_DBT(key);
2004 return NULL;
2005 }
2006
2007 if (flags & DB_APPEND)
2008 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2009 else {
2010 retval = Py_None;
2011 Py_INCREF(retval);
2012 }
2013 FREE_DBT(key);
2014 return retval;
2015}
2016
2017
2018
2019static PyObject*
2020DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2021{
2022 char* filename;
2023 char* database = NULL;
2024 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002025 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002026
2027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2028 &filename, &database, &flags))
2029 return NULL;
2030 CHECK_DB_NOT_CLOSED(self);
2031
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002032 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002033 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002034 RETURN_IF_ERR();
2035 RETURN_NONE();
2036}
2037
2038
2039
2040static PyObject*
2041DB_rename(DBObject* self, PyObject* args)
2042{
2043 char* filename;
2044 char* database;
2045 char* newname;
2046 int err, flags=0;
2047
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002048 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2049 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002050 return NULL;
2051 CHECK_DB_NOT_CLOSED(self);
2052
2053 MYDB_BEGIN_ALLOW_THREADS;
2054 err = self->db->rename(self->db, filename, database, newname, flags);
2055 MYDB_END_ALLOW_THREADS;
2056 RETURN_IF_ERR();
2057 RETURN_NONE();
2058}
2059
2060
2061static PyObject*
2062DB_set_bt_minkey(DBObject* self, PyObject* args)
2063{
2064 int err, minkey;
2065
2066 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2067 return NULL;
2068 CHECK_DB_NOT_CLOSED(self);
2069
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->set_bt_minkey(self->db, minkey);
2072 MYDB_END_ALLOW_THREADS;
2073 RETURN_IF_ERR();
2074 RETURN_NONE();
2075}
2076
Neal Norwitz84562352005-10-20 04:30:15 +00002077#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002078static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002079_default_cmp(const DBT *leftKey,
2080 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081{
2082 int res;
2083 int lsize = leftKey->size, rsize = rightKey->size;
2084
Georg Brandlef1701f2006-03-07 14:57:48 +00002085 res = memcmp(leftKey->data, rightKey->data,
2086 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002087
2088 if (res == 0) {
2089 if (lsize < rsize) {
2090 res = -1;
2091 }
2092 else if (lsize > rsize) {
2093 res = 1;
2094 }
2095 }
2096 return res;
2097}
2098
2099static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002100_db_compareCallback(DB* db,
2101 const DBT *leftKey,
2102 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103{
2104 int res = 0;
2105 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002106 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002107 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108
2109 if (self == NULL || self->btCompareCallback == NULL) {
2110 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002111 PyErr_SetString(PyExc_TypeError,
2112 (self == 0
2113 ? "DB_bt_compare db is NULL."
2114 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002115 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 PyErr_Print();
2117 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002118 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002119 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120 MYDB_BEGIN_BLOCK_THREADS;
2121
Thomas Woutersb3153832006-03-08 01:47:19 +00002122 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2123 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002125 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002128 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 PyErr_Print();
2132 res = _default_cmp(leftKey, rightKey);
2133 } else if (PyInt_Check(result)) {
2134 res = PyInt_AsLong(result);
2135 } else {
2136 PyErr_SetString(PyExc_TypeError,
2137 "DB_bt_compare callback MUST return an int.");
2138 /* we're in a callback within the DB code, we can't raise */
2139 PyErr_Print();
2140 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002141 }
2142
Thomas Woutersb3153832006-03-08 01:47:19 +00002143 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002144 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002145
2146 MYDB_END_BLOCK_THREADS;
2147 }
2148 return res;
2149}
2150
2151static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002152DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002153{
2154 int err;
2155 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002156 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002157
Georg Brandlef1701f2006-03-07 14:57:48 +00002158 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002159 return NULL;
2160
Georg Brandlef1701f2006-03-07 14:57:48 +00002161 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 if (!PyCallable_Check(comparator)) {
2164 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002165 return NULL;
2166 }
2167
2168 /*
2169 * Perform a test call of the comparator function with two empty
2170 * string objects here. verify that it returns an int (0).
2171 * err if not.
2172 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002173 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002174 result = PyEval_CallObject(comparator, tuple);
2175 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002176 if (result == NULL)
2177 return NULL;
2178 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002179 PyErr_SetString(PyExc_TypeError,
2180 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 } else if (PyInt_AsLong(result) != 0) {
2183 PyErr_SetString(PyExc_TypeError,
2184 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002185 return NULL;
2186 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002187 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188
2189 /* We don't accept multiple set_bt_compare operations, in order to
2190 * simplify the code. This would have no real use, as one cannot
2191 * change the function once the db is opened anyway */
2192 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002193 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002194 return NULL;
2195 }
2196
Georg Brandlef1701f2006-03-07 14:57:48 +00002197 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002198 self->btCompareCallback = comparator;
2199
2200 /* This is to workaround a problem with un-initialized threads (see
2201 comment in DB_associate) */
2202#ifdef WITH_THREAD
2203 PyEval_InitThreads();
2204#endif
2205
Thomas Woutersb3153832006-03-08 01:47:19 +00002206 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
2208 if (err) {
2209 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002210 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211 self->btCompareCallback = NULL;
2212 }
2213
Georg Brandlef1701f2006-03-07 14:57:48 +00002214 RETURN_IF_ERR();
2215 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216}
Neal Norwitz84562352005-10-20 04:30:15 +00002217#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002219
2220static PyObject*
2221DB_set_cachesize(DBObject* self, PyObject* args)
2222{
2223 int err;
2224 int gbytes = 0, bytes = 0, ncache = 0;
2225
2226 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2227 &gbytes,&bytes,&ncache))
2228 return NULL;
2229 CHECK_DB_NOT_CLOSED(self);
2230
2231 MYDB_BEGIN_ALLOW_THREADS;
2232 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2233 MYDB_END_ALLOW_THREADS;
2234 RETURN_IF_ERR();
2235 RETURN_NONE();
2236}
2237
2238
2239static PyObject*
2240DB_set_flags(DBObject* self, PyObject* args)
2241{
2242 int err, flags;
2243
2244 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_flags(self->db, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252
2253 self->setflags |= flags;
2254 RETURN_NONE();
2255}
2256
2257
2258static PyObject*
2259DB_set_h_ffactor(DBObject* self, PyObject* args)
2260{
2261 int err, ffactor;
2262
2263 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2266
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_h_ffactor(self->db, ffactor);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
2276DB_set_h_nelem(DBObject* self, PyObject* args)
2277{
2278 int err, nelem;
2279
2280 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_h_nelem(self->db, nelem);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
2291
2292static PyObject*
2293DB_set_lorder(DBObject* self, PyObject* args)
2294{
2295 int err, lorder;
2296
2297 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2298 return NULL;
2299 CHECK_DB_NOT_CLOSED(self);
2300
2301 MYDB_BEGIN_ALLOW_THREADS;
2302 err = self->db->set_lorder(self->db, lorder);
2303 MYDB_END_ALLOW_THREADS;
2304 RETURN_IF_ERR();
2305 RETURN_NONE();
2306}
2307
2308
2309static PyObject*
2310DB_set_pagesize(DBObject* self, PyObject* args)
2311{
2312 int err, pagesize;
2313
2314 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2315 return NULL;
2316 CHECK_DB_NOT_CLOSED(self);
2317
2318 MYDB_BEGIN_ALLOW_THREADS;
2319 err = self->db->set_pagesize(self->db, pagesize);
2320 MYDB_END_ALLOW_THREADS;
2321 RETURN_IF_ERR();
2322 RETURN_NONE();
2323}
2324
2325
2326static PyObject*
2327DB_set_re_delim(DBObject* self, PyObject* args)
2328{
2329 int err;
2330 char delim;
2331
2332 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2333 PyErr_Clear();
2334 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2335 return NULL;
2336 }
2337
2338 CHECK_DB_NOT_CLOSED(self);
2339
2340 MYDB_BEGIN_ALLOW_THREADS;
2341 err = self->db->set_re_delim(self->db, delim);
2342 MYDB_END_ALLOW_THREADS;
2343 RETURN_IF_ERR();
2344 RETURN_NONE();
2345}
2346
2347static PyObject*
2348DB_set_re_len(DBObject* self, PyObject* args)
2349{
2350 int err, len;
2351
2352 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2353 return NULL;
2354 CHECK_DB_NOT_CLOSED(self);
2355
2356 MYDB_BEGIN_ALLOW_THREADS;
2357 err = self->db->set_re_len(self->db, len);
2358 MYDB_END_ALLOW_THREADS;
2359 RETURN_IF_ERR();
2360 RETURN_NONE();
2361}
2362
2363
2364static PyObject*
2365DB_set_re_pad(DBObject* self, PyObject* args)
2366{
2367 int err;
2368 char pad;
2369
2370 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2371 PyErr_Clear();
2372 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2373 return NULL;
2374 }
2375 CHECK_DB_NOT_CLOSED(self);
2376
2377 MYDB_BEGIN_ALLOW_THREADS;
2378 err = self->db->set_re_pad(self->db, pad);
2379 MYDB_END_ALLOW_THREADS;
2380 RETURN_IF_ERR();
2381 RETURN_NONE();
2382}
2383
2384
2385static PyObject*
2386DB_set_re_source(DBObject* self, PyObject* args)
2387{
2388 int err;
2389 char *re_source;
2390
2391 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2392 return NULL;
2393 CHECK_DB_NOT_CLOSED(self);
2394
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_source(self->db, re_source);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2400}
2401
2402
2403#if (DBVER >= 32)
2404static PyObject*
2405DB_set_q_extentsize(DBObject* self, PyObject* args)
2406{
2407 int err;
2408 int extentsize;
2409
2410 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2413
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_q_extentsize(self->db, extentsize);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2419}
2420#endif
2421
2422static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002423DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002424{
2425 int err, flags = 0, type;
2426 void* sp;
2427 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002428#if (DBVER >= 43)
2429 PyObject* txnobj = NULL;
2430 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002431 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002432#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002433 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002435
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002436#if (DBVER >= 43)
2437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2438 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002439 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002440 if (!checkTxnObj(txnobj, &txn))
2441 return NULL;
2442#else
2443 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2444 return NULL;
2445#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002446 CHECK_DB_NOT_CLOSED(self);
2447
2448 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002449#if (DBVER >= 43)
2450 err = self->db->stat(self->db, txn, &sp, flags);
2451#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002452 err = self->db->stat(self->db, &sp, flags);
2453#else
2454 err = self->db->stat(self->db, &sp, NULL, flags);
2455#endif
2456 MYDB_END_ALLOW_THREADS;
2457 RETURN_IF_ERR();
2458
2459 self->haveStat = 1;
2460
2461 /* Turn the stat structure into a dictionary */
2462 type = _DB_get_type(self);
2463 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2464 free(sp);
2465 return NULL;
2466 }
2467
2468#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2469#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2470#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2471
2472 switch (type) {
2473 case DB_HASH:
2474 MAKE_HASH_ENTRY(magic);
2475 MAKE_HASH_ENTRY(version);
2476 MAKE_HASH_ENTRY(nkeys);
2477 MAKE_HASH_ENTRY(ndata);
2478 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002479#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002480 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002481#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002482 MAKE_HASH_ENTRY(ffactor);
2483 MAKE_HASH_ENTRY(buckets);
2484 MAKE_HASH_ENTRY(free);
2485 MAKE_HASH_ENTRY(bfree);
2486 MAKE_HASH_ENTRY(bigpages);
2487 MAKE_HASH_ENTRY(big_bfree);
2488 MAKE_HASH_ENTRY(overflows);
2489 MAKE_HASH_ENTRY(ovfl_free);
2490 MAKE_HASH_ENTRY(dup);
2491 MAKE_HASH_ENTRY(dup_free);
2492 break;
2493
2494 case DB_BTREE:
2495 case DB_RECNO:
2496 MAKE_BT_ENTRY(magic);
2497 MAKE_BT_ENTRY(version);
2498 MAKE_BT_ENTRY(nkeys);
2499 MAKE_BT_ENTRY(ndata);
2500 MAKE_BT_ENTRY(pagesize);
2501 MAKE_BT_ENTRY(minkey);
2502 MAKE_BT_ENTRY(re_len);
2503 MAKE_BT_ENTRY(re_pad);
2504 MAKE_BT_ENTRY(levels);
2505 MAKE_BT_ENTRY(int_pg);
2506 MAKE_BT_ENTRY(leaf_pg);
2507 MAKE_BT_ENTRY(dup_pg);
2508 MAKE_BT_ENTRY(over_pg);
2509 MAKE_BT_ENTRY(free);
2510 MAKE_BT_ENTRY(int_pgfree);
2511 MAKE_BT_ENTRY(leaf_pgfree);
2512 MAKE_BT_ENTRY(dup_pgfree);
2513 MAKE_BT_ENTRY(over_pgfree);
2514 break;
2515
2516 case DB_QUEUE:
2517 MAKE_QUEUE_ENTRY(magic);
2518 MAKE_QUEUE_ENTRY(version);
2519 MAKE_QUEUE_ENTRY(nkeys);
2520 MAKE_QUEUE_ENTRY(ndata);
2521 MAKE_QUEUE_ENTRY(pagesize);
2522 MAKE_QUEUE_ENTRY(pages);
2523 MAKE_QUEUE_ENTRY(re_len);
2524 MAKE_QUEUE_ENTRY(re_pad);
2525 MAKE_QUEUE_ENTRY(pgfree);
2526#if (DBVER == 31)
2527 MAKE_QUEUE_ENTRY(start);
2528#endif
2529 MAKE_QUEUE_ENTRY(first_recno);
2530 MAKE_QUEUE_ENTRY(cur_recno);
2531 break;
2532
2533 default:
2534 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2535 Py_DECREF(d);
2536 d = NULL;
2537 }
2538
2539#undef MAKE_HASH_ENTRY
2540#undef MAKE_BT_ENTRY
2541#undef MAKE_QUEUE_ENTRY
2542
2543 free(sp);
2544 return d;
2545}
2546
2547static PyObject*
2548DB_sync(DBObject* self, PyObject* args)
2549{
2550 int err;
2551 int flags = 0;
2552
2553 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2554 return NULL;
2555 CHECK_DB_NOT_CLOSED(self);
2556
2557 MYDB_BEGIN_ALLOW_THREADS;
2558 err = self->db->sync(self->db, flags);
2559 MYDB_END_ALLOW_THREADS;
2560 RETURN_IF_ERR();
2561 RETURN_NONE();
2562}
2563
2564
2565#if (DBVER >= 33)
2566static PyObject*
2567DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2568{
2569 int err, flags=0;
2570 u_int32_t count=0;
2571 PyObject* txnobj = NULL;
2572 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002573 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002574
2575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2576 &txnobj, &flags))
2577 return NULL;
2578 CHECK_DB_NOT_CLOSED(self);
2579 if (!checkTxnObj(txnobj, &txn))
2580 return NULL;
2581
2582 MYDB_BEGIN_ALLOW_THREADS;
2583 err = self->db->truncate(self->db, txn, &count, flags);
2584 MYDB_END_ALLOW_THREADS;
2585 RETURN_IF_ERR();
2586 return PyInt_FromLong(count);
2587}
2588#endif
2589
2590
2591static PyObject*
2592DB_upgrade(DBObject* self, PyObject* args)
2593{
2594 int err, flags=0;
2595 char *filename;
2596
2597 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2598 return NULL;
2599 CHECK_DB_NOT_CLOSED(self);
2600
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->upgrade(self->db, filename, flags);
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605 RETURN_NONE();
2606}
2607
2608
2609static PyObject*
2610DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2611{
2612 int err, flags=0;
2613 char* fileName;
2614 char* dbName=NULL;
2615 char* outFileName=NULL;
2616 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002617 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002618 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002619
2620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2621 &fileName, &dbName, &outFileName, &flags))
2622 return NULL;
2623
2624 CHECK_DB_NOT_CLOSED(self);
2625 if (outFileName)
2626 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002627 /* XXX(nnorwitz): it should probably be an exception if outFile
2628 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629
2630 MYDB_BEGIN_ALLOW_THREADS;
2631 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2632 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002633 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002634 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002635
2636 /* DB.verify acts as a DB handle destructor (like close); this was
2637 * documented in BerkeleyDB 4.2 but had the undocumented effect
2638 * of not being safe in prior versions while still requiring an explicit
2639 * DB.close call afterwards. Lets call close for the user to emulate
2640 * the safe 4.2 behaviour. */
2641#if (DBVER <= 41)
2642 self->db->close(self->db, 0);
2643#endif
2644 self->db = NULL;
2645
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002646 RETURN_IF_ERR();
2647 RETURN_NONE();
2648}
2649
2650
2651static PyObject*
2652DB_set_get_returns_none(DBObject* self, PyObject* args)
2653{
2654 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002655 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002656
2657 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2658 return NULL;
2659 CHECK_DB_NOT_CLOSED(self);
2660
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002661 if (self->moduleFlags.getReturnsNone)
2662 ++oldValue;
2663 if (self->moduleFlags.cursorSetReturnsNone)
2664 ++oldValue;
2665 self->moduleFlags.getReturnsNone = (flags >= 1);
2666 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002667 return PyInt_FromLong(oldValue);
2668}
2669
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002670#if (DBVER >= 41)
2671static PyObject*
2672DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2673{
2674 int err;
2675 u_int32_t flags=0;
2676 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002677 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002678
2679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2680 &passwd, &flags)) {
2681 return NULL;
2682 }
2683
2684 MYDB_BEGIN_ALLOW_THREADS;
2685 err = self->db->set_encrypt(self->db, passwd, flags);
2686 MYDB_END_ALLOW_THREADS;
2687
2688 RETURN_IF_ERR();
2689 RETURN_NONE();
2690}
2691#endif /* DBVER >= 41 */
2692
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002693
2694/*-------------------------------------------------------------- */
2695/* Mapping and Dictionary-like access routines */
2696
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002697Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002698{
2699 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002700 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002701 int flags = 0;
2702 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002703 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704
2705 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002706 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2707 PyErr_SetObject(DBError, t);
2708 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 return -1;
2710 }
2711
2712 if (self->haveStat) { /* Has the stat function been called recently? If
2713 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002714 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002715 }
2716
2717 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002718redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002719#if (DBVER >= 43)
2720 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2721#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002722 err = self->db->stat(self->db, &sp, flags);
2723#else
2724 err = self->db->stat(self->db, &sp, NULL, flags);
2725#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002726
2727 /* All the stat structures have matching fields upto the ndata field,
2728 so we can use any of them for the type cast */
2729 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2730
2731 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2732 * redo a full stat to make sure.
2733 * Fixes SF python bug 1493322, pybsddb bug 1184012
2734 */
2735 if (size == 0 && (flags & DB_FAST_STAT)) {
2736 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002737 if (!err)
2738 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002739 goto redo_stat_for_length;
2740 }
2741
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002742 MYDB_END_ALLOW_THREADS;
2743
2744 if (err)
2745 return -1;
2746
2747 self->haveStat = 1;
2748
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002749 free(sp);
2750 return size;
2751}
2752
2753
2754PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2755{
2756 int err;
2757 PyObject* retval;
2758 DBT key;
2759 DBT data;
2760
2761 CHECK_DB_NOT_CLOSED(self);
2762 if (!make_key_dbt(self, keyobj, &key, NULL))
2763 return NULL;
2764
2765 CLEAR_DBT(data);
2766 if (CHECK_DBFLAG(self, DB_THREAD)) {
2767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2768 data.flags = DB_DBT_MALLOC;
2769 }
2770 MYDB_BEGIN_ALLOW_THREADS;
2771 err = self->db->get(self->db, NULL, &key, &data, 0);
2772 MYDB_END_ALLOW_THREADS;
2773 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2774 PyErr_SetObject(PyExc_KeyError, keyobj);
2775 retval = NULL;
2776 }
2777 else if (makeDBError(err)) {
2778 retval = NULL;
2779 }
2780 else {
2781 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2782 FREE_DBT(data);
2783 }
2784
2785 FREE_DBT(key);
2786 return retval;
2787}
2788
2789
2790static int
2791DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2792{
2793 DBT key, data;
2794 int retval;
2795 int flags = 0;
2796
2797 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002798 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2799 PyErr_SetObject(DBError, t);
2800 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801 return -1;
2802 }
2803
2804 if (!make_key_dbt(self, keyobj, &key, NULL))
2805 return -1;
2806
2807 if (dataobj != NULL) {
2808 if (!make_dbt(dataobj, &data))
2809 retval = -1;
2810 else {
2811 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002812 /* dictionaries shouldn't have duplicate keys */
2813 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002814 retval = _DB_put(self, NULL, &key, &data, flags);
2815
2816 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002817 /* try deleting any old record that matches and then PUT it
2818 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002819 _DB_delete(self, NULL, &key, 0);
2820 PyErr_Clear();
2821 retval = _DB_put(self, NULL, &key, &data, flags);
2822 }
2823 }
2824 }
2825 else {
2826 /* dataobj == NULL, so delete the key */
2827 retval = _DB_delete(self, NULL, &key, 0);
2828 }
2829 FREE_DBT(key);
2830 return retval;
2831}
2832
2833
2834static PyObject*
2835DB_has_key(DBObject* self, PyObject* args)
2836{
2837 int err;
2838 PyObject* keyobj;
2839 DBT key, data;
2840 PyObject* txnobj = NULL;
2841 DB_TXN *txn = NULL;
2842
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002843 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002844 return NULL;
2845 CHECK_DB_NOT_CLOSED(self);
2846 if (!make_key_dbt(self, keyobj, &key, NULL))
2847 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002848 if (!checkTxnObj(txnobj, &txn)) {
2849 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002851 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002852
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002853 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 it has a record but can't allocate a buffer for the data. This saves
2855 having to deal with data we won't be using.
2856 */
2857 CLEAR_DBT(data);
2858 data.flags = DB_DBT_USERMEM;
2859
2860 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002861 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002862 MYDB_END_ALLOW_THREADS;
2863 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002864
2865 if (err == DB_BUFFER_SMALL || err == 0) {
2866 return PyInt_FromLong(1);
2867 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2868 return PyInt_FromLong(0);
2869 }
2870
2871 makeDBError(err);
2872 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873}
2874
2875
2876#define _KEYS_LIST 1
2877#define _VALUES_LIST 2
2878#define _ITEMS_LIST 3
2879
2880static PyObject*
2881_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2882{
2883 int err, dbtype;
2884 DBT key;
2885 DBT data;
2886 DBC *cursor;
2887 PyObject* list;
2888 PyObject* item = NULL;
2889
2890 CHECK_DB_NOT_CLOSED(self);
2891 CLEAR_DBT(key);
2892 CLEAR_DBT(data);
2893
2894 dbtype = _DB_get_type(self);
2895 if (dbtype == -1)
2896 return NULL;
2897
2898 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002899 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002900 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901
2902 /* get a cursor */
2903 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002904 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002906 if (makeDBError(err)) {
2907 Py_DECREF(list);
2908 return NULL;
2909 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910
2911 if (CHECK_DBFLAG(self, DB_THREAD)) {
2912 key.flags = DB_DBT_REALLOC;
2913 data.flags = DB_DBT_REALLOC;
2914 }
2915
2916 while (1) { /* use the cursor to traverse the DB, collecting items */
2917 MYDB_BEGIN_ALLOW_THREADS;
2918 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2919 MYDB_END_ALLOW_THREADS;
2920
2921 if (err) {
2922 /* for any error, break out of the loop */
2923 break;
2924 }
2925
2926 switch (type) {
2927 case _KEYS_LIST:
2928 switch(dbtype) {
2929 case DB_BTREE:
2930 case DB_HASH:
2931 default:
2932 item = PyString_FromStringAndSize((char*)key.data, key.size);
2933 break;
2934 case DB_RECNO:
2935 case DB_QUEUE:
2936 item = PyInt_FromLong(*((db_recno_t*)key.data));
2937 break;
2938 }
2939 break;
2940
2941 case _VALUES_LIST:
2942 item = PyString_FromStringAndSize((char*)data.data, data.size);
2943 break;
2944
2945 case _ITEMS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002950 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2951 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002955 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2956 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002957 break;
2958 }
2959 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002960 default:
2961 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2962 item = NULL;
2963 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002964 }
2965 if (item == NULL) {
2966 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967 list = NULL;
2968 goto done;
2969 }
2970 PyList_Append(list, item);
2971 Py_DECREF(item);
2972 }
2973
Gregory P. Smithe9477062005-06-04 06:46:59 +00002974 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2975 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 Py_DECREF(list);
2977 list = NULL;
2978 }
2979
2980 done:
2981 FREE_DBT(key);
2982 FREE_DBT(data);
2983 MYDB_BEGIN_ALLOW_THREADS;
2984 cursor->c_close(cursor);
2985 MYDB_END_ALLOW_THREADS;
2986 return list;
2987}
2988
2989
2990static PyObject*
2991DB_keys(DBObject* self, PyObject* args)
2992{
2993 PyObject* txnobj = NULL;
2994 DB_TXN *txn = NULL;
2995
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002996 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002997 return NULL;
2998 if (!checkTxnObj(txnobj, &txn))
2999 return NULL;
3000 return _DB_make_list(self, txn, _KEYS_LIST);
3001}
3002
3003
3004static PyObject*
3005DB_items(DBObject* self, PyObject* args)
3006{
3007 PyObject* txnobj = NULL;
3008 DB_TXN *txn = NULL;
3009
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003010 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003011 return NULL;
3012 if (!checkTxnObj(txnobj, &txn))
3013 return NULL;
3014 return _DB_make_list(self, txn, _ITEMS_LIST);
3015}
3016
3017
3018static PyObject*
3019DB_values(DBObject* self, PyObject* args)
3020{
3021 PyObject* txnobj = NULL;
3022 DB_TXN *txn = NULL;
3023
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003024 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003025 return NULL;
3026 if (!checkTxnObj(txnobj, &txn))
3027 return NULL;
3028 return _DB_make_list(self, txn, _VALUES_LIST);
3029}
3030
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031/* --------------------------------------------------------------------- */
3032/* DBCursor methods */
3033
3034
3035static PyObject*
3036DBC_close(DBCursorObject* self, PyObject* args)
3037{
3038 int err = 0;
3039
3040 if (!PyArg_ParseTuple(args, ":close"))
3041 return NULL;
3042
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003043 if (self->dbc != NULL) {
3044 MYDB_BEGIN_ALLOW_THREADS;
3045 err = self->dbc->c_close(self->dbc);
3046 self->dbc = NULL;
3047 MYDB_END_ALLOW_THREADS;
3048 }
3049 RETURN_IF_ERR();
3050 RETURN_NONE();
3051}
3052
3053
3054static PyObject*
3055DBC_count(DBCursorObject* self, PyObject* args)
3056{
3057 int err = 0;
3058 db_recno_t count;
3059 int flags = 0;
3060
3061 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3062 return NULL;
3063
3064 CHECK_CURSOR_NOT_CLOSED(self);
3065
3066 MYDB_BEGIN_ALLOW_THREADS;
3067 err = self->dbc->c_count(self->dbc, &count, flags);
3068 MYDB_END_ALLOW_THREADS;
3069 RETURN_IF_ERR();
3070
3071 return PyInt_FromLong(count);
3072}
3073
3074
3075static PyObject*
3076DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3077{
3078 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3079}
3080
3081
3082static PyObject*
3083DBC_delete(DBCursorObject* self, PyObject* args)
3084{
3085 int err, flags=0;
3086
3087 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3088 return NULL;
3089
3090 CHECK_CURSOR_NOT_CLOSED(self);
3091
3092 MYDB_BEGIN_ALLOW_THREADS;
3093 err = self->dbc->c_del(self->dbc, flags);
3094 MYDB_END_ALLOW_THREADS;
3095 RETURN_IF_ERR();
3096
3097 self->mydb->haveStat = 0;
3098 RETURN_NONE();
3099}
3100
3101
3102static PyObject*
3103DBC_dup(DBCursorObject* self, PyObject* args)
3104{
3105 int err, flags =0;
3106 DBC* dbc = NULL;
3107
3108 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3109 return NULL;
3110
3111 CHECK_CURSOR_NOT_CLOSED(self);
3112
3113 MYDB_BEGIN_ALLOW_THREADS;
3114 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3115 MYDB_END_ALLOW_THREADS;
3116 RETURN_IF_ERR();
3117
3118 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3119}
3120
3121static PyObject*
3122DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3123{
3124 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3125}
3126
3127
3128static PyObject*
3129DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3130{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003131 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003132 PyObject* keyobj = NULL;
3133 PyObject* dataobj = NULL;
3134 PyObject* retval = NULL;
3135 int dlen = -1;
3136 int doff = -1;
3137 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003138 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003139 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003140
3141 CLEAR_DBT(key);
3142 CLEAR_DBT(data);
3143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003144 &flags, &dlen, &doff))
3145 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003146 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3148 &kwnames[1],
3149 &keyobj, &flags, &dlen, &doff))
3150 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3153 kwnames, &keyobj, &dataobj,
3154 &flags, &dlen, &doff))
3155 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 return NULL;
3157 }
3158 }
3159 }
3160
3161 CHECK_CURSOR_NOT_CLOSED(self);
3162
3163 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3164 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003165 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3166 (!add_partial_dbt(&data, dlen, doff)) )
3167 {
3168 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003170 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003171
3172 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3173 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003174 if (!(key.flags & DB_DBT_REALLOC)) {
3175 key.flags |= DB_DBT_MALLOC;
3176 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 }
3178
3179 MYDB_BEGIN_ALLOW_THREADS;
3180 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3181 MYDB_END_ALLOW_THREADS;
3182
Gregory P. Smithe9477062005-06-04 06:46:59 +00003183 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3184 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003185 Py_INCREF(Py_None);
3186 retval = Py_None;
3187 }
3188 else if (makeDBError(err)) {
3189 retval = NULL;
3190 }
3191 else {
3192 switch (_DB_get_type(self->mydb)) {
3193 case -1:
3194 retval = NULL;
3195 break;
3196 case DB_BTREE:
3197 case DB_HASH:
3198 default:
3199 retval = Py_BuildValue("s#s#", key.data, key.size,
3200 data.data, data.size);
3201 break;
3202 case DB_RECNO:
3203 case DB_QUEUE:
3204 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3205 data.data, data.size);
3206 break;
3207 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 FREE_DBT(data);
3209 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003210 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003211 return retval;
3212}
3213
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003214#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003215static PyObject*
3216DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3217{
3218 int err, flags=0;
3219 PyObject* keyobj = NULL;
3220 PyObject* dataobj = NULL;
3221 PyObject* retval = NULL;
3222 int dlen = -1;
3223 int doff = -1;
3224 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003225 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3226 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003227
3228 CLEAR_DBT(key);
3229 CLEAR_DBT(data);
3230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3231 &flags, &dlen, &doff))
3232 {
3233 PyErr_Clear();
3234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003235 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003236 &keyobj, &flags, &dlen, &doff))
3237 {
3238 PyErr_Clear();
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3240 kwnames, &keyobj, &dataobj,
3241 &flags, &dlen, &doff))
3242 {
3243 return NULL;
3244 }
3245 }
3246 }
3247
3248 CHECK_CURSOR_NOT_CLOSED(self);
3249
3250 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3251 return NULL;
3252 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3253 (!add_partial_dbt(&data, dlen, doff)) ) {
3254 FREE_DBT(key);
3255 return NULL;
3256 }
3257
3258 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3259 data.flags = DB_DBT_MALLOC;
3260 if (!(key.flags & DB_DBT_REALLOC)) {
3261 key.flags |= DB_DBT_MALLOC;
3262 }
3263 }
3264
3265 CLEAR_DBT(pkey);
3266 pkey.flags = DB_DBT_MALLOC;
3267
3268 MYDB_BEGIN_ALLOW_THREADS;
3269 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3270 MYDB_END_ALLOW_THREADS;
3271
Gregory P. Smithe9477062005-06-04 06:46:59 +00003272 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3273 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003274 Py_INCREF(Py_None);
3275 retval = Py_None;
3276 }
3277 else if (makeDBError(err)) {
3278 retval = NULL;
3279 }
3280 else {
3281 PyObject *pkeyObj;
3282 PyObject *dataObj;
3283 dataObj = PyString_FromStringAndSize(data.data, data.size);
3284
3285 if (self->mydb->primaryDBType == DB_RECNO ||
3286 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003287 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003288 else
3289 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3290
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003291 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003292 {
3293 PyObject *keyObj;
3294 int type = _DB_get_type(self->mydb);
3295 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003296 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003297 else
3298 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003299#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003300 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003301#else
3302 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3303#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003304 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003305 FREE_DBT(key);
3306 }
3307 else /* return just the pkey and data */
3308 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003309#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003310 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003311#else
3312 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3313#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003314 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003315 Py_DECREF(dataObj);
3316 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003317 FREE_DBT(pkey);
3318 FREE_DBT(data);
3319 }
3320 /* the only time REALLOC should be set is if we used an integer
3321 * key that make_key_dbt malloc'd for us. always free these. */
3322 if (key.flags & DB_DBT_REALLOC) {
3323 FREE_DBT(key);
3324 }
3325 return retval;
3326}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003327#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003328
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003329
3330static PyObject*
3331DBC_get_recno(DBCursorObject* self, PyObject* args)
3332{
3333 int err;
3334 db_recno_t recno;
3335 DBT key;
3336 DBT data;
3337
3338 if (!PyArg_ParseTuple(args, ":get_recno"))
3339 return NULL;
3340
3341 CHECK_CURSOR_NOT_CLOSED(self);
3342
3343 CLEAR_DBT(key);
3344 CLEAR_DBT(data);
3345 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3346 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3347 data.flags = DB_DBT_MALLOC;
3348 key.flags = DB_DBT_MALLOC;
3349 }
3350
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3353 MYDB_END_ALLOW_THREADS;
3354 RETURN_IF_ERR();
3355
3356 recno = *((db_recno_t*)data.data);
3357 FREE_DBT(key);
3358 FREE_DBT(data);
3359 return PyInt_FromLong(recno);
3360}
3361
3362
3363static PyObject*
3364DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3365{
3366 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3367}
3368
3369
3370static PyObject*
3371DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3372{
3373 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3374}
3375
3376
3377static PyObject*
3378DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3379{
3380 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3381}
3382
3383
3384static PyObject*
3385DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3386{
3387 int err, flags = 0;
3388 PyObject* keyobj, *dataobj;
3389 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003390 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003391 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003392 int dlen = -1;
3393 int doff = -1;
3394
3395 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3396 &keyobj, &dataobj, &flags, &dlen, &doff))
3397 return NULL;
3398
3399 CHECK_CURSOR_NOT_CLOSED(self);
3400
3401 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3402 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003403 if (!make_dbt(dataobj, &data) ||
3404 !add_partial_dbt(&data, dlen, doff) )
3405 {
3406 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003407 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003408 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409
3410 MYDB_BEGIN_ALLOW_THREADS;
3411 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3412 MYDB_END_ALLOW_THREADS;
3413 FREE_DBT(key);
3414 RETURN_IF_ERR();
3415 self->mydb->haveStat = 0;
3416 RETURN_NONE();
3417}
3418
3419
3420static PyObject*
3421DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3422{
3423 int err, flags = 0;
3424 DBT key, data;
3425 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003426 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427 int dlen = -1;
3428 int doff = -1;
3429
3430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3431 &keyobj, &flags, &dlen, &doff))
3432 return NULL;
3433
3434 CHECK_CURSOR_NOT_CLOSED(self);
3435
3436 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
3438
3439 CLEAR_DBT(data);
3440 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3441 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3442 data.flags = DB_DBT_MALLOC;
3443 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003444 if (!add_partial_dbt(&data, dlen, doff)) {
3445 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003447 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448
3449 MYDB_BEGIN_ALLOW_THREADS;
3450 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3451 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003452 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3453 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003454 Py_INCREF(Py_None);
3455 retval = Py_None;
3456 }
3457 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003458 retval = NULL;
3459 }
3460 else {
3461 switch (_DB_get_type(self->mydb)) {
3462 case -1:
3463 retval = NULL;
3464 break;
3465 case DB_BTREE:
3466 case DB_HASH:
3467 default:
3468 retval = Py_BuildValue("s#s#", key.data, key.size,
3469 data.data, data.size);
3470 break;
3471 case DB_RECNO:
3472 case DB_QUEUE:
3473 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3474 data.data, data.size);
3475 break;
3476 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003478 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003480 /* the only time REALLOC should be set is if we used an integer
3481 * key that make_key_dbt malloc'd for us. always free these. */
3482 if (key.flags & DB_DBT_REALLOC) {
3483 FREE_DBT(key);
3484 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003485
3486 return retval;
3487}
3488
3489
3490static PyObject*
3491DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3492{
3493 int err, flags = 0;
3494 DBT key, data;
3495 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003496 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003497 int dlen = -1;
3498 int doff = -1;
3499
3500 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3501 &keyobj, &flags, &dlen, &doff))
3502 return NULL;
3503
3504 CHECK_CURSOR_NOT_CLOSED(self);
3505
3506 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3507 return NULL;
3508
3509 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003510 if (!add_partial_dbt(&data, dlen, doff)) {
3511 FREE_DBT(key);
3512 return NULL;
3513 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003514 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3515 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003516 data.flags |= DB_DBT_MALLOC;
3517 /* only BTREE databases will return anything in the key */
3518 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3519 key.flags |= DB_DBT_MALLOC;
3520 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003521 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003522 MYDB_BEGIN_ALLOW_THREADS;
3523 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3524 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003525 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3526 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003527 Py_INCREF(Py_None);
3528 retval = Py_None;
3529 }
3530 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 retval = NULL;
3532 }
3533 else {
3534 switch (_DB_get_type(self->mydb)) {
3535 case -1:
3536 retval = NULL;
3537 break;
3538 case DB_BTREE:
3539 case DB_HASH:
3540 default:
3541 retval = Py_BuildValue("s#s#", key.data, key.size,
3542 data.data, data.size);
3543 break;
3544 case DB_RECNO:
3545 case DB_QUEUE:
3546 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3547 data.data, data.size);
3548 break;
3549 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003550 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003551 FREE_DBT(data);
3552 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003553 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003554 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003555 if (key.flags & DB_DBT_REALLOC) {
3556 FREE_DBT(key);
3557 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558
3559 return retval;
3560}
3561
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003563_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3564 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003566 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003568 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569
Gregory P. Smith7441e652003-11-03 21:35:31 +00003570 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3572 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003573 if (!make_dbt(dataobj, &data)) {
3574 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577
3578 MYDB_BEGIN_ALLOW_THREADS;
3579 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3580 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003582 Py_INCREF(Py_None);
3583 retval = Py_None;
3584 }
3585 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586 retval = NULL;
3587 }
3588 else {
3589 switch (_DB_get_type(self->mydb)) {
3590 case -1:
3591 retval = NULL;
3592 break;
3593 case DB_BTREE:
3594 case DB_HASH:
3595 default:
3596 retval = Py_BuildValue("s#s#", key.data, key.size,
3597 data.data, data.size);
3598 break;
3599 case DB_RECNO:
3600 case DB_QUEUE:
3601 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3602 data.data, data.size);
3603 break;
3604 }
3605 }
3606
3607 FREE_DBT(key);
3608 return retval;
3609}
3610
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003611static PyObject*
3612DBC_get_both(DBCursorObject* self, PyObject* args)
3613{
3614 int flags=0;
3615 PyObject *keyobj, *dataobj;
3616
3617 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3618 return NULL;
3619
Gregory P. Smith7441e652003-11-03 21:35:31 +00003620 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003621 CHECK_CURSOR_NOT_CLOSED(self);
3622
3623 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3624 self->mydb->moduleFlags.getReturnsNone);
3625}
3626
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003627/* Return size of entry */
3628static PyObject*
3629DBC_get_current_size(DBCursorObject* self, PyObject* args)
3630{
3631 int err, flags=DB_CURRENT;
3632 PyObject* retval = NULL;
3633 DBT key, data;
3634
3635 if (!PyArg_ParseTuple(args, ":get_current_size"))
3636 return NULL;
3637 CHECK_CURSOR_NOT_CLOSED(self);
3638 CLEAR_DBT(key);
3639 CLEAR_DBT(data);
3640
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003641 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003642 getting the record size. */
3643 data.flags = DB_DBT_USERMEM;
3644 data.ulen = 0;
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3647 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003648 if (err == DB_BUFFER_SMALL || !err) {
3649 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003650 retval = PyInt_FromLong((long)data.size);
3651 err = 0;
3652 }
3653
3654 FREE_DBT(key);
3655 FREE_DBT(data);
3656 RETURN_IF_ERR();
3657 return retval;
3658}
3659
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003660static PyObject*
3661DBC_set_both(DBCursorObject* self, PyObject* args)
3662{
3663 int flags=0;
3664 PyObject *keyobj, *dataobj;
3665
3666 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3667 return NULL;
3668
Gregory P. Smith7441e652003-11-03 21:35:31 +00003669 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003670 CHECK_CURSOR_NOT_CLOSED(self);
3671
3672 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3673 self->mydb->moduleFlags.cursorSetReturnsNone);
3674}
3675
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003676
3677static PyObject*
3678DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3679{
3680 int err, irecno, flags=0;
3681 db_recno_t recno;
3682 DBT key, data;
3683 PyObject* retval;
3684 int dlen = -1;
3685 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003686 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003687
3688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3689 &irecno, &flags, &dlen, &doff))
3690 return NULL;
3691
3692 CHECK_CURSOR_NOT_CLOSED(self);
3693
3694 CLEAR_DBT(key);
3695 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003696 /* use allocated space so DB will be able to realloc room for the real
3697 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003698 key.data = malloc(sizeof(db_recno_t));
3699 if (key.data == NULL) {
3700 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3701 return NULL;
3702 }
3703 key.size = sizeof(db_recno_t);
3704 key.ulen = key.size;
3705 memcpy(key.data, &recno, sizeof(db_recno_t));
3706 key.flags = DB_DBT_REALLOC;
3707
3708 CLEAR_DBT(data);
3709 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3711 data.flags = DB_DBT_MALLOC;
3712 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003713 if (!add_partial_dbt(&data, dlen, doff)) {
3714 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003715 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003716 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717
3718 MYDB_BEGIN_ALLOW_THREADS;
3719 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3720 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3722 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003723 Py_INCREF(Py_None);
3724 retval = Py_None;
3725 }
3726 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003727 retval = NULL;
3728 }
3729 else { /* Can only be used for BTrees, so no need to return int key */
3730 retval = Py_BuildValue("s#s#", key.data, key.size,
3731 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732 FREE_DBT(data);
3733 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003734 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003735
3736 return retval;
3737}
3738
3739
3740static PyObject*
3741DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3742{
3743 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3744}
3745
3746
3747static PyObject*
3748DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3749{
3750 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3751}
3752
3753
3754static PyObject*
3755DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3756{
3757 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3758}
3759
3760
3761static PyObject*
3762DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3763{
3764 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3765}
3766
3767
3768static PyObject*
3769DBC_join_item(DBCursorObject* self, PyObject* args)
3770{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003771 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003772 DBT key, data;
3773 PyObject* retval;
3774
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003775 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003776 return NULL;
3777
3778 CHECK_CURSOR_NOT_CLOSED(self);
3779
3780 CLEAR_DBT(key);
3781 CLEAR_DBT(data);
3782 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3783 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3784 key.flags = DB_DBT_MALLOC;
3785 }
3786
3787 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003788 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003790 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3791 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792 Py_INCREF(Py_None);
3793 retval = Py_None;
3794 }
3795 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796 retval = NULL;
3797 }
3798 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003799 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 FREE_DBT(key);
3801 }
3802
3803 return retval;
3804}
3805
3806
3807
3808/* --------------------------------------------------------------------- */
3809/* DBEnv methods */
3810
3811
3812static PyObject*
3813DBEnv_close(DBEnvObject* self, PyObject* args)
3814{
3815 int err, flags = 0;
3816
3817 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3818 return NULL;
3819 if (!self->closed) { /* Don't close more than once */
3820 MYDB_BEGIN_ALLOW_THREADS;
3821 err = self->db_env->close(self->db_env, flags);
3822 MYDB_END_ALLOW_THREADS;
3823 /* after calling DBEnv->close, regardless of error, this DBEnv
3824 * may not be accessed again (BerkeleyDB docs). */
3825 self->closed = 1;
3826 self->db_env = NULL;
3827 RETURN_IF_ERR();
3828 }
3829 RETURN_NONE();
3830}
3831
3832
3833static PyObject*
3834DBEnv_open(DBEnvObject* self, PyObject* args)
3835{
3836 int err, flags=0, mode=0660;
3837 char *db_home;
3838
3839 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3840 return NULL;
3841
3842 CHECK_ENV_NOT_CLOSED(self);
3843
3844 MYDB_BEGIN_ALLOW_THREADS;
3845 err = self->db_env->open(self->db_env, db_home, flags, mode);
3846 MYDB_END_ALLOW_THREADS;
3847 RETURN_IF_ERR();
3848 self->closed = 0;
3849 self->flags = flags;
3850 RETURN_NONE();
3851}
3852
3853
3854static PyObject*
3855DBEnv_remove(DBEnvObject* self, PyObject* args)
3856{
3857 int err, flags=0;
3858 char *db_home;
3859
3860 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3861 return NULL;
3862 CHECK_ENV_NOT_CLOSED(self);
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->remove(self->db_env, db_home, flags);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3868}
3869
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003870#if (DBVER >= 41)
3871static PyObject*
3872DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3873{
3874 int err;
3875 u_int32_t flags=0;
3876 char *file = NULL;
3877 char *database = NULL;
3878 PyObject *txnobj = NULL;
3879 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003880 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003881 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003882
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003884 &file, &database, &txnobj, &flags)) {
3885 return NULL;
3886 }
3887 if (!checkTxnObj(txnobj, &txn)) {
3888 return NULL;
3889 }
3890 CHECK_ENV_NOT_CLOSED(self);
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3896}
3897
3898static PyObject*
3899DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3900{
3901 int err;
3902 u_int32_t flags=0;
3903 char *file = NULL;
3904 char *database = NULL;
3905 char *newname = NULL;
3906 PyObject *txnobj = NULL;
3907 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003908 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003909 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003910
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003912 &file, &database, &newname, &txnobj, &flags)) {
3913 return NULL;
3914 }
3915 if (!checkTxnObj(txnobj, &txn)) {
3916 return NULL;
3917 }
3918 CHECK_ENV_NOT_CLOSED(self);
3919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3921 flags);
3922 MYDB_END_ALLOW_THREADS;
3923 RETURN_IF_ERR();
3924 RETURN_NONE();
3925}
3926
3927static PyObject*
3928DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3929{
3930 int err;
3931 u_int32_t flags=0;
3932 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003933 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003934
3935 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3936 &passwd, &flags)) {
3937 return NULL;
3938 }
3939
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3942 MYDB_END_ALLOW_THREADS;
3943
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3946}
3947#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003948
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003949#if (DBVER >= 40)
3950static PyObject*
3951DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3952{
3953 int err;
3954 u_int32_t flags=0;
3955 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003956 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003957
3958 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3959 &timeout, &flags)) {
3960 return NULL;
3961 }
3962
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3965 MYDB_END_ALLOW_THREADS;
3966
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3969}
3970#endif /* DBVER >= 40 */
3971
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003972static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003973DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3974{
3975 int err;
3976 long shm_key = 0;
3977
3978 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3981
3982 err = self->db_env->set_shm_key(self->db_env, shm_key);
3983 RETURN_IF_ERR();
3984 RETURN_NONE();
3985}
3986
3987static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003988DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3989{
3990 int err, gbytes=0, bytes=0, ncache=0;
3991
3992 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3993 &gbytes, &bytes, &ncache))
3994 return NULL;
3995 CHECK_ENV_NOT_CLOSED(self);
3996
3997 MYDB_BEGIN_ALLOW_THREADS;
3998 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3999 MYDB_END_ALLOW_THREADS;
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4002}
4003
4004
4005#if (DBVER >= 32)
4006static PyObject*
4007DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4008{
4009 int err, flags=0, onoff=0;
4010
4011 if (!PyArg_ParseTuple(args, "ii:set_flags",
4012 &flags, &onoff))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4015
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_flags(self->db_env, flags, onoff);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4021}
4022#endif
4023
4024
4025static PyObject*
4026DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4027{
4028 int err;
4029 char *dir;
4030
4031 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4034
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_data_dir(self->db_env, dir);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4040}
4041
4042
4043static PyObject*
4044DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4045{
4046 int err, lg_bsize;
4047
4048 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4051
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4057}
4058
4059
4060static PyObject*
4061DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4062{
4063 int err;
4064 char *dir;
4065
4066 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4069
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_dir(self->db_env, dir);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4075}
4076
4077static PyObject*
4078DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4079{
4080 int err, lg_max;
4081
4082 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4083 return NULL;
4084 CHECK_ENV_NOT_CLOSED(self);
4085
4086 MYDB_BEGIN_ALLOW_THREADS;
4087 err = self->db_env->set_lg_max(self->db_env, lg_max);
4088 MYDB_END_ALLOW_THREADS;
4089 RETURN_IF_ERR();
4090 RETURN_NONE();
4091}
4092
4093
Neal Norwitz84562352005-10-20 04:30:15 +00004094#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004095static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004096DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4097{
4098 int err, lg_max;
4099
4100 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4103
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4109}
Neal Norwitz84562352005-10-20 04:30:15 +00004110#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004111
4112
4113static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4115{
4116 int err, lk_detect;
4117
4118 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4121
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4127}
4128
4129
4130static PyObject*
4131DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4132{
4133 int err, max;
4134
4135 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4136 return NULL;
4137 CHECK_ENV_NOT_CLOSED(self);
4138
4139 MYDB_BEGIN_ALLOW_THREADS;
4140 err = self->db_env->set_lk_max(self->db_env, max);
4141 MYDB_END_ALLOW_THREADS;
4142 RETURN_IF_ERR();
4143 RETURN_NONE();
4144}
4145
4146
4147#if (DBVER >= 32)
4148
4149static PyObject*
4150DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4151{
4152 int err, max;
4153
4154 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4157
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_lk_max_locks(self->db_env, max);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4163}
4164
4165
4166static PyObject*
4167DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4168{
4169 int err, max;
4170
4171 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4172 return NULL;
4173 CHECK_ENV_NOT_CLOSED(self);
4174
4175 MYDB_BEGIN_ALLOW_THREADS;
4176 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4177 MYDB_END_ALLOW_THREADS;
4178 RETURN_IF_ERR();
4179 RETURN_NONE();
4180}
4181
4182
4183static PyObject*
4184DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4185{
4186 int err, max;
4187
4188 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4189 return NULL;
4190 CHECK_ENV_NOT_CLOSED(self);
4191
4192 MYDB_BEGIN_ALLOW_THREADS;
4193 err = self->db_env->set_lk_max_objects(self->db_env, max);
4194 MYDB_END_ALLOW_THREADS;
4195 RETURN_IF_ERR();
4196 RETURN_NONE();
4197}
4198
4199#endif
4200
4201
4202static PyObject*
4203DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4204{
4205 int err, mp_mmapsize;
4206
4207 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4210
4211 MYDB_BEGIN_ALLOW_THREADS;
4212 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 RETURN_NONE();
4216}
4217
4218
4219static PyObject*
4220DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4221{
4222 int err;
4223 char *dir;
4224
4225 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4226 return NULL;
4227 CHECK_ENV_NOT_CLOSED(self);
4228
4229 MYDB_BEGIN_ALLOW_THREADS;
4230 err = self->db_env->set_tmp_dir(self->db_env, dir);
4231 MYDB_END_ALLOW_THREADS;
4232 RETURN_IF_ERR();
4233 RETURN_NONE();
4234}
4235
4236
4237static PyObject*
4238DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4239{
4240 int flags = 0;
4241 PyObject* txnobj = NULL;
4242 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004243 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004244
4245 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4246 &txnobj, &flags))
4247 return NULL;
4248
4249 if (!checkTxnObj(txnobj, &txn))
4250 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4252
4253 return (PyObject*)newDBTxnObject(self, txn, flags);
4254}
4255
4256
4257static PyObject*
4258DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4259{
4260 int err, kbyte=0, min=0, flags=0;
4261
4262 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4263 return NULL;
4264 CHECK_ENV_NOT_CLOSED(self);
4265
4266 MYDB_BEGIN_ALLOW_THREADS;
4267#if (DBVER >= 40)
4268 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4269#else
4270 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4271#endif
4272 MYDB_END_ALLOW_THREADS;
4273 RETURN_IF_ERR();
4274 RETURN_NONE();
4275}
4276
4277
4278static PyObject*
4279DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4280{
4281 int err, max;
4282
4283 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4284 return NULL;
4285 CHECK_ENV_NOT_CLOSED(self);
4286
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004287 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004288 RETURN_IF_ERR();
4289 RETURN_NONE();
4290}
4291
4292
4293static PyObject*
4294DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4295{
4296 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004297 long stamp;
4298 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004299
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004300 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004301 return NULL;
4302 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004303 timestamp = (time_t)stamp;
4304 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307}
4308
4309
4310static PyObject*
4311DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4312{
4313 int err, atype, flags=0;
4314 int aborted = 0;
4315
4316 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4317 return NULL;
4318 CHECK_ENV_NOT_CLOSED(self);
4319
4320 MYDB_BEGIN_ALLOW_THREADS;
4321#if (DBVER >= 40)
4322 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4323#else
4324 err = lock_detect(self->db_env, flags, atype, &aborted);
4325#endif
4326 MYDB_END_ALLOW_THREADS;
4327 RETURN_IF_ERR();
4328 return PyInt_FromLong(aborted);
4329}
4330
4331
4332static PyObject*
4333DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4334{
4335 int flags=0;
4336 int locker, lock_mode;
4337 DBT obj;
4338 PyObject* objobj;
4339
4340 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4341 return NULL;
4342
4343
4344 if (!make_dbt(objobj, &obj))
4345 return NULL;
4346
4347 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4348}
4349
4350
4351static PyObject*
4352DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4353{
4354 int err;
4355 u_int32_t theID;
4356
4357 if (!PyArg_ParseTuple(args, ":lock_id"))
4358 return NULL;
4359
4360 CHECK_ENV_NOT_CLOSED(self);
4361 MYDB_BEGIN_ALLOW_THREADS;
4362#if (DBVER >= 40)
4363 err = self->db_env->lock_id(self->db_env, &theID);
4364#else
4365 err = lock_id(self->db_env, &theID);
4366#endif
4367 MYDB_END_ALLOW_THREADS;
4368 RETURN_IF_ERR();
4369
4370 return PyInt_FromLong((long)theID);
4371}
4372
4373
4374static PyObject*
4375DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4376{
4377 int err;
4378 DBLockObject* dblockobj;
4379
4380 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4381 return NULL;
4382
4383 CHECK_ENV_NOT_CLOSED(self);
4384 MYDB_BEGIN_ALLOW_THREADS;
4385#if (DBVER >= 40)
4386 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4387#else
4388 err = lock_put(self->db_env, &dblockobj->lock);
4389#endif
4390 MYDB_END_ALLOW_THREADS;
4391 RETURN_IF_ERR();
4392 RETURN_NONE();
4393}
4394
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004395#if (DBVER >= 44)
4396static PyObject*
4397DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4398{
4399 int err;
4400 char *file;
4401 u_int32_t flags = 0;
4402 static char* kwnames[] = { "file", "flags", NULL};
4403
4404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4405 &file, &flags))
4406 return NULL;
4407 CHECK_ENV_NOT_CLOSED(self);
4408
4409 MYDB_BEGIN_ALLOW_THREADS;
4410 err = self->db_env->lsn_reset(self->db_env, file, flags);
4411 MYDB_END_ALLOW_THREADS;
4412 RETURN_IF_ERR();
4413 RETURN_NONE();
4414}
4415#endif /* DBVER >= 4.4 */
4416
4417#if (DBVER >= 40)
4418static PyObject*
4419DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4420{
4421 int err;
4422 DB_LOG_STAT* statp = NULL;
4423 PyObject* d = NULL;
4424 u_int32_t flags = 0;
4425
4426 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4427 return NULL;
4428 CHECK_ENV_NOT_CLOSED(self);
4429
4430 MYDB_BEGIN_ALLOW_THREADS;
4431 err = self->db_env->log_stat(self->db_env, &statp, flags);
4432 MYDB_END_ALLOW_THREADS;
4433 RETURN_IF_ERR();
4434
4435 /* Turn the stat structure into a dictionary */
4436 d = PyDict_New();
4437 if (d == NULL) {
4438 if (statp)
4439 free(statp);
4440 return NULL;
4441 }
4442
4443#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4444
4445 MAKE_ENTRY(magic);
4446 MAKE_ENTRY(version);
4447 MAKE_ENTRY(mode);
4448 MAKE_ENTRY(lg_bsize);
4449#if (DBVER >= 44)
4450 MAKE_ENTRY(lg_size);
4451 MAKE_ENTRY(record);
4452#endif
4453#if (DBVER <= 40)
4454 MAKE_ENTRY(lg_max);
4455#endif
4456 MAKE_ENTRY(w_mbytes);
4457 MAKE_ENTRY(w_bytes);
4458 MAKE_ENTRY(wc_mbytes);
4459 MAKE_ENTRY(wc_bytes);
4460 MAKE_ENTRY(wcount);
4461 MAKE_ENTRY(wcount_fill);
4462#if (DBVER >= 44)
4463 MAKE_ENTRY(rcount);
4464#endif
4465 MAKE_ENTRY(scount);
4466 MAKE_ENTRY(cur_file);
4467 MAKE_ENTRY(cur_offset);
4468 MAKE_ENTRY(disk_file);
4469 MAKE_ENTRY(disk_offset);
4470 MAKE_ENTRY(maxcommitperflush);
4471 MAKE_ENTRY(mincommitperflush);
4472 MAKE_ENTRY(regsize);
4473 MAKE_ENTRY(region_wait);
4474 MAKE_ENTRY(region_nowait);
4475
4476#undef MAKE_ENTRY
4477 free(statp);
4478 return d;
4479} /* DBEnv_log_stat */
4480#endif /* DBVER >= 4.0 for log_stat method */
4481
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004482
4483static PyObject*
4484DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4485{
4486 int err;
4487 DB_LOCK_STAT* sp;
4488 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004489 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490
4491 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4492 return NULL;
4493 CHECK_ENV_NOT_CLOSED(self);
4494
4495 MYDB_BEGIN_ALLOW_THREADS;
4496#if (DBVER >= 40)
4497 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4498#else
4499#if (DBVER >= 33)
4500 err = lock_stat(self->db_env, &sp);
4501#else
4502 err = lock_stat(self->db_env, &sp, NULL);
4503#endif
4504#endif
4505 MYDB_END_ALLOW_THREADS;
4506 RETURN_IF_ERR();
4507
4508 /* Turn the stat structure into a dictionary */
4509 d = PyDict_New();
4510 if (d == NULL) {
4511 free(sp);
4512 return NULL;
4513 }
4514
4515#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4516
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004517#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004518 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004519#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004520 MAKE_ENTRY(nmodes);
4521#if (DBVER >= 32)
4522 MAKE_ENTRY(maxlocks);
4523 MAKE_ENTRY(maxlockers);
4524 MAKE_ENTRY(maxobjects);
4525 MAKE_ENTRY(nlocks);
4526 MAKE_ENTRY(maxnlocks);
4527#endif
4528 MAKE_ENTRY(nlockers);
4529 MAKE_ENTRY(maxnlockers);
4530#if (DBVER >= 32)
4531 MAKE_ENTRY(nobjects);
4532 MAKE_ENTRY(maxnobjects);
4533#endif
4534 MAKE_ENTRY(nrequests);
4535 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004536#if (DBVER < 44)
4537 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004539#else
4540 MAKE_ENTRY(lock_nowait);
4541 MAKE_ENTRY(lock_wait);
4542#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004543 MAKE_ENTRY(ndeadlocks);
4544 MAKE_ENTRY(regsize);
4545 MAKE_ENTRY(region_wait);
4546 MAKE_ENTRY(region_nowait);
4547
4548#undef MAKE_ENTRY
4549 free(sp);
4550 return d;
4551}
4552
4553
4554static PyObject*
4555DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4556{
4557 int flags=0;
4558 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004559 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560 PyObject* list;
4561 PyObject* item = NULL;
4562
4563 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4564 return NULL;
4565
4566 CHECK_ENV_NOT_CLOSED(self);
4567 MYDB_BEGIN_ALLOW_THREADS;
4568#if (DBVER >= 40)
4569 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4570#elif (DBVER == 33)
4571 err = log_archive(self->db_env, &log_list, flags);
4572#else
4573 err = log_archive(self->db_env, &log_list, flags, NULL);
4574#endif
4575 MYDB_END_ALLOW_THREADS;
4576 RETURN_IF_ERR();
4577
4578 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004579 if (list == NULL) {
4580 if (log_list)
4581 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004582 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004583 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584
4585 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004586 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4588 item = PyString_FromString (*log_list);
4589 if (item == NULL) {
4590 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004591 list = NULL;
4592 break;
4593 }
4594 PyList_Append(list, item);
4595 Py_DECREF(item);
4596 }
4597 free(log_list_start);
4598 }
4599 return list;
4600}
4601
4602
4603static PyObject*
4604DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4605{
4606 int err;
4607 DB_TXN_STAT* sp;
4608 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004609 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610
4611 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4612 return NULL;
4613 CHECK_ENV_NOT_CLOSED(self);
4614
4615 MYDB_BEGIN_ALLOW_THREADS;
4616#if (DBVER >= 40)
4617 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4618#elif (DBVER == 33)
4619 err = txn_stat(self->db_env, &sp);
4620#else
4621 err = txn_stat(self->db_env, &sp, NULL);
4622#endif
4623 MYDB_END_ALLOW_THREADS;
4624 RETURN_IF_ERR();
4625
4626 /* Turn the stat structure into a dictionary */
4627 d = PyDict_New();
4628 if (d == NULL) {
4629 free(sp);
4630 return NULL;
4631 }
4632
4633#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4634
4635 MAKE_ENTRY(time_ckp);
4636 MAKE_ENTRY(last_txnid);
4637 MAKE_ENTRY(maxtxns);
4638 MAKE_ENTRY(nactive);
4639 MAKE_ENTRY(maxnactive);
4640 MAKE_ENTRY(nbegins);
4641 MAKE_ENTRY(naborts);
4642 MAKE_ENTRY(ncommits);
4643 MAKE_ENTRY(regsize);
4644 MAKE_ENTRY(region_wait);
4645 MAKE_ENTRY(region_nowait);
4646
4647#undef MAKE_ENTRY
4648 free(sp);
4649 return d;
4650}
4651
4652
4653static PyObject*
4654DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4655{
4656 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004657 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004658
4659 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4660 return NULL;
4661 CHECK_ENV_NOT_CLOSED(self);
4662
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004663 if (self->moduleFlags.getReturnsNone)
4664 ++oldValue;
4665 if (self->moduleFlags.cursorSetReturnsNone)
4666 ++oldValue;
4667 self->moduleFlags.getReturnsNone = (flags >= 1);
4668 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004669 return PyInt_FromLong(oldValue);
4670}
4671
4672
4673/* --------------------------------------------------------------------- */
4674/* DBTxn methods */
4675
4676
4677static PyObject*
4678DBTxn_commit(DBTxnObject* self, PyObject* args)
4679{
4680 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004681 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682
4683 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4684 return NULL;
4685
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004686 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004687 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4688 "after txn_commit or txn_abort");
4689 PyErr_SetObject(DBError, t);
4690 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004691 return NULL;
4692 }
4693 txn = self->txn;
4694 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004695 MYDB_BEGIN_ALLOW_THREADS;
4696#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004697 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004698#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004699 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004700#endif
4701 MYDB_END_ALLOW_THREADS;
4702 RETURN_IF_ERR();
4703 RETURN_NONE();
4704}
4705
4706static PyObject*
4707DBTxn_prepare(DBTxnObject* self, PyObject* args)
4708{
4709#if (DBVER >= 33)
4710 int err;
4711 char* gid=NULL;
4712 int gid_size=0;
4713
4714 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4715 return NULL;
4716
4717 if (gid_size != DB_XIDDATASIZE) {
4718 PyErr_SetString(PyExc_TypeError,
4719 "gid must be DB_XIDDATASIZE bytes long");
4720 return NULL;
4721 }
4722
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004723 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004724 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4725 "after txn_commit or txn_abort");
4726 PyErr_SetObject(DBError, t);
4727 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004728 return NULL;
4729 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730 MYDB_BEGIN_ALLOW_THREADS;
4731#if (DBVER >= 40)
4732 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4733#else
4734 err = txn_prepare(self->txn, (u_int8_t*)gid);
4735#endif
4736 MYDB_END_ALLOW_THREADS;
4737 RETURN_IF_ERR();
4738 RETURN_NONE();
4739#else
4740 int err;
4741
4742 if (!PyArg_ParseTuple(args, ":prepare"))
4743 return NULL;
4744
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004745 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004746 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4747 "after txn_commit or txn_abort");
4748 PyErr_SetObject(DBError, t);
4749 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004750 return NULL;
4751 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004752 MYDB_BEGIN_ALLOW_THREADS;
4753 err = txn_prepare(self->txn);
4754 MYDB_END_ALLOW_THREADS;
4755 RETURN_IF_ERR();
4756 RETURN_NONE();
4757#endif
4758}
4759
4760
4761static PyObject*
4762DBTxn_abort(DBTxnObject* self, PyObject* args)
4763{
4764 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004765 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766
4767 if (!PyArg_ParseTuple(args, ":abort"))
4768 return NULL;
4769
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004770 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004771 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4772 "after txn_commit or txn_abort");
4773 PyErr_SetObject(DBError, t);
4774 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004775 return NULL;
4776 }
4777 txn = self->txn;
4778 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004779 MYDB_BEGIN_ALLOW_THREADS;
4780#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004781 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004782#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004783 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004784#endif
4785 MYDB_END_ALLOW_THREADS;
4786 RETURN_IF_ERR();
4787 RETURN_NONE();
4788}
4789
4790
4791static PyObject*
4792DBTxn_id(DBTxnObject* self, PyObject* args)
4793{
4794 int id;
4795
4796 if (!PyArg_ParseTuple(args, ":id"))
4797 return NULL;
4798
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004799 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004800 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4801 "after txn_commit or txn_abort");
4802 PyErr_SetObject(DBError, t);
4803 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 return NULL;
4805 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004806 MYDB_BEGIN_ALLOW_THREADS;
4807#if (DBVER >= 40)
4808 id = self->txn->id(self->txn);
4809#else
4810 id = txn_id(self->txn);
4811#endif
4812 MYDB_END_ALLOW_THREADS;
4813 return PyInt_FromLong(id);
4814}
4815
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004816#if (DBVER >= 43)
4817/* --------------------------------------------------------------------- */
4818/* DBSequence methods */
4819
4820
4821static PyObject*
4822DBSequence_close(DBSequenceObject* self, PyObject* args)
4823{
4824 int err, flags=0;
4825 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4826 return NULL;
4827 CHECK_SEQUENCE_NOT_CLOSED(self)
4828
4829 MYDB_BEGIN_ALLOW_THREADS
4830 err = self->sequence->close(self->sequence, flags);
4831 self->sequence = NULL;
4832 MYDB_END_ALLOW_THREADS
4833
4834 RETURN_IF_ERR();
4835
4836 RETURN_NONE();
4837}
4838
4839static PyObject*
4840DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4841{
4842 int err, flags = 0;
4843 int delta = 1;
4844 db_seq_t value;
4845 PyObject *txnobj = NULL;
4846 DB_TXN *txn = NULL;
4847 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4849 return NULL;
4850 CHECK_SEQUENCE_NOT_CLOSED(self)
4851
4852 if (!checkTxnObj(txnobj, &txn))
4853 return NULL;
4854
4855 MYDB_BEGIN_ALLOW_THREADS
4856 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4857 MYDB_END_ALLOW_THREADS
4858
4859 RETURN_IF_ERR();
4860 return PyLong_FromLongLong(value);
4861
4862}
4863
4864static PyObject*
4865DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4866{
4867 if (!PyArg_ParseTuple(args,":get_dbp"))
4868 return NULL;
4869 CHECK_SEQUENCE_NOT_CLOSED(self)
4870 Py_INCREF(self->mydb);
4871 return (PyObject* )self->mydb;
4872}
4873
4874static PyObject*
4875DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4876{
4877 int err;
4878 DBT key;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880 MYDB_BEGIN_ALLOW_THREADS
4881 err = self->sequence->get_key(self->sequence, &key);
4882 MYDB_END_ALLOW_THREADS
4883
4884 RETURN_IF_ERR();
4885
4886 return PyString_FromStringAndSize(key.data, key.size);
4887}
4888
4889static PyObject*
4890DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4891{
4892 int err;
4893 db_seq_t value;
4894 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4895 return NULL;
4896 CHECK_SEQUENCE_NOT_CLOSED(self)
4897
4898 MYDB_BEGIN_ALLOW_THREADS
4899 err = self->sequence->initial_value(self->sequence, value);
4900 MYDB_END_ALLOW_THREADS
4901
4902 RETURN_IF_ERR();
4903
4904 RETURN_NONE();
4905}
4906
4907static PyObject*
4908DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4909{
4910 int err, flags = 0;
4911 PyObject* keyobj;
4912 PyObject *txnobj = NULL;
4913 DB_TXN *txn = NULL;
4914 DBT key;
4915
4916 static char* kwnames[] = {"key", "txn", "flags", NULL };
4917 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4918 return NULL;
4919
4920 if (!checkTxnObj(txnobj, &txn))
4921 return NULL;
4922
4923 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4924 return NULL;
4925
4926 MYDB_BEGIN_ALLOW_THREADS
4927 err = self->sequence->open(self->sequence, txn, &key, flags);
4928 MYDB_END_ALLOW_THREADS
4929
4930 CLEAR_DBT(key);
4931 RETURN_IF_ERR();
4932
4933 RETURN_NONE();
4934}
4935
4936static PyObject*
4937DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4938{
4939 int err, flags = 0;
4940 PyObject *txnobj = NULL;
4941 DB_TXN *txn = NULL;
4942
4943 static char* kwnames[] = {"txn", "flags", NULL };
4944 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4945 return NULL;
4946
4947 if (!checkTxnObj(txnobj, &txn))
4948 return NULL;
4949
4950 CHECK_SEQUENCE_NOT_CLOSED(self)
4951
4952 MYDB_BEGIN_ALLOW_THREADS
4953 err = self->sequence->remove(self->sequence, txn, flags);
4954 MYDB_END_ALLOW_THREADS
4955
4956 RETURN_IF_ERR();
4957 RETURN_NONE();
4958}
4959
4960static PyObject*
4961DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4962{
4963 int err, size;
4964 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4965 return NULL;
4966 CHECK_SEQUENCE_NOT_CLOSED(self)
4967
4968 MYDB_BEGIN_ALLOW_THREADS
4969 err = self->sequence->set_cachesize(self->sequence, size);
4970 MYDB_END_ALLOW_THREADS
4971
4972 RETURN_IF_ERR();
4973 RETURN_NONE();
4974}
4975
4976static PyObject*
4977DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4978{
4979 int err, size;
4980 if (!PyArg_ParseTuple(args,":get_cachesize"))
4981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self)
4983
4984 MYDB_BEGIN_ALLOW_THREADS
4985 err = self->sequence->get_cachesize(self->sequence, &size);
4986 MYDB_END_ALLOW_THREADS
4987
4988 RETURN_IF_ERR();
4989 return PyInt_FromLong(size);
4990}
4991
4992static PyObject*
4993DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4994{
4995 int err, flags = 0;
4996 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4997 return NULL;
4998 CHECK_SEQUENCE_NOT_CLOSED(self)
4999
5000 MYDB_BEGIN_ALLOW_THREADS
5001 err = self->sequence->set_flags(self->sequence, flags);
5002 MYDB_END_ALLOW_THREADS
5003
5004 RETURN_IF_ERR();
5005 RETURN_NONE();
5006
5007}
5008
5009static PyObject*
5010DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5011{
5012 unsigned int flags;
5013 int err;
5014 if (!PyArg_ParseTuple(args,":get_flags"))
5015 return NULL;
5016 CHECK_SEQUENCE_NOT_CLOSED(self)
5017
5018 MYDB_BEGIN_ALLOW_THREADS
5019 err = self->sequence->get_flags(self->sequence, &flags);
5020 MYDB_END_ALLOW_THREADS
5021
5022 RETURN_IF_ERR();
5023 return PyInt_FromLong((int)flags);
5024}
5025
5026static PyObject*
5027DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5028{
5029 int err;
5030 db_seq_t min, max;
5031 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5032 return NULL;
5033 CHECK_SEQUENCE_NOT_CLOSED(self)
5034
5035 MYDB_BEGIN_ALLOW_THREADS
5036 err = self->sequence->set_range(self->sequence, min, max);
5037 MYDB_END_ALLOW_THREADS
5038
5039 RETURN_IF_ERR();
5040 RETURN_NONE();
5041}
5042
5043static PyObject*
5044DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5045{
5046 int err;
5047 db_seq_t min, max;
5048 if (!PyArg_ParseTuple(args,":get_range"))
5049 return NULL;
5050 CHECK_SEQUENCE_NOT_CLOSED(self)
5051
5052 MYDB_BEGIN_ALLOW_THREADS
5053 err = self->sequence->get_range(self->sequence, &min, &max);
5054 MYDB_END_ALLOW_THREADS
5055
5056 RETURN_IF_ERR();
5057 return Py_BuildValue("(LL)", min, max);
5058}
5059
5060static PyObject*
5061DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5062{
5063 int err, flags = 0;
5064 DB_SEQUENCE_STAT* sp = NULL;
5065 PyObject* dict_stat;
5066 static char* kwnames[] = {"flags", NULL };
5067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5068 return NULL;
5069 CHECK_SEQUENCE_NOT_CLOSED(self);
5070
5071 MYDB_BEGIN_ALLOW_THREADS;
5072 err = self->sequence->stat(self->sequence, &sp, flags);
5073 MYDB_END_ALLOW_THREADS;
5074 RETURN_IF_ERR();
5075
5076 if ((dict_stat = PyDict_New()) == NULL) {
5077 free(sp);
5078 return NULL;
5079 }
5080
5081
5082#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5083#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5084
5085 MAKE_INT_ENTRY(wait);
5086 MAKE_INT_ENTRY(nowait);
5087 MAKE_LONG_LONG_ENTRY(current);
5088 MAKE_LONG_LONG_ENTRY(value);
5089 MAKE_LONG_LONG_ENTRY(last_value);
5090 MAKE_LONG_LONG_ENTRY(min);
5091 MAKE_LONG_LONG_ENTRY(max);
5092 MAKE_INT_ENTRY(cache_size);
5093 MAKE_INT_ENTRY(flags);
5094
5095#undef MAKE_INT_ENTRY
5096#undef MAKE_LONG_LONG_ENTRY
5097
5098 free(sp);
5099 return dict_stat;
5100}
5101#endif
5102
5103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005104/* --------------------------------------------------------------------- */
5105/* Method definition tables and type objects */
5106
5107static PyMethodDef DB_methods[] = {
5108 {"append", (PyCFunction)DB_append, METH_VARARGS},
5109#if (DBVER >= 33)
5110 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5111#endif
5112 {"close", (PyCFunction)DB_close, METH_VARARGS},
5113#if (DBVER >= 32)
5114 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5115 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5116#endif
5117 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5118 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5119 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5120 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005121#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005122 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005123#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005124 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5125 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5126 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5127 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5128 {"join", (PyCFunction)DB_join, METH_VARARGS},
5129 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5130 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5131 {"items", (PyCFunction)DB_items, METH_VARARGS},
5132 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5133 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5134 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5135 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5136 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5137 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005138#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005139 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005140#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005141 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005142#if (DBVER >= 41)
5143 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5144#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005145 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5146 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5147 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5148 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5149 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5150 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5151 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5152 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5153 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5154#if (DBVER >= 32)
5155 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5156#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005157 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5159#if (DBVER >= 33)
5160 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5161#endif
5162 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5163 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5164 {"values", (PyCFunction)DB_values, METH_VARARGS},
5165 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5166 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5167 {NULL, NULL} /* sentinel */
5168};
5169
5170
5171static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005172 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005173 (binaryfunc)DB_subscript, /*mp_subscript*/
5174 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5175};
5176
5177
5178static PyMethodDef DBCursor_methods[] = {
5179 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5180 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5181 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5182 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5183 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5184 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5185 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005186#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005187 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005189 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5190 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5191 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5192 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5193 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5194 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5195 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5196 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005197 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005198 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005199 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5200 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5201 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5202 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5203 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5204 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5205 {NULL, NULL} /* sentinel */
5206};
5207
5208
5209static PyMethodDef DBEnv_methods[] = {
5210 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5211 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5212 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005213#if (DBVER >= 41)
5214 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5215 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5216 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5217#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005218#if (DBVER >= 40)
5219 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5220#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005221 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005222 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5223 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5224#if (DBVER >= 32)
5225 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5226#endif
5227 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5228 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5229 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005230#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005231 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005232#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005233 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5234 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5235#if (DBVER >= 32)
5236 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5237 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5238 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5239#endif
5240 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5241 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5242 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5243 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5244 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5245 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005246 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005247 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5248 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5249 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5250 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5251 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5252 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005253#if (DBVER >= 40)
5254 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5255#endif
5256#if (DBVER >= 44)
5257 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5260 {NULL, NULL} /* sentinel */
5261};
5262
5263
5264static PyMethodDef DBTxn_methods[] = {
5265 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5266 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5267 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5268 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5269 {NULL, NULL} /* sentinel */
5270};
5271
5272
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005273#if (DBVER >= 43)
5274static PyMethodDef DBSequence_methods[] = {
5275 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5276 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5277 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5278 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5279 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5280 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5281 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5282 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5283 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5284 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5285 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5286 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5287 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5288 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5289 {NULL, NULL} /* sentinel */
5290};
5291#endif
5292
5293
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005294static PyObject*
5295DB_getattr(DBObject* self, char *name)
5296{
5297 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5298}
5299
5300
5301static PyObject*
5302DBEnv_getattr(DBEnvObject* self, char *name)
5303{
5304 if (!strcmp(name, "db_home")) {
5305 CHECK_ENV_NOT_CLOSED(self);
5306 if (self->db_env->db_home == NULL) {
5307 RETURN_NONE();
5308 }
5309 return PyString_FromString(self->db_env->db_home);
5310 }
5311
5312 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5313}
5314
5315
5316static PyObject*
5317DBCursor_getattr(DBCursorObject* self, char *name)
5318{
5319 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5320}
5321
5322static PyObject*
5323DBTxn_getattr(DBTxnObject* self, char *name)
5324{
5325 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5326}
5327
5328static PyObject*
5329DBLock_getattr(DBLockObject* self, char *name)
5330{
5331 return NULL;
5332}
5333
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005334#if (DBVER >= 43)
5335static PyObject*
5336DBSequence_getattr(DBSequenceObject* self, char *name)
5337{
5338 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5339}
5340#endif
5341
Neal Norwitz227b5332006-03-22 09:28:35 +00005342static PyTypeObject DB_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005343 PyObject_HEAD_INIT(NULL)
5344 0, /*ob_size*/
5345 "DB", /*tp_name*/
5346 sizeof(DBObject), /*tp_basicsize*/
5347 0, /*tp_itemsize*/
5348 /* methods */
5349 (destructor)DB_dealloc, /*tp_dealloc*/
5350 0, /*tp_print*/
5351 (getattrfunc)DB_getattr, /*tp_getattr*/
5352 0, /*tp_setattr*/
5353 0, /*tp_compare*/
5354 0, /*tp_repr*/
5355 0, /*tp_as_number*/
5356 0, /*tp_as_sequence*/
5357 &DB_mapping,/*tp_as_mapping*/
5358 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005359#ifdef HAVE_WEAKREF
5360 0, /* tp_call */
5361 0, /* tp_str */
5362 0, /* tp_getattro */
5363 0, /* tp_setattro */
5364 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005365 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005366 0, /* tp_doc */
5367 0, /* tp_traverse */
5368 0, /* tp_clear */
5369 0, /* tp_richcompare */
5370 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5371#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005372};
5373
5374
Neal Norwitz227b5332006-03-22 09:28:35 +00005375static PyTypeObject DBCursor_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005376 PyObject_HEAD_INIT(NULL)
5377 0, /*ob_size*/
5378 "DBCursor", /*tp_name*/
5379 sizeof(DBCursorObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5383 0, /*tp_print*/
5384 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5391 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005392#ifdef HAVE_WEAKREF
5393 0, /* tp_call */
5394 0, /* tp_str */
5395 0, /* tp_getattro */
5396 0, /* tp_setattro */
5397 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005398 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005399 0, /* tp_doc */
5400 0, /* tp_traverse */
5401 0, /* tp_clear */
5402 0, /* tp_richcompare */
5403 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5404#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005405};
5406
5407
Neal Norwitz227b5332006-03-22 09:28:35 +00005408static PyTypeObject DBEnv_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005409 PyObject_HEAD_INIT(NULL)
5410 0, /*ob_size*/
5411 "DBEnv", /*tp_name*/
5412 sizeof(DBEnvObject), /*tp_basicsize*/
5413 0, /*tp_itemsize*/
5414 /* methods */
5415 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5416 0, /*tp_print*/
5417 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5418 0, /*tp_setattr*/
5419 0, /*tp_compare*/
5420 0, /*tp_repr*/
5421 0, /*tp_as_number*/
5422 0, /*tp_as_sequence*/
5423 0, /*tp_as_mapping*/
5424 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005425#ifdef HAVE_WEAKREF
5426 0, /* tp_call */
5427 0, /* tp_str */
5428 0, /* tp_getattro */
5429 0, /* tp_setattro */
5430 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005431 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005432 0, /* tp_doc */
5433 0, /* tp_traverse */
5434 0, /* tp_clear */
5435 0, /* tp_richcompare */
5436 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5437#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005438};
5439
Neal Norwitz227b5332006-03-22 09:28:35 +00005440static PyTypeObject DBTxn_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005441 PyObject_HEAD_INIT(NULL)
5442 0, /*ob_size*/
5443 "DBTxn", /*tp_name*/
5444 sizeof(DBTxnObject), /*tp_basicsize*/
5445 0, /*tp_itemsize*/
5446 /* methods */
5447 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5448 0, /*tp_print*/
5449 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5450 0, /*tp_setattr*/
5451 0, /*tp_compare*/
5452 0, /*tp_repr*/
5453 0, /*tp_as_number*/
5454 0, /*tp_as_sequence*/
5455 0, /*tp_as_mapping*/
5456 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005457#ifdef HAVE_WEAKREF
5458 0, /* tp_call */
5459 0, /* tp_str */
5460 0, /* tp_getattro */
5461 0, /* tp_setattro */
5462 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005463 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005464 0, /* tp_doc */
5465 0, /* tp_traverse */
5466 0, /* tp_clear */
5467 0, /* tp_richcompare */
5468 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5469#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005470};
5471
5472
Neal Norwitz227b5332006-03-22 09:28:35 +00005473static PyTypeObject DBLock_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005474 PyObject_HEAD_INIT(NULL)
5475 0, /*ob_size*/
5476 "DBLock", /*tp_name*/
5477 sizeof(DBLockObject), /*tp_basicsize*/
5478 0, /*tp_itemsize*/
5479 /* methods */
5480 (destructor)DBLock_dealloc, /*tp_dealloc*/
5481 0, /*tp_print*/
5482 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5483 0, /*tp_setattr*/
5484 0, /*tp_compare*/
5485 0, /*tp_repr*/
5486 0, /*tp_as_number*/
5487 0, /*tp_as_sequence*/
5488 0, /*tp_as_mapping*/
5489 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005490#ifdef HAVE_WEAKREF
5491 0, /* tp_call */
5492 0, /* tp_str */
5493 0, /* tp_getattro */
5494 0, /* tp_setattro */
5495 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005496 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005497 0, /* tp_doc */
5498 0, /* tp_traverse */
5499 0, /* tp_clear */
5500 0, /* tp_richcompare */
5501 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5502#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005503};
5504
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005505#if (DBVER >= 43)
5506static PyTypeObject DBSequence_Type = {
5507 PyObject_HEAD_INIT(NULL)
5508 0, /*ob_size*/
5509 "DBSequence", /*tp_name*/
5510 sizeof(DBSequenceObject), /*tp_basicsize*/
5511 0, /*tp_itemsize*/
5512 /* methods */
5513 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5514 0, /*tp_print*/
5515 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5516 0, /*tp_setattr*/
5517 0, /*tp_compare*/
5518 0, /*tp_repr*/
5519 0, /*tp_as_number*/
5520 0, /*tp_as_sequence*/
5521 0, /*tp_as_mapping*/
5522 0, /*tp_hash*/
5523#ifdef HAVE_WEAKREF
5524 0, /* tp_call */
5525 0, /* tp_str */
5526 0, /* tp_getattro */
5527 0, /* tp_setattro */
5528 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005529 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005530 0, /* tp_doc */
5531 0, /* tp_traverse */
5532 0, /* tp_clear */
5533 0, /* tp_richcompare */
5534 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5535#endif
5536};
5537#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005538
5539/* --------------------------------------------------------------------- */
5540/* Module-level functions */
5541
5542static PyObject*
5543DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5544{
5545 PyObject* dbenvobj = NULL;
5546 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005547 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005548
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5550 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005551 return NULL;
5552 if (dbenvobj == Py_None)
5553 dbenvobj = NULL;
5554 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5555 makeTypeError("DBEnv", dbenvobj);
5556 return NULL;
5557 }
5558
5559 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5560}
5561
5562
5563static PyObject*
5564DBEnv_construct(PyObject* self, PyObject* args)
5565{
5566 int flags = 0;
5567 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5568 return (PyObject* )newDBEnvObject(flags);
5569}
5570
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005571#if (DBVER >= 43)
5572static PyObject*
5573DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5574{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005575 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005576 int flags = 0;
5577 static char* kwnames[] = { "db", "flags", NULL};
5578
5579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5580 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005581 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005582 makeTypeError("DB", dbobj);
5583 return NULL;
5584 }
5585 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5586}
5587#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005588
5589static char bsddb_version_doc[] =
5590"Returns a tuple of major, minor, and patch release numbers of the\n\
5591underlying DB library.";
5592
5593static PyObject*
5594bsddb_version(PyObject* self, PyObject* args)
5595{
5596 int major, minor, patch;
5597
5598 if (!PyArg_ParseTuple(args, ":version"))
5599 return NULL;
5600 db_version(&major, &minor, &patch);
5601 return Py_BuildValue("(iii)", major, minor, patch);
5602}
5603
5604
5605/* List of functions defined in the module */
5606
5607static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005608 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5609 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5610#if (DBVER >= 43)
5611 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5612#endif
5613 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005614 {NULL, NULL} /* sentinel */
5615};
5616
5617
5618/* --------------------------------------------------------------------- */
5619/* Module initialization */
5620
5621
5622/* Convenience routine to export an integer value.
5623 * Errors are silently ignored, for better or for worse...
5624 */
5625#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5626
Gregory P. Smith41631e82003-09-21 00:08:14 +00005627#define MODULE_NAME_MAX_LEN 11
5628static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005629
Neal Norwitzf6657e62006-12-28 04:47:50 +00005630PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005631{
5632 PyObject* m;
5633 PyObject* d;
5634 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5635 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5636 PyObject* cvsid_s = PyString_FromString( rcs_id );
5637
5638 /* Initialize the type of the new type objects here; doing it here
5639 is required for portability to Windows without requiring C++. */
5640 DB_Type.ob_type = &PyType_Type;
5641 DBCursor_Type.ob_type = &PyType_Type;
5642 DBEnv_Type.ob_type = &PyType_Type;
5643 DBTxn_Type.ob_type = &PyType_Type;
5644 DBLock_Type.ob_type = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005645#if (DBVER >= 43)
5646 DBSequence_Type.ob_type = &PyType_Type;
5647#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005648
5649
Mark Hammonda69d4092003-04-22 23:13:27 +00005650#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005651 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005652 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653#endif
5654
5655 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005656 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005657 if (m == NULL)
5658 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005659
5660 /* Add some symbolic constants to the module */
5661 d = PyModule_GetDict(m);
5662 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5663 PyDict_SetItemString(d, "cvsid", cvsid_s);
5664 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5665 Py_DECREF(pybsddb_version_s);
5666 pybsddb_version_s = NULL;
5667 Py_DECREF(cvsid_s);
5668 cvsid_s = NULL;
5669 Py_DECREF(db_version_s);
5670 db_version_s = NULL;
5671
5672 ADD_INT(d, DB_VERSION_MAJOR);
5673 ADD_INT(d, DB_VERSION_MINOR);
5674 ADD_INT(d, DB_VERSION_PATCH);
5675
5676 ADD_INT(d, DB_MAX_PAGES);
5677 ADD_INT(d, DB_MAX_RECORDS);
5678
Gregory P. Smith41631e82003-09-21 00:08:14 +00005679#if (DBVER >= 42)
5680 ADD_INT(d, DB_RPCCLIENT);
5681#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005683 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5684 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5685#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005686 ADD_INT(d, DB_XA_CREATE);
5687
5688 ADD_INT(d, DB_CREATE);
5689 ADD_INT(d, DB_NOMMAP);
5690 ADD_INT(d, DB_THREAD);
5691
5692 ADD_INT(d, DB_FORCE);
5693 ADD_INT(d, DB_INIT_CDB);
5694 ADD_INT(d, DB_INIT_LOCK);
5695 ADD_INT(d, DB_INIT_LOG);
5696 ADD_INT(d, DB_INIT_MPOOL);
5697 ADD_INT(d, DB_INIT_TXN);
5698#if (DBVER >= 32)
5699 ADD_INT(d, DB_JOINENV);
5700#endif
5701
5702 ADD_INT(d, DB_RECOVER);
5703 ADD_INT(d, DB_RECOVER_FATAL);
5704 ADD_INT(d, DB_TXN_NOSYNC);
5705 ADD_INT(d, DB_USE_ENVIRON);
5706 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5707
5708 ADD_INT(d, DB_LOCKDOWN);
5709 ADD_INT(d, DB_PRIVATE);
5710 ADD_INT(d, DB_SYSTEM_MEM);
5711
5712 ADD_INT(d, DB_TXN_SYNC);
5713 ADD_INT(d, DB_TXN_NOWAIT);
5714
5715 ADD_INT(d, DB_EXCL);
5716 ADD_INT(d, DB_FCNTL_LOCKING);
5717 ADD_INT(d, DB_ODDFILESIZE);
5718 ADD_INT(d, DB_RDWRMASTER);
5719 ADD_INT(d, DB_RDONLY);
5720 ADD_INT(d, DB_TRUNCATE);
5721#if (DBVER >= 32)
5722 ADD_INT(d, DB_EXTENT);
5723 ADD_INT(d, DB_CDB_ALLDB);
5724 ADD_INT(d, DB_VERIFY);
5725#endif
5726 ADD_INT(d, DB_UPGRADE);
5727
5728 ADD_INT(d, DB_AGGRESSIVE);
5729 ADD_INT(d, DB_NOORDERCHK);
5730 ADD_INT(d, DB_ORDERCHKONLY);
5731 ADD_INT(d, DB_PR_PAGE);
5732#if ! (DBVER >= 33)
5733 ADD_INT(d, DB_VRFY_FLAGMASK);
5734 ADD_INT(d, DB_PR_HEADERS);
5735#endif
5736 ADD_INT(d, DB_PR_RECOVERYTEST);
5737 ADD_INT(d, DB_SALVAGE);
5738
5739 ADD_INT(d, DB_LOCK_NORUN);
5740 ADD_INT(d, DB_LOCK_DEFAULT);
5741 ADD_INT(d, DB_LOCK_OLDEST);
5742 ADD_INT(d, DB_LOCK_RANDOM);
5743 ADD_INT(d, DB_LOCK_YOUNGEST);
5744#if (DBVER >= 33)
5745 ADD_INT(d, DB_LOCK_MAXLOCKS);
5746 ADD_INT(d, DB_LOCK_MINLOCKS);
5747 ADD_INT(d, DB_LOCK_MINWRITE);
5748#endif
5749
5750
5751#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005752 /* docs say to use zero instead */
5753 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005754#else
5755 ADD_INT(d, DB_LOCK_CONFLICT);
5756#endif
5757
5758 ADD_INT(d, DB_LOCK_DUMP);
5759 ADD_INT(d, DB_LOCK_GET);
5760 ADD_INT(d, DB_LOCK_INHERIT);
5761 ADD_INT(d, DB_LOCK_PUT);
5762 ADD_INT(d, DB_LOCK_PUT_ALL);
5763 ADD_INT(d, DB_LOCK_PUT_OBJ);
5764
5765 ADD_INT(d, DB_LOCK_NG);
5766 ADD_INT(d, DB_LOCK_READ);
5767 ADD_INT(d, DB_LOCK_WRITE);
5768 ADD_INT(d, DB_LOCK_NOWAIT);
5769#if (DBVER >= 32)
5770 ADD_INT(d, DB_LOCK_WAIT);
5771#endif
5772 ADD_INT(d, DB_LOCK_IWRITE);
5773 ADD_INT(d, DB_LOCK_IREAD);
5774 ADD_INT(d, DB_LOCK_IWR);
5775#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005776#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005777 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005778#else
5779 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005781 ADD_INT(d, DB_LOCK_WWRITE);
5782#endif
5783
5784 ADD_INT(d, DB_LOCK_RECORD);
5785 ADD_INT(d, DB_LOCK_UPGRADE);
5786#if (DBVER >= 32)
5787 ADD_INT(d, DB_LOCK_SWITCH);
5788#endif
5789#if (DBVER >= 33)
5790 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5791#endif
5792
5793 ADD_INT(d, DB_LOCK_NOWAIT);
5794 ADD_INT(d, DB_LOCK_RECORD);
5795 ADD_INT(d, DB_LOCK_UPGRADE);
5796
5797#if (DBVER >= 33)
5798 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005799#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005800 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005801#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 ADD_INT(d, DB_LSTAT_FREE);
5803 ADD_INT(d, DB_LSTAT_HELD);
5804#if (DBVER == 33)
5805 ADD_INT(d, DB_LSTAT_NOGRANT);
5806#endif
5807 ADD_INT(d, DB_LSTAT_PENDING);
5808 ADD_INT(d, DB_LSTAT_WAITING);
5809#endif
5810
5811 ADD_INT(d, DB_ARCH_ABS);
5812 ADD_INT(d, DB_ARCH_DATA);
5813 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005814#if (DBVER >= 42)
5815 ADD_INT(d, DB_ARCH_REMOVE);
5816#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005817
5818 ADD_INT(d, DB_BTREE);
5819 ADD_INT(d, DB_HASH);
5820 ADD_INT(d, DB_RECNO);
5821 ADD_INT(d, DB_QUEUE);
5822 ADD_INT(d, DB_UNKNOWN);
5823
5824 ADD_INT(d, DB_DUP);
5825 ADD_INT(d, DB_DUPSORT);
5826 ADD_INT(d, DB_RECNUM);
5827 ADD_INT(d, DB_RENUMBER);
5828 ADD_INT(d, DB_REVSPLITOFF);
5829 ADD_INT(d, DB_SNAPSHOT);
5830
5831 ADD_INT(d, DB_JOIN_NOSORT);
5832
5833 ADD_INT(d, DB_AFTER);
5834 ADD_INT(d, DB_APPEND);
5835 ADD_INT(d, DB_BEFORE);
5836 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005837#if (DBVER >= 41)
5838 _addIntToDict(d, "DB_CHECKPOINT", 0);
5839#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005840 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005841 ADD_INT(d, DB_CURLSN);
5842#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005843#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005844 ADD_INT(d, DB_COMMIT);
5845#endif
5846 ADD_INT(d, DB_CONSUME);
5847#if (DBVER >= 32)
5848 ADD_INT(d, DB_CONSUME_WAIT);
5849#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005850 ADD_INT(d, DB_CURRENT);
5851#if (DBVER >= 33)
5852 ADD_INT(d, DB_FAST_STAT);
5853#endif
5854 ADD_INT(d, DB_FIRST);
5855 ADD_INT(d, DB_FLUSH);
5856 ADD_INT(d, DB_GET_BOTH);
5857 ADD_INT(d, DB_GET_RECNO);
5858 ADD_INT(d, DB_JOIN_ITEM);
5859 ADD_INT(d, DB_KEYFIRST);
5860 ADD_INT(d, DB_KEYLAST);
5861 ADD_INT(d, DB_LAST);
5862 ADD_INT(d, DB_NEXT);
5863 ADD_INT(d, DB_NEXT_DUP);
5864 ADD_INT(d, DB_NEXT_NODUP);
5865 ADD_INT(d, DB_NODUPDATA);
5866 ADD_INT(d, DB_NOOVERWRITE);
5867 ADD_INT(d, DB_NOSYNC);
5868 ADD_INT(d, DB_POSITION);
5869 ADD_INT(d, DB_PREV);
5870 ADD_INT(d, DB_PREV_NODUP);
5871 ADD_INT(d, DB_RECORDCOUNT);
5872 ADD_INT(d, DB_SET);
5873 ADD_INT(d, DB_SET_RANGE);
5874 ADD_INT(d, DB_SET_RECNO);
5875 ADD_INT(d, DB_WRITECURSOR);
5876
5877 ADD_INT(d, DB_OPFLAGS_MASK);
5878 ADD_INT(d, DB_RMW);
5879#if (DBVER >= 33)
5880 ADD_INT(d, DB_DIRTY_READ);
5881 ADD_INT(d, DB_MULTIPLE);
5882 ADD_INT(d, DB_MULTIPLE_KEY);
5883#endif
5884
Gregory P. Smith29602d22006-01-24 09:46:48 +00005885#if (DBVER >= 44)
5886 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5887 ADD_INT(d, DB_READ_COMMITTED);
5888#endif
5889
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005890#if (DBVER >= 33)
5891 ADD_INT(d, DB_DONOTINDEX);
5892#endif
5893
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005894#if (DBVER >= 41)
5895 _addIntToDict(d, "DB_INCOMPLETE", 0);
5896#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005897 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899 ADD_INT(d, DB_KEYEMPTY);
5900 ADD_INT(d, DB_KEYEXIST);
5901 ADD_INT(d, DB_LOCK_DEADLOCK);
5902 ADD_INT(d, DB_LOCK_NOTGRANTED);
5903 ADD_INT(d, DB_NOSERVER);
5904 ADD_INT(d, DB_NOSERVER_HOME);
5905 ADD_INT(d, DB_NOSERVER_ID);
5906 ADD_INT(d, DB_NOTFOUND);
5907 ADD_INT(d, DB_OLD_VERSION);
5908 ADD_INT(d, DB_RUNRECOVERY);
5909 ADD_INT(d, DB_VERIFY_BAD);
5910#if (DBVER >= 33)
5911 ADD_INT(d, DB_PAGE_NOTFOUND);
5912 ADD_INT(d, DB_SECONDARY_BAD);
5913#endif
5914#if (DBVER >= 40)
5915 ADD_INT(d, DB_STAT_CLEAR);
5916 ADD_INT(d, DB_REGION_INIT);
5917 ADD_INT(d, DB_NOLOCKING);
5918 ADD_INT(d, DB_YIELDCPU);
5919 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5920 ADD_INT(d, DB_NOPANIC);
5921#endif
5922
Gregory P. Smith41631e82003-09-21 00:08:14 +00005923#if (DBVER >= 42)
5924 ADD_INT(d, DB_TIME_NOTGRANTED);
5925 ADD_INT(d, DB_TXN_NOT_DURABLE);
5926 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5927 ADD_INT(d, DB_LOG_AUTOREMOVE);
5928 ADD_INT(d, DB_DIRECT_LOG);
5929 ADD_INT(d, DB_DIRECT_DB);
5930 ADD_INT(d, DB_INIT_REP);
5931 ADD_INT(d, DB_ENCRYPT);
5932 ADD_INT(d, DB_CHKSUM);
5933#endif
5934
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005935#if (DBVER >= 43)
5936 ADD_INT(d, DB_LOG_INMEMORY);
5937 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005938 ADD_INT(d, DB_SEQ_DEC);
5939 ADD_INT(d, DB_SEQ_INC);
5940 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005941#endif
5942
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005943#if (DBVER >= 41)
5944 ADD_INT(d, DB_ENCRYPT_AES);
5945 ADD_INT(d, DB_AUTO_COMMIT);
5946#else
5947 /* allow berkeleydb 4.1 aware apps to run on older versions */
5948 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5949#endif
5950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005951 ADD_INT(d, EINVAL);
5952 ADD_INT(d, EACCES);
5953 ADD_INT(d, ENOSPC);
5954 ADD_INT(d, ENOMEM);
5955 ADD_INT(d, EAGAIN);
5956 ADD_INT(d, EBUSY);
5957 ADD_INT(d, EEXIST);
5958 ADD_INT(d, ENOENT);
5959 ADD_INT(d, EPERM);
5960
Barry Warsaw1baa9822003-03-31 19:51:29 +00005961#if (DBVER >= 40)
5962 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5963 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5964#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005965
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005966 /* The exception name must be correct for pickled exception *
5967 * objects to unpickle properly. */
5968#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5969#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5970#else
5971#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5972#endif
5973
5974 /* All the rest of the exceptions derive only from DBError */
5975#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5976 PyDict_SetItemString(d, #name, name)
5977
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005978 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005979 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5980 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981
Gregory P. Smithe9477062005-06-04 06:46:59 +00005982 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5983 * from both DBError and KeyError, since the API only supports
5984 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005985 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005986 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5987 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 Py_file_input, d, d);
5989 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005990 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005991 PyDict_DelItemString(d, "KeyError");
5992
5993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005994#if !INCOMPLETE_IS_WARNING
5995 MAKE_EX(DBIncompleteError);
5996#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005997 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005998 MAKE_EX(DBKeyEmptyError);
5999 MAKE_EX(DBKeyExistError);
6000 MAKE_EX(DBLockDeadlockError);
6001 MAKE_EX(DBLockNotGrantedError);
6002 MAKE_EX(DBOldVersionError);
6003 MAKE_EX(DBRunRecoveryError);
6004 MAKE_EX(DBVerifyBadError);
6005 MAKE_EX(DBNoServerError);
6006 MAKE_EX(DBNoServerHomeError);
6007 MAKE_EX(DBNoServerIDError);
6008#if (DBVER >= 33)
6009 MAKE_EX(DBPageNotFoundError);
6010 MAKE_EX(DBSecondaryBadError);
6011#endif
6012
6013 MAKE_EX(DBInvalidArgError);
6014 MAKE_EX(DBAccessError);
6015 MAKE_EX(DBNoSpaceError);
6016 MAKE_EX(DBNoMemoryError);
6017 MAKE_EX(DBAgainError);
6018 MAKE_EX(DBBusyError);
6019 MAKE_EX(DBFileExistsError);
6020 MAKE_EX(DBNoSuchFileError);
6021 MAKE_EX(DBPermissionsError);
6022
6023#undef MAKE_EX
6024
6025 /* Check for errors */
6026 if (PyErr_Occurred()) {
6027 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006028 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006029 }
6030}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006031
6032/* allow this module to be named _pybsddb so that it can be installed
6033 * and imported on top of python >= 2.3 that includes its own older
6034 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006035PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006036{
6037 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6038 init_bsddb();
6039}