blob: 943a4ea0e77df08f3df8748282229926a811264c [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 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +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)
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
Gregory P. Smith2e49f782007-11-07 07:25:20 +0000101#define PY_BSDDB_VERSION "4.4.5.3"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +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
Gregory P. Smithf0547d02006-06-05 17:38:04 +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;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
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)
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000428 /*
429 * NOTE(gps): I don't like doing a data copy here, it seems
430 * wasteful. But without a clean way to tell FREE_DBT if it
431 * should free key->data or not we have to. Other places in
432 * the code check for DB_THREAD and forceably set DBT_MALLOC
433 * when we otherwise would leave flags 0 to indicate that.
434 */
Gregory P. Smith2c3e0d92007-11-01 21:22:40 +0000435 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000436 if (key->data == NULL) {
437 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
438 return 0;
439 }
Gregory P. Smith2c3e0d92007-11-01 21:22:40 +0000440 memcpy(key->data, PyString_AS_STRING(keyobj),
441 PyString_GET_SIZE(keyobj));
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000442 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000443 key->size = PyString_GET_SIZE(keyobj);
444 }
445
446 else if (PyInt_Check(keyobj)) {
447 /* verify access method type */
448 type = _DB_get_type(self);
449 if (type == -1)
450 return 0;
451 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000452 /* if BTREE then an Integer key is allowed with the
453 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 *pflags |= DB_SET_RECNO;
455 }
456 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000457 PyErr_SetString(
458 PyExc_TypeError,
459 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000460 return 0;
461 }
462
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000463 /* Make a key out of the requested recno, use allocated space so DB
464 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 recno = PyInt_AS_LONG(keyobj);
466 key->data = malloc(sizeof(db_recno_t));
467 if (key->data == NULL) {
468 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
469 return 0;
470 }
471 key->ulen = key->size = sizeof(db_recno_t);
472 memcpy(key->data, &recno, sizeof(db_recno_t));
473 key->flags = DB_DBT_REALLOC;
474 }
475 else {
476 PyErr_Format(PyExc_TypeError,
477 "String or Integer object expected for key, %s found",
478 keyobj->ob_type->tp_name);
479 return 0;
480 }
481
482 return 1;
483}
484
485
486/* Add partial record access to an existing DBT data struct.
487 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
488 and the data storage/retrieval will be done using dlen and doff. */
489static int add_partial_dbt(DBT* d, int dlen, int doff) {
490 /* if neither were set we do nothing (-1 is the default value) */
491 if ((dlen == -1) && (doff == -1)) {
492 return 1;
493 }
494
495 if ((dlen < 0) || (doff < 0)) {
496 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
497 return 0;
498 }
499
500 d->flags = d->flags | DB_DBT_PARTIAL;
501 d->dlen = (unsigned int) dlen;
502 d->doff = (unsigned int) doff;
503 return 1;
504}
505
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000506/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
507/* TODO: make this use the native libc strlcpy() when available (BSD) */
508unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
509{
510 unsigned int srclen, copylen;
511
512 srclen = strlen(src);
513 if (n <= 0)
514 return srclen;
515 copylen = (srclen > n-1) ? n-1 : srclen;
516 /* populate dest[0] thru dest[copylen-1] */
517 memcpy(dest, src, copylen);
518 /* guarantee null termination */
519 dest[copylen] = 0;
520
521 return srclen;
522}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000524/* Callback used to save away more information about errors from the DB
525 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000526static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000527#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000528static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000529#else
530static void _db_errorCallback(const DB_ENV *db_env,
531 const char* prefix, const char* msg)
532#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000534 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000535}
536
537
538/* make a nice exception object to raise for errors. */
539static int makeDBError(int err)
540{
541 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000542 PyObject *errObj = NULL;
543 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000545 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546
547 switch (err) {
548 case 0: /* successful, no error */ break;
549
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000550#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000551 case DB_INCOMPLETE:
552#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000553 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
554 /* Ensure that bytes_left never goes negative */
555 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
556 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
557 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000559 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000561 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000562#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
564#else
565 fprintf(stderr, errTxt);
566 fprintf(stderr, "\n");
567#endif
568
569#else /* do an exception instead */
570 errObj = DBIncompleteError;
571#endif
572 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000573#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000574
575 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
576 case DB_KEYEXIST: errObj = DBKeyExistError; break;
577 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
578 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
579 case DB_NOTFOUND: errObj = DBNotFoundError; break;
580 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
581 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
582 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
583 case DB_NOSERVER: errObj = DBNoServerError; break;
584 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
585 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
586#if (DBVER >= 33)
587 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
588 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
589#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000590 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000591
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000592#if (DBVER >= 43)
593 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
594 case ENOMEM: errObj = PyExc_MemoryError; break;
595#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 case EINVAL: errObj = DBInvalidArgError; break;
597 case EACCES: errObj = DBAccessError; break;
598 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000599 case EAGAIN: errObj = DBAgainError; break;
600 case EBUSY : errObj = DBBusyError; break;
601 case EEXIST: errObj = DBFileExistsError; break;
602 case ENOENT: errObj = DBNoSuchFileError; break;
603 case EPERM : errObj = DBPermissionsError; break;
604
605 default: errObj = DBError; break;
606 }
607
608 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000609 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
610 /* Ensure that bytes_left never goes negative */
611 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
612 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
613 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000615 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000616 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000617 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000618
619 errTuple = Py_BuildValue("(is)", err, errTxt);
620 PyErr_SetObject(errObj, errTuple);
621 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000622 }
623
624 return ((errObj != NULL) || exceptionRaised);
625}
626
627
628
629/* set a type exception */
630static void makeTypeError(char* expected, PyObject* found)
631{
632 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
633 expected, found->ob_type->tp_name);
634}
635
636
637/* verify that an obj is either None or a DBTxn, and set the txn pointer */
638static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
639{
640 if (txnobj == Py_None || txnobj == NULL) {
641 *txn = NULL;
642 return 1;
643 }
644 if (DBTxnObject_Check(txnobj)) {
645 *txn = ((DBTxnObject*)txnobj)->txn;
646 return 1;
647 }
648 else
649 makeTypeError("DBTxn", txnobj);
650 return 0;
651}
652
653
654/* Delete a key from a database
655 Returns 0 on success, -1 on an error. */
656static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
657{
658 int err;
659
660 MYDB_BEGIN_ALLOW_THREADS;
661 err = self->db->del(self->db, txn, key, 0);
662 MYDB_END_ALLOW_THREADS;
663 if (makeDBError(err)) {
664 return -1;
665 }
666 self->haveStat = 0;
667 return 0;
668}
669
670
671/* Store a key into a database
672 Returns 0 on success, -1 on an error. */
673static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
674{
675 int err;
676
677 MYDB_BEGIN_ALLOW_THREADS;
678 err = self->db->put(self->db, txn, key, data, flags);
679 MYDB_END_ALLOW_THREADS;
680 if (makeDBError(err)) {
681 return -1;
682 }
683 self->haveStat = 0;
684 return 0;
685}
686
687/* Get a key/data pair from a cursor */
688static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
689 PyObject *args, PyObject *kwargs, char *format)
690{
691 int err;
692 PyObject* retval = NULL;
693 DBT key, data;
694 int dlen = -1;
695 int doff = -1;
696 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000697 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000698
699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
700 &flags, &dlen, &doff))
701 return NULL;
702
703 CHECK_CURSOR_NOT_CLOSED(self);
704
705 flags |= extra_flags;
706 CLEAR_DBT(key);
707 CLEAR_DBT(data);
708 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
709 /* Tell BerkeleyDB to malloc the return value (thread safe) */
710 data.flags = DB_DBT_MALLOC;
711 key.flags = DB_DBT_MALLOC;
712 }
713 if (!add_partial_dbt(&data, dlen, doff))
714 return NULL;
715
716 MYDB_BEGIN_ALLOW_THREADS;
717 err = self->dbc->c_get(self->dbc, &key, &data, flags);
718 MYDB_END_ALLOW_THREADS;
719
Gregory P. Smithe9477062005-06-04 06:46:59 +0000720 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
721 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000722 Py_INCREF(Py_None);
723 retval = Py_None;
724 }
725 else if (makeDBError(err)) {
726 retval = NULL;
727 }
728 else { /* otherwise, success! */
729
730 /* if Recno or Queue, return the key as an Int */
731 switch (_DB_get_type(self->mydb)) {
732 case -1:
733 retval = NULL;
734 break;
735
736 case DB_RECNO:
737 case DB_QUEUE:
738 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
739 data.data, data.size);
740 break;
741 case DB_HASH:
742 case DB_BTREE:
743 default:
744 retval = Py_BuildValue("s#s#", key.data, key.size,
745 data.data, data.size);
746 break;
747 }
748 }
749 if (!err) {
750 FREE_DBT(key);
751 FREE_DBT(data);
752 }
753 return retval;
754}
755
756
757/* add an integer to a dictionary using the given name as a key */
758static void _addIntToDict(PyObject* dict, char *name, int value)
759{
760 PyObject* v = PyInt_FromLong((long) value);
761 if (!v || PyDict_SetItemString(dict, name, v))
762 PyErr_Clear();
763
764 Py_XDECREF(v);
765}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000766#if (DBVER >= 43)
767/* add an db_seq_t to a dictionary using the given name as a key */
768static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
769{
770 PyObject* v = PyLong_FromLongLong(value);
771 if (!v || PyDict_SetItemString(dict, name, v))
772 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000774 Py_XDECREF(v);
775}
776#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777
778
779
780/* --------------------------------------------------------------------- */
781/* Allocators and deallocators */
782
783static DBObject*
784newDBObject(DBEnvObject* arg, int flags)
785{
786 DBObject* self;
787 DB_ENV* db_env = NULL;
788 int err;
789
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000791 if (self == NULL)
792 return NULL;
793
794 self->haveStat = 0;
795 self->flags = 0;
796 self->setflags = 0;
797 self->myenvobj = NULL;
798#if (DBVER >= 33)
799 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000800 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000801 self->primaryDBType = 0;
802#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000803#ifdef HAVE_WEAKREF
804 self->in_weakreflist = NULL;
805#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806
807 /* keep a reference to our python DBEnv object */
808 if (arg) {
809 Py_INCREF(arg);
810 self->myenvobj = arg;
811 db_env = arg->db_env;
812 }
813
814 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000815 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000817 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
818 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000819
820 MYDB_BEGIN_ALLOW_THREADS;
821 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000822 if (self->db != NULL) {
823 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000825 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000827 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000829 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
830 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000831 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 if (makeDBError(err)) {
833 if (self->myenvobj) {
834 Py_DECREF(self->myenvobj);
835 self->myenvobj = NULL;
836 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000837 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 self = NULL;
839 }
840 return self;
841}
842
843
844static void
845DB_dealloc(DBObject* self)
846{
847 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000848 /* avoid closing a DB when its DBEnv has been closed out from under
849 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000851 (self->myenvobj && self->myenvobj->db_env))
852 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853 MYDB_BEGIN_ALLOW_THREADS;
854 self->db->close(self->db, 0);
855 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000856#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 } else {
858 PyErr_Warn(PyExc_RuntimeWarning,
859 "DB could not be closed in destructor: DBEnv already closed");
860#endif
861 }
862 self->db = NULL;
863 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000864#ifdef HAVE_WEAKREF
865 if (self->in_weakreflist != NULL) {
866 PyObject_ClearWeakRefs((PyObject *) self);
867 }
868#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 if (self->myenvobj) {
870 Py_DECREF(self->myenvobj);
871 self->myenvobj = NULL;
872 }
873#if (DBVER >= 33)
874 if (self->associateCallback != NULL) {
875 Py_DECREF(self->associateCallback);
876 self->associateCallback = NULL;
877 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000878 if (self->btCompareCallback != NULL) {
879 Py_DECREF(self->btCompareCallback);
880 self->btCompareCallback = NULL;
881 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000883 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000884}
885
886
887static DBCursorObject*
888newDBCursorObject(DBC* dbc, DBObject* db)
889{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000890 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000891 if (self == NULL)
892 return NULL;
893
894 self->dbc = dbc;
895 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000896#ifdef HAVE_WEAKREF
897 self->in_weakreflist = NULL;
898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899 Py_INCREF(self->mydb);
900 return self;
901}
902
903
904static void
905DBCursor_dealloc(DBCursorObject* self)
906{
907 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000908
909#ifdef HAVE_WEAKREF
910 if (self->in_weakreflist != NULL) {
911 PyObject_ClearWeakRefs((PyObject *) self);
912 }
913#endif
914
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915 if (self->dbc != NULL) {
916 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000917 /* If the underlying database has been closed, we don't
918 need to do anything. If the environment has been closed
919 we need to leak, as BerkeleyDB will crash trying to access
920 the environment. There was an exception when the
921 user closed the environment even though there still was
922 a database open. */
923 if (self->mydb->db && self->mydb->myenvobj &&
924 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000925 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000926 self->dbc = NULL;
927 MYDB_END_ALLOW_THREADS;
928 }
929 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931}
932
933
934static DBEnvObject*
935newDBEnvObject(int flags)
936{
937 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000938 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939 if (self == NULL)
940 return NULL;
941
942 self->closed = 1;
943 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000944 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
945 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000946#ifdef HAVE_WEAKREF
947 self->in_weakreflist = NULL;
948#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000949
950 MYDB_BEGIN_ALLOW_THREADS;
951 err = db_env_create(&self->db_env, flags);
952 MYDB_END_ALLOW_THREADS;
953 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000954 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000955 self = NULL;
956 }
957 else {
958 self->db_env->set_errcall(self->db_env, _db_errorCallback);
959 }
960 return self;
961}
962
963
964static void
965DBEnv_dealloc(DBEnvObject* self)
966{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000967#ifdef HAVE_WEAKREF
968 if (self->in_weakreflist != NULL) {
969 PyObject_ClearWeakRefs((PyObject *) self);
970 }
971#endif
972
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000973 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000974 MYDB_BEGIN_ALLOW_THREADS;
975 self->db_env->close(self->db_env, 0);
976 MYDB_END_ALLOW_THREADS;
977 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979}
980
981
982static DBTxnObject*
983newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
984{
985 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000986 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000987 if (self == NULL)
988 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000989 Py_INCREF(myenv);
990 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000991#ifdef HAVE_WEAKREF
992 self->in_weakreflist = NULL;
993#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994
995 MYDB_BEGIN_ALLOW_THREADS;
996#if (DBVER >= 40)
997 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
998#else
999 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1000#endif
1001 MYDB_END_ALLOW_THREADS;
1002 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001003 Py_DECREF(self->env);
1004 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005 self = NULL;
1006 }
1007 return self;
1008}
1009
1010
1011static void
1012DBTxn_dealloc(DBTxnObject* self)
1013{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001014#ifdef HAVE_WEAKREF
1015 if (self->in_weakreflist != NULL) {
1016 PyObject_ClearWeakRefs((PyObject *) self);
1017 }
1018#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019
Gregory P. Smith31c50652004-06-28 01:20:40 +00001020#ifdef HAVE_WARNINGS
1021 if (self->txn) {
1022 /* it hasn't been finalized, abort it! */
1023 MYDB_BEGIN_ALLOW_THREADS;
1024#if (DBVER >= 40)
1025 self->txn->abort(self->txn);
1026#else
1027 txn_abort(self->txn);
1028#endif
1029 MYDB_END_ALLOW_THREADS;
1030 PyErr_Warn(PyExc_RuntimeWarning,
1031 "DBTxn aborted in destructor. No prior commit() or abort().");
1032 }
1033#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001034
Neal Norwitz62a21122006-01-25 05:21:55 +00001035 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001036 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037}
1038
1039
1040static DBLockObject*
1041newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1042 db_lockmode_t lock_mode, int flags)
1043{
1044 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001045 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046 if (self == NULL)
1047 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001048#ifdef HAVE_WEAKREF
1049 self->in_weakreflist = NULL;
1050#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001051
1052 MYDB_BEGIN_ALLOW_THREADS;
1053#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001054 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1055 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056#else
1057 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1058#endif
1059 MYDB_END_ALLOW_THREADS;
1060 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001061 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062 self = NULL;
1063 }
1064
1065 return self;
1066}
1067
1068
1069static void
1070DBLock_dealloc(DBLockObject* self)
1071{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001072#ifdef HAVE_WEAKREF
1073 if (self->in_weakreflist != NULL) {
1074 PyObject_ClearWeakRefs((PyObject *) self);
1075 }
1076#endif
1077 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001078
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001079 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001080}
1081
1082
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001083#if (DBVER >= 43)
1084static DBSequenceObject*
1085newDBSequenceObject(DBObject* mydb, int flags)
1086{
1087 int err;
1088 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1089 if (self == NULL)
1090 return NULL;
1091 Py_INCREF(mydb);
1092 self->mydb = mydb;
1093#ifdef HAVE_WEAKREF
1094 self->in_weakreflist = NULL;
1095#endif
1096
1097
1098 MYDB_BEGIN_ALLOW_THREADS;
1099 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1100 MYDB_END_ALLOW_THREADS;
1101 if (makeDBError(err)) {
1102 Py_DECREF(self->mydb);
1103 PyObject_Del(self);
1104 self = NULL;
1105 }
1106
1107 return self;
1108}
1109
1110
1111static void
1112DBSequence_dealloc(DBSequenceObject* self)
1113{
1114#ifdef HAVE_WEAKREF
1115 if (self->in_weakreflist != NULL) {
1116 PyObject_ClearWeakRefs((PyObject *) self);
1117 }
1118#endif
1119
1120 Py_DECREF(self->mydb);
1121 PyObject_Del(self);
1122}
1123#endif
1124
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125/* --------------------------------------------------------------------- */
1126/* DB methods */
1127
1128static PyObject*
1129DB_append(DBObject* self, PyObject* args)
1130{
1131 PyObject* txnobj = NULL;
1132 PyObject* dataobj;
1133 db_recno_t recno;
1134 DBT key, data;
1135 DB_TXN *txn = NULL;
1136
Georg Brandl96a8c392006-05-29 21:04:52 +00001137 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001138 return NULL;
1139
1140 CHECK_DB_NOT_CLOSED(self);
1141
1142 /* make a dummy key out of a recno */
1143 recno = 0;
1144 CLEAR_DBT(key);
1145 key.data = &recno;
1146 key.size = sizeof(recno);
1147 key.ulen = key.size;
1148 key.flags = DB_DBT_USERMEM;
1149
1150 if (!make_dbt(dataobj, &data)) return NULL;
1151 if (!checkTxnObj(txnobj, &txn)) return NULL;
1152
1153 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1154 return NULL;
1155
1156 return PyInt_FromLong(recno);
1157}
1158
1159
1160#if (DBVER >= 33)
1161
1162static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001163_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1164 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001165{
1166 int retval = DB_DONOTINDEX;
1167 DBObject* secondaryDB = (DBObject*)db->app_private;
1168 PyObject* callback = secondaryDB->associateCallback;
1169 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001171 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172
1173
1174 if (callback != NULL) {
1175 MYDB_BEGIN_BLOCK_THREADS;
1176
Thomas Woutersb3153832006-03-08 01:47:19 +00001177 if (type == DB_RECNO || type == DB_QUEUE)
1178 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1179 priData->data, priData->size);
1180 else
1181 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1182 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001183 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001184 result = PyEval_CallObject(callback, args);
1185 }
1186 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001187 PyErr_Print();
1188 }
1189 else if (result == Py_None) {
1190 retval = DB_DONOTINDEX;
1191 }
1192 else if (PyInt_Check(result)) {
1193 retval = PyInt_AsLong(result);
1194 }
1195 else if (PyString_Check(result)) {
1196 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001197 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198
1199 CLEAR_DBT(*secKey);
1200#if PYTHON_API_VERSION <= 1007
1201 /* 1.5 compatibility */
1202 size = PyString_Size(result);
1203 data = PyString_AsString(result);
1204#else
1205 PyString_AsStringAndSize(result, &data, &size);
1206#endif
1207 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1208 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001209 if (secKey->data) {
1210 memcpy(secKey->data, data, size);
1211 secKey->size = size;
1212 retval = 0;
1213 }
1214 else {
1215 PyErr_SetString(PyExc_MemoryError,
1216 "malloc failed in _db_associateCallback");
1217 PyErr_Print();
1218 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219 }
1220 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001221 PyErr_SetString(
1222 PyExc_TypeError,
1223 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001224 PyErr_Print();
1225 }
1226
Thomas Woutersb3153832006-03-08 01:47:19 +00001227 Py_XDECREF(args);
1228 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001229
1230 MYDB_END_BLOCK_THREADS;
1231 }
1232 return retval;
1233}
1234
1235
1236static PyObject*
1237DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1238{
1239 int err, flags=0;
1240 DBObject* secondaryDB;
1241 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001242#if (DBVER >= 41)
1243 PyObject *txnobj = NULL;
1244 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001245 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001246 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001247#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001248 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001249#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001251#if (DBVER >= 41)
1252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1253 &secondaryDB, &callback, &flags,
1254 &txnobj)) {
1255#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001257 &secondaryDB, &callback, &flags)) {
1258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001259 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001260 }
1261
1262#if (DBVER >= 41)
1263 if (!checkTxnObj(txnobj, &txn)) return NULL;
1264#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265
1266 CHECK_DB_NOT_CLOSED(self);
1267 if (!DBObject_Check(secondaryDB)) {
1268 makeTypeError("DB", (PyObject*)secondaryDB);
1269 return NULL;
1270 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001271 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 if (callback == Py_None) {
1273 callback = NULL;
1274 }
1275 else if (!PyCallable_Check(callback)) {
1276 makeTypeError("Callable", callback);
1277 return NULL;
1278 }
1279
1280 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001281 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001282 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001283 secondaryDB->associateCallback = callback;
1284 secondaryDB->primaryDBType = _DB_get_type(self);
1285
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001286 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1287 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1288 * The global interepreter lock is not initialized until the first
1289 * thread is created using thread.start_new_thread() or fork() is
1290 * called. that would cause the ALLOW_THREADS here to segfault due
1291 * to a null pointer reference if no threads or child processes
1292 * have been created. This works around that and is a no-op if
1293 * threads have already been initialized.
1294 * (see pybsddb-users mailing list post on 2002-08-07)
1295 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001296#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001297 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001298#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001299 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001300#if (DBVER >= 41)
1301 err = self->db->associate(self->db,
1302 txn,
1303 secondaryDB->db,
1304 _db_associateCallback,
1305 flags);
1306#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001307 err = self->db->associate(self->db,
1308 secondaryDB->db,
1309 _db_associateCallback,
1310 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001311#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 MYDB_END_ALLOW_THREADS;
1313
1314 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001315 Py_XDECREF(secondaryDB->associateCallback);
1316 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001317 secondaryDB->primaryDBType = 0;
1318 }
1319
1320 RETURN_IF_ERR();
1321 RETURN_NONE();
1322}
1323
1324
1325#endif
1326
1327
1328static PyObject*
1329DB_close(DBObject* self, PyObject* args)
1330{
1331 int err, flags=0;
1332 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1333 return NULL;
1334 if (self->db != NULL) {
1335 if (self->myenvobj)
1336 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001337 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338 self->db = NULL;
1339 RETURN_IF_ERR();
1340 }
1341 RETURN_NONE();
1342}
1343
1344
1345#if (DBVER >= 32)
1346static PyObject*
1347_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1348{
1349 int err, flags=0, type;
1350 PyObject* txnobj = NULL;
1351 PyObject* retval = NULL;
1352 DBT key, data;
1353 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001354 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001355
1356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1357 &txnobj, &flags))
1358 return NULL;
1359
1360 CHECK_DB_NOT_CLOSED(self);
1361 type = _DB_get_type(self);
1362 if (type == -1)
1363 return NULL;
1364 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001365 PyErr_SetString(PyExc_TypeError,
1366 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001367 return NULL;
1368 }
1369 if (!checkTxnObj(txnobj, &txn))
1370 return NULL;
1371
1372 CLEAR_DBT(key);
1373 CLEAR_DBT(data);
1374 if (CHECK_DBFLAG(self, DB_THREAD)) {
1375 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1376 data.flags = DB_DBT_MALLOC;
1377 key.flags = DB_DBT_MALLOC;
1378 }
1379
1380 MYDB_BEGIN_ALLOW_THREADS;
1381 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1382 MYDB_END_ALLOW_THREADS;
1383
Gregory P. Smithe9477062005-06-04 06:46:59 +00001384 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1385 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386 err = 0;
1387 Py_INCREF(Py_None);
1388 retval = Py_None;
1389 }
1390 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001391 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1392 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393 FREE_DBT(key);
1394 FREE_DBT(data);
1395 }
1396
1397 RETURN_IF_ERR();
1398 return retval;
1399}
1400
1401static PyObject*
1402DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1403{
1404 return _DB_consume(self, args, kwargs, DB_CONSUME);
1405}
1406
1407static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001408DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1409 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410{
1411 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1412}
1413#endif
1414
1415
1416
1417static PyObject*
1418DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1419{
1420 int err, flags=0;
1421 DBC* dbc;
1422 PyObject* txnobj = NULL;
1423 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001424 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425
1426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1427 &txnobj, &flags))
1428 return NULL;
1429 CHECK_DB_NOT_CLOSED(self);
1430 if (!checkTxnObj(txnobj, &txn))
1431 return NULL;
1432
1433 MYDB_BEGIN_ALLOW_THREADS;
1434 err = self->db->cursor(self->db, txn, &dbc, flags);
1435 MYDB_END_ALLOW_THREADS;
1436 RETURN_IF_ERR();
1437 return (PyObject*) newDBCursorObject(dbc, self);
1438}
1439
1440
1441static PyObject*
1442DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1443{
1444 PyObject* txnobj = NULL;
1445 int flags = 0;
1446 PyObject* keyobj;
1447 DBT key;
1448 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001449 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450
1451 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1452 &keyobj, &txnobj, &flags))
1453 return NULL;
1454 CHECK_DB_NOT_CLOSED(self);
1455 if (!make_key_dbt(self, keyobj, &key, NULL))
1456 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001457 if (!checkTxnObj(txnobj, &txn)) {
1458 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001459 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001460 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001462 if (-1 == _DB_delete(self, txn, &key, 0)) {
1463 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001465 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466
1467 FREE_DBT(key);
1468 RETURN_NONE();
1469}
1470
1471
1472static PyObject*
1473DB_fd(DBObject* self, PyObject* args)
1474{
1475 int err, the_fd;
1476
1477 if (!PyArg_ParseTuple(args,":fd"))
1478 return NULL;
1479 CHECK_DB_NOT_CLOSED(self);
1480
1481 MYDB_BEGIN_ALLOW_THREADS;
1482 err = self->db->fd(self->db, &the_fd);
1483 MYDB_END_ALLOW_THREADS;
1484 RETURN_IF_ERR();
1485 return PyInt_FromLong(the_fd);
1486}
1487
1488
1489static PyObject*
1490DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1491{
1492 int err, flags=0;
1493 PyObject* txnobj = NULL;
1494 PyObject* keyobj;
1495 PyObject* dfltobj = NULL;
1496 PyObject* retval = NULL;
1497 int dlen = -1;
1498 int doff = -1;
1499 DBT key, data;
1500 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001501 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001502 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503
1504 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001505 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1506 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001507 return NULL;
1508
1509 CHECK_DB_NOT_CLOSED(self);
1510 if (!make_key_dbt(self, keyobj, &key, &flags))
1511 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001512 if (!checkTxnObj(txnobj, &txn)) {
1513 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001514 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001515 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001516
1517 CLEAR_DBT(data);
1518 if (CHECK_DBFLAG(self, DB_THREAD)) {
1519 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1520 data.flags = DB_DBT_MALLOC;
1521 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001522 if (!add_partial_dbt(&data, dlen, doff)) {
1523 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001525 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001526
1527 MYDB_BEGIN_ALLOW_THREADS;
1528 err = self->db->get(self->db, txn, &key, &data, flags);
1529 MYDB_END_ALLOW_THREADS;
1530
Gregory P. Smithe9477062005-06-04 06:46:59 +00001531 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532 err = 0;
1533 Py_INCREF(dfltobj);
1534 retval = dfltobj;
1535 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001536 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1537 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001538 err = 0;
1539 Py_INCREF(Py_None);
1540 retval = Py_None;
1541 }
1542 else if (!err) {
1543 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001544 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1545 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001546 else /* return just the data */
1547 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001548 FREE_DBT(data);
1549 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001550 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001551
1552 RETURN_IF_ERR();
1553 return retval;
1554}
1555
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001556#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001557static PyObject*
1558DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1559{
1560 int err, flags=0;
1561 PyObject* txnobj = NULL;
1562 PyObject* keyobj;
1563 PyObject* dfltobj = NULL;
1564 PyObject* retval = NULL;
1565 int dlen = -1;
1566 int doff = -1;
1567 DBT key, pkey, data;
1568 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001569 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001570 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001571
1572 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1573 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1574 &doff))
1575 return NULL;
1576
1577 CHECK_DB_NOT_CLOSED(self);
1578 if (!make_key_dbt(self, keyobj, &key, &flags))
1579 return NULL;
1580 if (!checkTxnObj(txnobj, &txn)) {
1581 FREE_DBT(key);
1582 return NULL;
1583 }
1584
1585 CLEAR_DBT(data);
1586 if (CHECK_DBFLAG(self, DB_THREAD)) {
1587 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1588 data.flags = DB_DBT_MALLOC;
1589 }
1590 if (!add_partial_dbt(&data, dlen, doff)) {
1591 FREE_DBT(key);
1592 return NULL;
1593 }
1594
1595 CLEAR_DBT(pkey);
1596 pkey.flags = DB_DBT_MALLOC;
1597
1598 MYDB_BEGIN_ALLOW_THREADS;
1599 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1600 MYDB_END_ALLOW_THREADS;
1601
Gregory P. Smithe9477062005-06-04 06:46:59 +00001602 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001603 err = 0;
1604 Py_INCREF(dfltobj);
1605 retval = dfltobj;
1606 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001607 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1608 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001609 err = 0;
1610 Py_INCREF(Py_None);
1611 retval = Py_None;
1612 }
1613 else if (!err) {
1614 PyObject *pkeyObj;
1615 PyObject *dataObj;
1616 dataObj = PyString_FromStringAndSize(data.data, data.size);
1617
1618 if (self->primaryDBType == DB_RECNO ||
1619 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001620 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001621 else
1622 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1623
1624 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1625 {
1626 PyObject *keyObj;
1627 int type = _DB_get_type(self);
1628 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001629 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001630 else
1631 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001632#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001633 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001634#else
1635 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1636#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001637 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001638 }
1639 else /* return just the pkey and data */
1640 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001641#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001642 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001643#else
1644 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1645#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001646 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001647 Py_DECREF(dataObj);
1648 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001649 FREE_DBT(pkey);
1650 FREE_DBT(data);
1651 }
1652 FREE_DBT(key);
1653
1654 RETURN_IF_ERR();
1655 return retval;
1656}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001657#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001658
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659
1660/* Return size of entry */
1661static PyObject*
1662DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1663{
1664 int err, flags=0;
1665 PyObject* txnobj = NULL;
1666 PyObject* keyobj;
1667 PyObject* retval = NULL;
1668 DBT key, data;
1669 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001670 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001671
1672 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1673 &keyobj, &txnobj))
1674 return NULL;
1675 CHECK_DB_NOT_CLOSED(self);
1676 if (!make_key_dbt(self, keyobj, &key, &flags))
1677 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001678 if (!checkTxnObj(txnobj, &txn)) {
1679 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001680 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001681 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001682 CLEAR_DBT(data);
1683
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001684 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1685 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 data.flags = DB_DBT_USERMEM;
1687 data.ulen = 0;
1688 MYDB_BEGIN_ALLOW_THREADS;
1689 err = self->db->get(self->db, txn, &key, &data, flags);
1690 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001691 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692 retval = PyInt_FromLong((long)data.size);
1693 err = 0;
1694 }
1695
1696 FREE_DBT(key);
1697 FREE_DBT(data);
1698 RETURN_IF_ERR();
1699 return retval;
1700}
1701
1702
1703static PyObject*
1704DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1705{
1706 int err, flags=0;
1707 PyObject* txnobj = NULL;
1708 PyObject* keyobj;
1709 PyObject* dataobj;
1710 PyObject* retval = NULL;
1711 DBT key, data;
Neal Norwitzdf738022007-05-20 02:14:48 +00001712 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001714 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715
1716
1717 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1718 &keyobj, &dataobj, &txnobj, &flags))
1719 return NULL;
1720
1721 CHECK_DB_NOT_CLOSED(self);
1722 if (!make_key_dbt(self, keyobj, &key, NULL))
1723 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001724 if ( !make_dbt(dataobj, &data) ||
1725 !checkTxnObj(txnobj, &txn) )
1726 {
1727 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001729 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001730
1731 flags |= DB_GET_BOTH;
Neal Norwitzdf738022007-05-20 02:14:48 +00001732 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001733
1734 if (CHECK_DBFLAG(self, DB_THREAD)) {
1735 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitzdf738022007-05-20 02:14:48 +00001736 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001737 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001738 }
1739
1740 MYDB_BEGIN_ALLOW_THREADS;
1741 err = self->db->get(self->db, txn, &key, &data, flags);
1742 MYDB_END_ALLOW_THREADS;
1743
Gregory P. Smithe9477062005-06-04 06:46:59 +00001744 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1745 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746 err = 0;
1747 Py_INCREF(Py_None);
1748 retval = Py_None;
1749 }
1750 else if (!err) {
Neal Norwitzdf738022007-05-20 02:14:48 +00001751 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001752 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitzdf738022007-05-20 02:14:48 +00001753
1754 /* Even though the flags require DB_DBT_MALLOC, data is not always
1755 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1756 if (data.data != orig_data)
1757 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001758 }
1759
1760 FREE_DBT(key);
1761 RETURN_IF_ERR();
1762 return retval;
1763}
1764
1765
1766static PyObject*
1767DB_get_byteswapped(DBObject* self, PyObject* args)
1768{
1769#if (DBVER >= 33)
1770 int err = 0;
1771#endif
1772 int retval = -1;
1773
1774 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1775 return NULL;
1776 CHECK_DB_NOT_CLOSED(self);
1777
1778#if (DBVER >= 33)
1779 MYDB_BEGIN_ALLOW_THREADS;
1780 err = self->db->get_byteswapped(self->db, &retval);
1781 MYDB_END_ALLOW_THREADS;
1782 RETURN_IF_ERR();
1783#else
1784 MYDB_BEGIN_ALLOW_THREADS;
1785 retval = self->db->get_byteswapped(self->db);
1786 MYDB_END_ALLOW_THREADS;
1787#endif
1788 return PyInt_FromLong(retval);
1789}
1790
1791
1792static PyObject*
1793DB_get_type(DBObject* self, PyObject* args)
1794{
1795 int type;
1796
1797 if (!PyArg_ParseTuple(args,":get_type"))
1798 return NULL;
1799 CHECK_DB_NOT_CLOSED(self);
1800
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802 if (type == -1)
1803 return NULL;
1804 return PyInt_FromLong(type);
1805}
1806
1807
1808static PyObject*
1809DB_join(DBObject* self, PyObject* args)
1810{
1811 int err, flags=0;
1812 int length, x;
1813 PyObject* cursorsObj;
1814 DBC** cursors;
1815 DBC* dbc;
1816
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001817 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1818 return NULL;
1819
1820 CHECK_DB_NOT_CLOSED(self);
1821
1822 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001823 PyErr_SetString(PyExc_TypeError,
1824 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 return NULL;
1826 }
1827
1828 length = PyObject_Length(cursorsObj);
1829 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001830 if (!cursors) {
1831 PyErr_NoMemory();
1832 return NULL;
1833 }
1834
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001835 cursors[length] = NULL;
1836 for (x=0; x<length; x++) {
1837 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001838 if (item == NULL) {
1839 free(cursors);
1840 return NULL;
1841 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001843 PyErr_SetString(PyExc_TypeError,
1844 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 free(cursors);
1846 return NULL;
1847 }
1848 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001849 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850 }
1851
1852 MYDB_BEGIN_ALLOW_THREADS;
1853 err = self->db->join(self->db, cursors, &dbc, flags);
1854 MYDB_END_ALLOW_THREADS;
1855 free(cursors);
1856 RETURN_IF_ERR();
1857
Gregory P. Smith7441e652003-11-03 21:35:31 +00001858 /* FIXME: this is a buggy interface. The returned cursor
1859 contains internal references to the passed in cursors
1860 but does not hold python references to them or prevent
1861 them from being closed prematurely. This can cause
1862 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863 return (PyObject*) newDBCursorObject(dbc, self);
1864}
1865
1866
1867static PyObject*
1868DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1869{
1870 int err, flags=0;
1871 PyObject* txnobj = NULL;
1872 PyObject* keyobj;
1873 DBT key;
1874 DB_TXN *txn = NULL;
1875 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001876 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001877
1878 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1879 &keyobj, &txnobj, &flags))
1880 return NULL;
1881 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001882 if (!make_dbt(keyobj, &key))
1883 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001884 return NULL;
1885 if (!checkTxnObj(txnobj, &txn))
1886 return NULL;
1887
1888 MYDB_BEGIN_ALLOW_THREADS;
1889 err = self->db->key_range(self->db, txn, &key, &range, flags);
1890 MYDB_END_ALLOW_THREADS;
1891
1892 RETURN_IF_ERR();
1893 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1894}
1895
1896
1897static PyObject*
1898DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1899{
1900 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1901 char* filename = NULL;
1902 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001903#if (DBVER >= 41)
1904 PyObject *txnobj = NULL;
1905 DB_TXN *txn = NULL;
1906 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001907 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001908 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1909 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001910 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001911 "filename", "dbtype", "flags", "mode", "txn", NULL};
1912#else
1913 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001914 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001915 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1916 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001917 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918 "filename", "dbtype", "flags", "mode", NULL};
1919#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001920
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001921#if (DBVER >= 41)
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1923 &filename, &dbname, &type, &flags, &mode,
1924 &txnobj))
1925#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001927 &filename, &dbname, &type, &flags,
1928 &mode))
1929#endif
1930 {
1931 PyErr_Clear();
1932 type = DB_UNKNOWN; flags = 0; mode = 0660;
1933 filename = NULL; dbname = NULL;
1934#if (DBVER >= 41)
1935 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1936 kwnames_basic,
1937 &filename, &type, &flags, &mode,
1938 &txnobj))
1939 return NULL;
1940#else
1941 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1942 kwnames_basic,
1943 &filename, &type, &flags, &mode))
1944 return NULL;
1945#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946 }
1947
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001948#if (DBVER >= 41)
1949 if (!checkTxnObj(txnobj, &txn)) return NULL;
1950#endif
1951
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001953 PyObject *t = Py_BuildValue("(is)", 0,
1954 "Cannot call open() twice for DB object");
1955 PyErr_SetObject(DBError, t);
1956 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 return NULL;
1958 }
1959
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001960#if 0 && (DBVER >= 41)
1961 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1962 && (self->myenvobj->flags & DB_INIT_TXN))
1963 {
1964 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1965 * explicitly passed) but we are in a transaction ready environment:
1966 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1967 * to work on BerkeleyDB 4.1 without needing to modify their
1968 * DBEnv or DB open calls.
1969 * TODO make this behaviour of the library configurable.
1970 */
1971 flags |= DB_AUTO_COMMIT;
1972 }
1973#endif
1974
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001975 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001976#if (DBVER >= 41)
1977 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1978#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001980#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001981 MYDB_END_ALLOW_THREADS;
1982 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001983 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984 self->db = NULL;
1985 return NULL;
1986 }
1987
1988 self->flags = flags;
1989 RETURN_NONE();
1990}
1991
1992
1993static PyObject*
1994DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1995{
1996 int flags=0;
1997 PyObject* txnobj = NULL;
1998 int dlen = -1;
1999 int doff = -1;
2000 PyObject* keyobj, *dataobj, *retval;
2001 DBT key, data;
2002 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002003 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002004 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002005
2006 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2007 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2008 return NULL;
2009
2010 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002011 if (!make_key_dbt(self, keyobj, &key, NULL))
2012 return NULL;
2013 if ( !make_dbt(dataobj, &data) ||
2014 !add_partial_dbt(&data, dlen, doff) ||
2015 !checkTxnObj(txnobj, &txn) )
2016 {
2017 FREE_DBT(key);
2018 return NULL;
2019 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002020
2021 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2022 FREE_DBT(key);
2023 return NULL;
2024 }
2025
2026 if (flags & DB_APPEND)
2027 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2028 else {
2029 retval = Py_None;
2030 Py_INCREF(retval);
2031 }
2032 FREE_DBT(key);
2033 return retval;
2034}
2035
2036
2037
2038static PyObject*
2039DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2040{
2041 char* filename;
2042 char* database = NULL;
2043 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002044 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002045
2046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2047 &filename, &database, &flags))
2048 return NULL;
2049 CHECK_DB_NOT_CLOSED(self);
2050
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002052 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 RETURN_IF_ERR();
2054 RETURN_NONE();
2055}
2056
2057
2058
2059static PyObject*
2060DB_rename(DBObject* self, PyObject* args)
2061{
2062 char* filename;
2063 char* database;
2064 char* newname;
2065 int err, flags=0;
2066
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002067 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2068 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002069 return NULL;
2070 CHECK_DB_NOT_CLOSED(self);
2071
2072 MYDB_BEGIN_ALLOW_THREADS;
2073 err = self->db->rename(self->db, filename, database, newname, flags);
2074 MYDB_END_ALLOW_THREADS;
2075 RETURN_IF_ERR();
2076 RETURN_NONE();
2077}
2078
2079
2080static PyObject*
2081DB_set_bt_minkey(DBObject* self, PyObject* args)
2082{
2083 int err, minkey;
2084
2085 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2086 return NULL;
2087 CHECK_DB_NOT_CLOSED(self);
2088
2089 MYDB_BEGIN_ALLOW_THREADS;
2090 err = self->db->set_bt_minkey(self->db, minkey);
2091 MYDB_END_ALLOW_THREADS;
2092 RETURN_IF_ERR();
2093 RETURN_NONE();
2094}
2095
Neal Norwitz84562352005-10-20 04:30:15 +00002096#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002097static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002098_default_cmp(const DBT *leftKey,
2099 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100{
2101 int res;
2102 int lsize = leftKey->size, rsize = rightKey->size;
2103
Georg Brandlef1701f2006-03-07 14:57:48 +00002104 res = memcmp(leftKey->data, rightKey->data,
2105 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002106
2107 if (res == 0) {
2108 if (lsize < rsize) {
2109 res = -1;
2110 }
2111 else if (lsize > rsize) {
2112 res = 1;
2113 }
2114 }
2115 return res;
2116}
2117
2118static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002119_db_compareCallback(DB* db,
2120 const DBT *leftKey,
2121 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122{
2123 int res = 0;
2124 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002125 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002127
2128 if (self == NULL || self->btCompareCallback == NULL) {
2129 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 PyErr_SetString(PyExc_TypeError,
2131 (self == 0
2132 ? "DB_bt_compare db is NULL."
2133 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002135 PyErr_Print();
2136 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002138 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002139 MYDB_BEGIN_BLOCK_THREADS;
2140
Thomas Woutersb3153832006-03-08 01:47:19 +00002141 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2142 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002143 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002144 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002146 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002147 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 PyErr_Print();
2151 res = _default_cmp(leftKey, rightKey);
2152 } else if (PyInt_Check(result)) {
2153 res = PyInt_AsLong(result);
2154 } else {
2155 PyErr_SetString(PyExc_TypeError,
2156 "DB_bt_compare callback MUST return an int.");
2157 /* we're in a callback within the DB code, we can't raise */
2158 PyErr_Print();
2159 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160 }
2161
Thomas Woutersb3153832006-03-08 01:47:19 +00002162 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164
2165 MYDB_END_BLOCK_THREADS;
2166 }
2167 return res;
2168}
2169
2170static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002171DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002172{
2173 int err;
2174 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002175 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002176
Georg Brandlef1701f2006-03-07 14:57:48 +00002177 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178 return NULL;
2179
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 if (!PyCallable_Check(comparator)) {
2183 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184 return NULL;
2185 }
2186
2187 /*
2188 * Perform a test call of the comparator function with two empty
2189 * string objects here. verify that it returns an int (0).
2190 * err if not.
2191 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002192 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002193 result = PyEval_CallObject(comparator, tuple);
2194 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002195 if (result == NULL)
2196 return NULL;
2197 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002198 PyErr_SetString(PyExc_TypeError,
2199 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002201 } else if (PyInt_AsLong(result) != 0) {
2202 PyErr_SetString(PyExc_TypeError,
2203 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204 return NULL;
2205 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002206 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
2208 /* We don't accept multiple set_bt_compare operations, in order to
2209 * simplify the code. This would have no real use, as one cannot
2210 * change the function once the db is opened anyway */
2211 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002212 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213 return NULL;
2214 }
2215
Georg Brandlef1701f2006-03-07 14:57:48 +00002216 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002217 self->btCompareCallback = comparator;
2218
2219 /* This is to workaround a problem with un-initialized threads (see
2220 comment in DB_associate) */
2221#ifdef WITH_THREAD
2222 PyEval_InitThreads();
2223#endif
2224
Thomas Woutersb3153832006-03-08 01:47:19 +00002225 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002226
2227 if (err) {
2228 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002229 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002230 self->btCompareCallback = NULL;
2231 }
2232
Georg Brandlef1701f2006-03-07 14:57:48 +00002233 RETURN_IF_ERR();
2234 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002235}
Neal Norwitz84562352005-10-20 04:30:15 +00002236#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002237
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002238
2239static PyObject*
2240DB_set_cachesize(DBObject* self, PyObject* args)
2241{
2242 int err;
2243 int gbytes = 0, bytes = 0, ncache = 0;
2244
2245 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2246 &gbytes,&bytes,&ncache))
2247 return NULL;
2248 CHECK_DB_NOT_CLOSED(self);
2249
2250 MYDB_BEGIN_ALLOW_THREADS;
2251 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2252 MYDB_END_ALLOW_THREADS;
2253 RETURN_IF_ERR();
2254 RETURN_NONE();
2255}
2256
2257
2258static PyObject*
2259DB_set_flags(DBObject* self, PyObject* args)
2260{
2261 int err, flags;
2262
2263 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2266
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_flags(self->db, flags);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271
2272 self->setflags |= flags;
2273 RETURN_NONE();
2274}
2275
2276
2277static PyObject*
2278DB_set_h_ffactor(DBObject* self, PyObject* args)
2279{
2280 int err, ffactor;
2281
2282 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2283 return NULL;
2284 CHECK_DB_NOT_CLOSED(self);
2285
2286 MYDB_BEGIN_ALLOW_THREADS;
2287 err = self->db->set_h_ffactor(self->db, ffactor);
2288 MYDB_END_ALLOW_THREADS;
2289 RETURN_IF_ERR();
2290 RETURN_NONE();
2291}
2292
2293
2294static PyObject*
2295DB_set_h_nelem(DBObject* self, PyObject* args)
2296{
2297 int err, nelem;
2298
2299 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2300 return NULL;
2301 CHECK_DB_NOT_CLOSED(self);
2302
2303 MYDB_BEGIN_ALLOW_THREADS;
2304 err = self->db->set_h_nelem(self->db, nelem);
2305 MYDB_END_ALLOW_THREADS;
2306 RETURN_IF_ERR();
2307 RETURN_NONE();
2308}
2309
2310
2311static PyObject*
2312DB_set_lorder(DBObject* self, PyObject* args)
2313{
2314 int err, lorder;
2315
2316 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319
2320 MYDB_BEGIN_ALLOW_THREADS;
2321 err = self->db->set_lorder(self->db, lorder);
2322 MYDB_END_ALLOW_THREADS;
2323 RETURN_IF_ERR();
2324 RETURN_NONE();
2325}
2326
2327
2328static PyObject*
2329DB_set_pagesize(DBObject* self, PyObject* args)
2330{
2331 int err, pagesize;
2332
2333 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2334 return NULL;
2335 CHECK_DB_NOT_CLOSED(self);
2336
2337 MYDB_BEGIN_ALLOW_THREADS;
2338 err = self->db->set_pagesize(self->db, pagesize);
2339 MYDB_END_ALLOW_THREADS;
2340 RETURN_IF_ERR();
2341 RETURN_NONE();
2342}
2343
2344
2345static PyObject*
2346DB_set_re_delim(DBObject* self, PyObject* args)
2347{
2348 int err;
2349 char delim;
2350
2351 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2352 PyErr_Clear();
2353 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2354 return NULL;
2355 }
2356
2357 CHECK_DB_NOT_CLOSED(self);
2358
2359 MYDB_BEGIN_ALLOW_THREADS;
2360 err = self->db->set_re_delim(self->db, delim);
2361 MYDB_END_ALLOW_THREADS;
2362 RETURN_IF_ERR();
2363 RETURN_NONE();
2364}
2365
2366static PyObject*
2367DB_set_re_len(DBObject* self, PyObject* args)
2368{
2369 int err, len;
2370
2371 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2372 return NULL;
2373 CHECK_DB_NOT_CLOSED(self);
2374
2375 MYDB_BEGIN_ALLOW_THREADS;
2376 err = self->db->set_re_len(self->db, len);
2377 MYDB_END_ALLOW_THREADS;
2378 RETURN_IF_ERR();
2379 RETURN_NONE();
2380}
2381
2382
2383static PyObject*
2384DB_set_re_pad(DBObject* self, PyObject* args)
2385{
2386 int err;
2387 char pad;
2388
2389 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2390 PyErr_Clear();
2391 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2392 return NULL;
2393 }
2394 CHECK_DB_NOT_CLOSED(self);
2395
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_re_pad(self->db, pad);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2400 RETURN_NONE();
2401}
2402
2403
2404static PyObject*
2405DB_set_re_source(DBObject* self, PyObject* args)
2406{
2407 int err;
2408 char *re_source;
2409
2410 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2413
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_re_source(self->db, re_source);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2419}
2420
2421
2422#if (DBVER >= 32)
2423static PyObject*
2424DB_set_q_extentsize(DBObject* self, PyObject* args)
2425{
2426 int err;
2427 int extentsize;
2428
2429 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2430 return NULL;
2431 CHECK_DB_NOT_CLOSED(self);
2432
2433 MYDB_BEGIN_ALLOW_THREADS;
2434 err = self->db->set_q_extentsize(self->db, extentsize);
2435 MYDB_END_ALLOW_THREADS;
2436 RETURN_IF_ERR();
2437 RETURN_NONE();
2438}
2439#endif
2440
2441static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002442DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002443{
2444 int err, flags = 0, type;
2445 void* sp;
2446 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002447#if (DBVER >= 43)
2448 PyObject* txnobj = NULL;
2449 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002450 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002452 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002453#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002454
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002455#if (DBVER >= 43)
2456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2457 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002458 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002459 if (!checkTxnObj(txnobj, &txn))
2460 return NULL;
2461#else
2462 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2463 return NULL;
2464#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002465 CHECK_DB_NOT_CLOSED(self);
2466
2467 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002468#if (DBVER >= 43)
2469 err = self->db->stat(self->db, txn, &sp, flags);
2470#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 err = self->db->stat(self->db, &sp, flags);
2472#else
2473 err = self->db->stat(self->db, &sp, NULL, flags);
2474#endif
2475 MYDB_END_ALLOW_THREADS;
2476 RETURN_IF_ERR();
2477
2478 self->haveStat = 1;
2479
2480 /* Turn the stat structure into a dictionary */
2481 type = _DB_get_type(self);
2482 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2483 free(sp);
2484 return NULL;
2485 }
2486
2487#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2488#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2489#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2490
2491 switch (type) {
2492 case DB_HASH:
2493 MAKE_HASH_ENTRY(magic);
2494 MAKE_HASH_ENTRY(version);
2495 MAKE_HASH_ENTRY(nkeys);
2496 MAKE_HASH_ENTRY(ndata);
2497 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002498#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002499 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002500#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002501 MAKE_HASH_ENTRY(ffactor);
2502 MAKE_HASH_ENTRY(buckets);
2503 MAKE_HASH_ENTRY(free);
2504 MAKE_HASH_ENTRY(bfree);
2505 MAKE_HASH_ENTRY(bigpages);
2506 MAKE_HASH_ENTRY(big_bfree);
2507 MAKE_HASH_ENTRY(overflows);
2508 MAKE_HASH_ENTRY(ovfl_free);
2509 MAKE_HASH_ENTRY(dup);
2510 MAKE_HASH_ENTRY(dup_free);
2511 break;
2512
2513 case DB_BTREE:
2514 case DB_RECNO:
2515 MAKE_BT_ENTRY(magic);
2516 MAKE_BT_ENTRY(version);
2517 MAKE_BT_ENTRY(nkeys);
2518 MAKE_BT_ENTRY(ndata);
2519 MAKE_BT_ENTRY(pagesize);
2520 MAKE_BT_ENTRY(minkey);
2521 MAKE_BT_ENTRY(re_len);
2522 MAKE_BT_ENTRY(re_pad);
2523 MAKE_BT_ENTRY(levels);
2524 MAKE_BT_ENTRY(int_pg);
2525 MAKE_BT_ENTRY(leaf_pg);
2526 MAKE_BT_ENTRY(dup_pg);
2527 MAKE_BT_ENTRY(over_pg);
2528 MAKE_BT_ENTRY(free);
2529 MAKE_BT_ENTRY(int_pgfree);
2530 MAKE_BT_ENTRY(leaf_pgfree);
2531 MAKE_BT_ENTRY(dup_pgfree);
2532 MAKE_BT_ENTRY(over_pgfree);
2533 break;
2534
2535 case DB_QUEUE:
2536 MAKE_QUEUE_ENTRY(magic);
2537 MAKE_QUEUE_ENTRY(version);
2538 MAKE_QUEUE_ENTRY(nkeys);
2539 MAKE_QUEUE_ENTRY(ndata);
2540 MAKE_QUEUE_ENTRY(pagesize);
2541 MAKE_QUEUE_ENTRY(pages);
2542 MAKE_QUEUE_ENTRY(re_len);
2543 MAKE_QUEUE_ENTRY(re_pad);
2544 MAKE_QUEUE_ENTRY(pgfree);
2545#if (DBVER == 31)
2546 MAKE_QUEUE_ENTRY(start);
2547#endif
2548 MAKE_QUEUE_ENTRY(first_recno);
2549 MAKE_QUEUE_ENTRY(cur_recno);
2550 break;
2551
2552 default:
2553 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2554 Py_DECREF(d);
2555 d = NULL;
2556 }
2557
2558#undef MAKE_HASH_ENTRY
2559#undef MAKE_BT_ENTRY
2560#undef MAKE_QUEUE_ENTRY
2561
2562 free(sp);
2563 return d;
2564}
2565
2566static PyObject*
2567DB_sync(DBObject* self, PyObject* args)
2568{
2569 int err;
2570 int flags = 0;
2571
2572 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2573 return NULL;
2574 CHECK_DB_NOT_CLOSED(self);
2575
2576 MYDB_BEGIN_ALLOW_THREADS;
2577 err = self->db->sync(self->db, flags);
2578 MYDB_END_ALLOW_THREADS;
2579 RETURN_IF_ERR();
2580 RETURN_NONE();
2581}
2582
2583
2584#if (DBVER >= 33)
2585static PyObject*
2586DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2587{
2588 int err, flags=0;
2589 u_int32_t count=0;
2590 PyObject* txnobj = NULL;
2591 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002592 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002593
2594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2595 &txnobj, &flags))
2596 return NULL;
2597 CHECK_DB_NOT_CLOSED(self);
2598 if (!checkTxnObj(txnobj, &txn))
2599 return NULL;
2600
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->truncate(self->db, txn, &count, flags);
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605 return PyInt_FromLong(count);
2606}
2607#endif
2608
2609
2610static PyObject*
2611DB_upgrade(DBObject* self, PyObject* args)
2612{
2613 int err, flags=0;
2614 char *filename;
2615
2616 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2617 return NULL;
2618 CHECK_DB_NOT_CLOSED(self);
2619
2620 MYDB_BEGIN_ALLOW_THREADS;
2621 err = self->db->upgrade(self->db, filename, flags);
2622 MYDB_END_ALLOW_THREADS;
2623 RETURN_IF_ERR();
2624 RETURN_NONE();
2625}
2626
2627
2628static PyObject*
2629DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2630{
2631 int err, flags=0;
2632 char* fileName;
2633 char* dbName=NULL;
2634 char* outFileName=NULL;
2635 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002636 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002637 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002638
2639 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2640 &fileName, &dbName, &outFileName, &flags))
2641 return NULL;
2642
2643 CHECK_DB_NOT_CLOSED(self);
2644 if (outFileName)
2645 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002646 /* XXX(nnorwitz): it should probably be an exception if outFile
2647 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002648
2649 MYDB_BEGIN_ALLOW_THREADS;
2650 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2651 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002652 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002653 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002654
2655 /* DB.verify acts as a DB handle destructor (like close); this was
2656 * documented in BerkeleyDB 4.2 but had the undocumented effect
2657 * of not being safe in prior versions while still requiring an explicit
2658 * DB.close call afterwards. Lets call close for the user to emulate
2659 * the safe 4.2 behaviour. */
2660#if (DBVER <= 41)
2661 self->db->close(self->db, 0);
2662#endif
2663 self->db = NULL;
2664
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002665 RETURN_IF_ERR();
2666 RETURN_NONE();
2667}
2668
2669
2670static PyObject*
2671DB_set_get_returns_none(DBObject* self, PyObject* args)
2672{
2673 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002674 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002675
2676 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2677 return NULL;
2678 CHECK_DB_NOT_CLOSED(self);
2679
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002680 if (self->moduleFlags.getReturnsNone)
2681 ++oldValue;
2682 if (self->moduleFlags.cursorSetReturnsNone)
2683 ++oldValue;
2684 self->moduleFlags.getReturnsNone = (flags >= 1);
2685 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686 return PyInt_FromLong(oldValue);
2687}
2688
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002689#if (DBVER >= 41)
2690static PyObject*
2691DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2692{
2693 int err;
2694 u_int32_t flags=0;
2695 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002696 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002697
2698 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2699 &passwd, &flags)) {
2700 return NULL;
2701 }
2702
2703 MYDB_BEGIN_ALLOW_THREADS;
2704 err = self->db->set_encrypt(self->db, passwd, flags);
2705 MYDB_END_ALLOW_THREADS;
2706
2707 RETURN_IF_ERR();
2708 RETURN_NONE();
2709}
2710#endif /* DBVER >= 41 */
2711
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002712
2713/*-------------------------------------------------------------- */
2714/* Mapping and Dictionary-like access routines */
2715
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002716Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717{
2718 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002719 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720 int flags = 0;
2721 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002722 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723
2724 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002725 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2726 PyErr_SetObject(DBError, t);
2727 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002728 return -1;
2729 }
2730
2731 if (self->haveStat) { /* Has the stat function been called recently? If
2732 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002733 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 }
2735
2736 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002737redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002738#if (DBVER >= 43)
2739 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2740#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002741 err = self->db->stat(self->db, &sp, flags);
2742#else
2743 err = self->db->stat(self->db, &sp, NULL, flags);
2744#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002745
2746 /* All the stat structures have matching fields upto the ndata field,
2747 so we can use any of them for the type cast */
2748 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2749
2750 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2751 * redo a full stat to make sure.
2752 * Fixes SF python bug 1493322, pybsddb bug 1184012
2753 */
2754 if (size == 0 && (flags & DB_FAST_STAT)) {
2755 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002756 if (!err)
2757 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002758 goto redo_stat_for_length;
2759 }
2760
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002761 MYDB_END_ALLOW_THREADS;
2762
2763 if (err)
2764 return -1;
2765
2766 self->haveStat = 1;
2767
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002768 free(sp);
2769 return size;
2770}
2771
2772
2773PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2774{
2775 int err;
2776 PyObject* retval;
2777 DBT key;
2778 DBT data;
2779
2780 CHECK_DB_NOT_CLOSED(self);
2781 if (!make_key_dbt(self, keyobj, &key, NULL))
2782 return NULL;
2783
2784 CLEAR_DBT(data);
2785 if (CHECK_DBFLAG(self, DB_THREAD)) {
2786 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2787 data.flags = DB_DBT_MALLOC;
2788 }
2789 MYDB_BEGIN_ALLOW_THREADS;
2790 err = self->db->get(self->db, NULL, &key, &data, 0);
2791 MYDB_END_ALLOW_THREADS;
2792 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2793 PyErr_SetObject(PyExc_KeyError, keyobj);
2794 retval = NULL;
2795 }
2796 else if (makeDBError(err)) {
2797 retval = NULL;
2798 }
2799 else {
2800 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2801 FREE_DBT(data);
2802 }
2803
2804 FREE_DBT(key);
2805 return retval;
2806}
2807
2808
2809static int
2810DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2811{
2812 DBT key, data;
2813 int retval;
2814 int flags = 0;
2815
2816 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002817 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2818 PyErr_SetObject(DBError, t);
2819 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002820 return -1;
2821 }
2822
2823 if (!make_key_dbt(self, keyobj, &key, NULL))
2824 return -1;
2825
2826 if (dataobj != NULL) {
2827 if (!make_dbt(dataobj, &data))
2828 retval = -1;
2829 else {
2830 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002831 /* dictionaries shouldn't have duplicate keys */
2832 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002833 retval = _DB_put(self, NULL, &key, &data, flags);
2834
2835 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002836 /* try deleting any old record that matches and then PUT it
2837 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 _DB_delete(self, NULL, &key, 0);
2839 PyErr_Clear();
2840 retval = _DB_put(self, NULL, &key, &data, flags);
2841 }
2842 }
2843 }
2844 else {
2845 /* dataobj == NULL, so delete the key */
2846 retval = _DB_delete(self, NULL, &key, 0);
2847 }
2848 FREE_DBT(key);
2849 return retval;
2850}
2851
2852
2853static PyObject*
2854DB_has_key(DBObject* self, PyObject* args)
2855{
2856 int err;
2857 PyObject* keyobj;
2858 DBT key, data;
2859 PyObject* txnobj = NULL;
2860 DB_TXN *txn = NULL;
2861
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002862 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002863 return NULL;
2864 CHECK_DB_NOT_CLOSED(self);
2865 if (!make_key_dbt(self, keyobj, &key, NULL))
2866 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002867 if (!checkTxnObj(txnobj, &txn)) {
2868 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002870 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002871
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002872 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873 it has a record but can't allocate a buffer for the data. This saves
2874 having to deal with data we won't be using.
2875 */
2876 CLEAR_DBT(data);
2877 data.flags = DB_DBT_USERMEM;
2878
2879 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002880 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002881 MYDB_END_ALLOW_THREADS;
2882 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002883
2884 if (err == DB_BUFFER_SMALL || err == 0) {
2885 return PyInt_FromLong(1);
2886 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2887 return PyInt_FromLong(0);
2888 }
2889
2890 makeDBError(err);
2891 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002892}
2893
2894
2895#define _KEYS_LIST 1
2896#define _VALUES_LIST 2
2897#define _ITEMS_LIST 3
2898
2899static PyObject*
2900_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2901{
2902 int err, dbtype;
2903 DBT key;
2904 DBT data;
2905 DBC *cursor;
2906 PyObject* list;
2907 PyObject* item = NULL;
2908
2909 CHECK_DB_NOT_CLOSED(self);
2910 CLEAR_DBT(key);
2911 CLEAR_DBT(data);
2912
2913 dbtype = _DB_get_type(self);
2914 if (dbtype == -1)
2915 return NULL;
2916
2917 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002918 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002920
2921 /* get a cursor */
2922 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002923 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002925 if (makeDBError(err)) {
2926 Py_DECREF(list);
2927 return NULL;
2928 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929
2930 if (CHECK_DBFLAG(self, DB_THREAD)) {
2931 key.flags = DB_DBT_REALLOC;
2932 data.flags = DB_DBT_REALLOC;
2933 }
2934
2935 while (1) { /* use the cursor to traverse the DB, collecting items */
2936 MYDB_BEGIN_ALLOW_THREADS;
2937 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2938 MYDB_END_ALLOW_THREADS;
2939
2940 if (err) {
2941 /* for any error, break out of the loop */
2942 break;
2943 }
2944
2945 switch (type) {
2946 case _KEYS_LIST:
2947 switch(dbtype) {
2948 case DB_BTREE:
2949 case DB_HASH:
2950 default:
2951 item = PyString_FromStringAndSize((char*)key.data, key.size);
2952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
2955 item = PyInt_FromLong(*((db_recno_t*)key.data));
2956 break;
2957 }
2958 break;
2959
2960 case _VALUES_LIST:
2961 item = PyString_FromStringAndSize((char*)data.data, data.size);
2962 break;
2963
2964 case _ITEMS_LIST:
2965 switch(dbtype) {
2966 case DB_BTREE:
2967 case DB_HASH:
2968 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002969 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2970 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971 break;
2972 case DB_RECNO:
2973 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002974 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2975 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 break;
2977 }
2978 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002979 default:
2980 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2981 item = NULL;
2982 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983 }
2984 if (item == NULL) {
2985 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986 list = NULL;
2987 goto done;
2988 }
2989 PyList_Append(list, item);
2990 Py_DECREF(item);
2991 }
2992
Gregory P. Smithe9477062005-06-04 06:46:59 +00002993 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2994 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002995 Py_DECREF(list);
2996 list = NULL;
2997 }
2998
2999 done:
3000 FREE_DBT(key);
3001 FREE_DBT(data);
3002 MYDB_BEGIN_ALLOW_THREADS;
3003 cursor->c_close(cursor);
3004 MYDB_END_ALLOW_THREADS;
3005 return list;
3006}
3007
3008
3009static PyObject*
3010DB_keys(DBObject* self, PyObject* args)
3011{
3012 PyObject* txnobj = NULL;
3013 DB_TXN *txn = NULL;
3014
Georg Brandl96a8c392006-05-29 21:04:52 +00003015 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016 return NULL;
3017 if (!checkTxnObj(txnobj, &txn))
3018 return NULL;
3019 return _DB_make_list(self, txn, _KEYS_LIST);
3020}
3021
3022
3023static PyObject*
3024DB_items(DBObject* self, PyObject* args)
3025{
3026 PyObject* txnobj = NULL;
3027 DB_TXN *txn = NULL;
3028
Georg Brandl96a8c392006-05-29 21:04:52 +00003029 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030 return NULL;
3031 if (!checkTxnObj(txnobj, &txn))
3032 return NULL;
3033 return _DB_make_list(self, txn, _ITEMS_LIST);
3034}
3035
3036
3037static PyObject*
3038DB_values(DBObject* self, PyObject* args)
3039{
3040 PyObject* txnobj = NULL;
3041 DB_TXN *txn = NULL;
3042
Georg Brandl96a8c392006-05-29 21:04:52 +00003043 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 return NULL;
3045 if (!checkTxnObj(txnobj, &txn))
3046 return NULL;
3047 return _DB_make_list(self, txn, _VALUES_LIST);
3048}
3049
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050/* --------------------------------------------------------------------- */
3051/* DBCursor methods */
3052
3053
3054static PyObject*
3055DBC_close(DBCursorObject* self, PyObject* args)
3056{
3057 int err = 0;
3058
3059 if (!PyArg_ParseTuple(args, ":close"))
3060 return NULL;
3061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062 if (self->dbc != NULL) {
3063 MYDB_BEGIN_ALLOW_THREADS;
3064 err = self->dbc->c_close(self->dbc);
3065 self->dbc = NULL;
3066 MYDB_END_ALLOW_THREADS;
3067 }
3068 RETURN_IF_ERR();
3069 RETURN_NONE();
3070}
3071
3072
3073static PyObject*
3074DBC_count(DBCursorObject* self, PyObject* args)
3075{
3076 int err = 0;
3077 db_recno_t count;
3078 int flags = 0;
3079
3080 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3081 return NULL;
3082
3083 CHECK_CURSOR_NOT_CLOSED(self);
3084
3085 MYDB_BEGIN_ALLOW_THREADS;
3086 err = self->dbc->c_count(self->dbc, &count, flags);
3087 MYDB_END_ALLOW_THREADS;
3088 RETURN_IF_ERR();
3089
3090 return PyInt_FromLong(count);
3091}
3092
3093
3094static PyObject*
3095DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3096{
3097 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3098}
3099
3100
3101static PyObject*
3102DBC_delete(DBCursorObject* self, PyObject* args)
3103{
3104 int err, flags=0;
3105
3106 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3107 return NULL;
3108
3109 CHECK_CURSOR_NOT_CLOSED(self);
3110
3111 MYDB_BEGIN_ALLOW_THREADS;
3112 err = self->dbc->c_del(self->dbc, flags);
3113 MYDB_END_ALLOW_THREADS;
3114 RETURN_IF_ERR();
3115
3116 self->mydb->haveStat = 0;
3117 RETURN_NONE();
3118}
3119
3120
3121static PyObject*
3122DBC_dup(DBCursorObject* self, PyObject* args)
3123{
3124 int err, flags =0;
3125 DBC* dbc = NULL;
3126
3127 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3128 return NULL;
3129
3130 CHECK_CURSOR_NOT_CLOSED(self);
3131
3132 MYDB_BEGIN_ALLOW_THREADS;
3133 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3134 MYDB_END_ALLOW_THREADS;
3135 RETURN_IF_ERR();
3136
3137 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3138}
3139
3140static PyObject*
3141DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3142{
3143 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3144}
3145
3146
3147static PyObject*
3148DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3149{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003150 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 PyObject* keyobj = NULL;
3152 PyObject* dataobj = NULL;
3153 PyObject* retval = NULL;
3154 int dlen = -1;
3155 int doff = -1;
3156 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003157 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003158 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003159
3160 CLEAR_DBT(key);
3161 CLEAR_DBT(data);
3162 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003163 &flags, &dlen, &doff))
3164 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003166 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3167 &kwnames[1],
3168 &keyobj, &flags, &dlen, &doff))
3169 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003171 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3172 kwnames, &keyobj, &dataobj,
3173 &flags, &dlen, &doff))
3174 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003175 return NULL;
3176 }
3177 }
3178 }
3179
3180 CHECK_CURSOR_NOT_CLOSED(self);
3181
3182 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3183 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003184 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3185 (!add_partial_dbt(&data, dlen, doff)) )
3186 {
3187 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003189 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190
3191 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3192 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003193 if (!(key.flags & DB_DBT_REALLOC)) {
3194 key.flags |= DB_DBT_MALLOC;
3195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 }
3197
3198 MYDB_BEGIN_ALLOW_THREADS;
3199 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3200 MYDB_END_ALLOW_THREADS;
3201
Gregory P. Smithe9477062005-06-04 06:46:59 +00003202 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3203 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003204 Py_INCREF(Py_None);
3205 retval = Py_None;
3206 }
3207 else if (makeDBError(err)) {
3208 retval = NULL;
3209 }
3210 else {
3211 switch (_DB_get_type(self->mydb)) {
3212 case -1:
3213 retval = NULL;
3214 break;
3215 case DB_BTREE:
3216 case DB_HASH:
3217 default:
3218 retval = Py_BuildValue("s#s#", key.data, key.size,
3219 data.data, data.size);
3220 break;
3221 case DB_RECNO:
3222 case DB_QUEUE:
3223 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3224 data.data, data.size);
3225 break;
3226 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003227 FREE_DBT(data);
3228 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003229 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003230 return retval;
3231}
3232
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003233#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003234static PyObject*
3235DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3236{
3237 int err, flags=0;
3238 PyObject* keyobj = NULL;
3239 PyObject* dataobj = NULL;
3240 PyObject* retval = NULL;
3241 int dlen = -1;
3242 int doff = -1;
3243 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003244 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3245 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003246
3247 CLEAR_DBT(key);
3248 CLEAR_DBT(data);
3249 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3250 &flags, &dlen, &doff))
3251 {
3252 PyErr_Clear();
3253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003254 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003255 &keyobj, &flags, &dlen, &doff))
3256 {
3257 PyErr_Clear();
3258 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3259 kwnames, &keyobj, &dataobj,
3260 &flags, &dlen, &doff))
3261 {
3262 return NULL;
3263 }
3264 }
3265 }
3266
3267 CHECK_CURSOR_NOT_CLOSED(self);
3268
3269 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3270 return NULL;
3271 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3272 (!add_partial_dbt(&data, dlen, doff)) ) {
3273 FREE_DBT(key);
3274 return NULL;
3275 }
3276
3277 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3278 data.flags = DB_DBT_MALLOC;
3279 if (!(key.flags & DB_DBT_REALLOC)) {
3280 key.flags |= DB_DBT_MALLOC;
3281 }
3282 }
3283
3284 CLEAR_DBT(pkey);
3285 pkey.flags = DB_DBT_MALLOC;
3286
3287 MYDB_BEGIN_ALLOW_THREADS;
3288 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3289 MYDB_END_ALLOW_THREADS;
3290
Gregory P. Smithe9477062005-06-04 06:46:59 +00003291 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3292 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293 Py_INCREF(Py_None);
3294 retval = Py_None;
3295 }
3296 else if (makeDBError(err)) {
3297 retval = NULL;
3298 }
3299 else {
3300 PyObject *pkeyObj;
3301 PyObject *dataObj;
3302 dataObj = PyString_FromStringAndSize(data.data, data.size);
3303
3304 if (self->mydb->primaryDBType == DB_RECNO ||
3305 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003306 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307 else
3308 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3309
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003310 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 {
3312 PyObject *keyObj;
3313 int type = _DB_get_type(self->mydb);
3314 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003315 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003316 else
3317 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003318#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003319 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003320#else
3321 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3322#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003323 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324 FREE_DBT(key);
3325 }
3326 else /* return just the pkey and data */
3327 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003328#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003329 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003330#else
3331 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3332#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003333 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003334 Py_DECREF(dataObj);
3335 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003336 FREE_DBT(pkey);
3337 FREE_DBT(data);
3338 }
3339 /* the only time REALLOC should be set is if we used an integer
3340 * key that make_key_dbt malloc'd for us. always free these. */
3341 if (key.flags & DB_DBT_REALLOC) {
3342 FREE_DBT(key);
3343 }
3344 return retval;
3345}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003346#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003347
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348
3349static PyObject*
3350DBC_get_recno(DBCursorObject* self, PyObject* args)
3351{
3352 int err;
3353 db_recno_t recno;
3354 DBT key;
3355 DBT data;
3356
3357 if (!PyArg_ParseTuple(args, ":get_recno"))
3358 return NULL;
3359
3360 CHECK_CURSOR_NOT_CLOSED(self);
3361
3362 CLEAR_DBT(key);
3363 CLEAR_DBT(data);
3364 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3365 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3366 data.flags = DB_DBT_MALLOC;
3367 key.flags = DB_DBT_MALLOC;
3368 }
3369
3370 MYDB_BEGIN_ALLOW_THREADS;
3371 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3372 MYDB_END_ALLOW_THREADS;
3373 RETURN_IF_ERR();
3374
3375 recno = *((db_recno_t*)data.data);
3376 FREE_DBT(key);
3377 FREE_DBT(data);
3378 return PyInt_FromLong(recno);
3379}
3380
3381
3382static PyObject*
3383DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3384{
3385 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3386}
3387
3388
3389static PyObject*
3390DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3391{
3392 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3393}
3394
3395
3396static PyObject*
3397DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3398{
3399 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3400}
3401
3402
3403static PyObject*
3404DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3405{
3406 int err, flags = 0;
3407 PyObject* keyobj, *dataobj;
3408 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003409 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003410 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411 int dlen = -1;
3412 int doff = -1;
3413
3414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3415 &keyobj, &dataobj, &flags, &dlen, &doff))
3416 return NULL;
3417
3418 CHECK_CURSOR_NOT_CLOSED(self);
3419
3420 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3421 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003422 if (!make_dbt(dataobj, &data) ||
3423 !add_partial_dbt(&data, dlen, doff) )
3424 {
3425 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003426 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003427 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428
3429 MYDB_BEGIN_ALLOW_THREADS;
3430 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3431 MYDB_END_ALLOW_THREADS;
3432 FREE_DBT(key);
3433 RETURN_IF_ERR();
3434 self->mydb->haveStat = 0;
3435 RETURN_NONE();
3436}
3437
3438
3439static PyObject*
3440DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3441{
3442 int err, flags = 0;
3443 DBT key, data;
3444 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003445 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446 int dlen = -1;
3447 int doff = -1;
3448
3449 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3450 &keyobj, &flags, &dlen, &doff))
3451 return NULL;
3452
3453 CHECK_CURSOR_NOT_CLOSED(self);
3454
3455 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3456 return NULL;
3457
3458 CLEAR_DBT(data);
3459 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3460 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3461 data.flags = DB_DBT_MALLOC;
3462 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003463 if (!add_partial_dbt(&data, dlen, doff)) {
3464 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003466 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467
3468 MYDB_BEGIN_ALLOW_THREADS;
3469 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3470 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003471 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3472 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003473 Py_INCREF(Py_None);
3474 retval = Py_None;
3475 }
3476 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477 retval = NULL;
3478 }
3479 else {
3480 switch (_DB_get_type(self->mydb)) {
3481 case -1:
3482 retval = NULL;
3483 break;
3484 case DB_BTREE:
3485 case DB_HASH:
3486 default:
3487 retval = Py_BuildValue("s#s#", key.data, key.size,
3488 data.data, data.size);
3489 break;
3490 case DB_RECNO:
3491 case DB_QUEUE:
3492 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3493 data.data, data.size);
3494 break;
3495 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003496 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003497 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003499 /* the only time REALLOC should be set is if we used an integer
3500 * key that make_key_dbt malloc'd for us. always free these. */
3501 if (key.flags & DB_DBT_REALLOC) {
3502 FREE_DBT(key);
3503 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003504
3505 return retval;
3506}
3507
3508
3509static PyObject*
3510DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3511{
3512 int err, flags = 0;
3513 DBT key, data;
3514 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003515 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 int dlen = -1;
3517 int doff = -1;
3518
3519 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3520 &keyobj, &flags, &dlen, &doff))
3521 return NULL;
3522
3523 CHECK_CURSOR_NOT_CLOSED(self);
3524
3525 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3526 return NULL;
3527
3528 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003529 if (!add_partial_dbt(&data, dlen, doff)) {
3530 FREE_DBT(key);
3531 return NULL;
3532 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3534 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003535 data.flags |= DB_DBT_MALLOC;
3536 /* only BTREE databases will return anything in the key */
3537 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3538 key.flags |= DB_DBT_MALLOC;
3539 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3543 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003544 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3545 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003546 Py_INCREF(Py_None);
3547 retval = Py_None;
3548 }
3549 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550 retval = NULL;
3551 }
3552 else {
3553 switch (_DB_get_type(self->mydb)) {
3554 case -1:
3555 retval = NULL;
3556 break;
3557 case DB_BTREE:
3558 case DB_HASH:
3559 default:
3560 retval = Py_BuildValue("s#s#", key.data, key.size,
3561 data.data, data.size);
3562 break;
3563 case DB_RECNO:
3564 case DB_QUEUE:
3565 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3566 data.data, data.size);
3567 break;
3568 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003569 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570 FREE_DBT(data);
3571 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003573 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003574 if (key.flags & DB_DBT_REALLOC) {
3575 FREE_DBT(key);
3576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577
3578 return retval;
3579}
3580
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003582_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3583 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003585 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003587 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588
Gregory P. Smith7441e652003-11-03 21:35:31 +00003589 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3591 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003592 if (!make_dbt(dataobj, &data)) {
3593 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003595 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596
3597 MYDB_BEGIN_ALLOW_THREADS;
3598 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3599 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003600 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003601 Py_INCREF(Py_None);
3602 retval = Py_None;
3603 }
3604 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003605 retval = NULL;
3606 }
3607 else {
3608 switch (_DB_get_type(self->mydb)) {
3609 case -1:
3610 retval = NULL;
3611 break;
3612 case DB_BTREE:
3613 case DB_HASH:
3614 default:
3615 retval = Py_BuildValue("s#s#", key.data, key.size,
3616 data.data, data.size);
3617 break;
3618 case DB_RECNO:
3619 case DB_QUEUE:
3620 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3621 data.data, data.size);
3622 break;
3623 }
3624 }
3625
3626 FREE_DBT(key);
3627 return retval;
3628}
3629
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003630static PyObject*
3631DBC_get_both(DBCursorObject* self, PyObject* args)
3632{
3633 int flags=0;
3634 PyObject *keyobj, *dataobj;
3635
3636 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3637 return NULL;
3638
Gregory P. Smith7441e652003-11-03 21:35:31 +00003639 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003640 CHECK_CURSOR_NOT_CLOSED(self);
3641
3642 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3643 self->mydb->moduleFlags.getReturnsNone);
3644}
3645
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003646/* Return size of entry */
3647static PyObject*
3648DBC_get_current_size(DBCursorObject* self, PyObject* args)
3649{
3650 int err, flags=DB_CURRENT;
3651 PyObject* retval = NULL;
3652 DBT key, data;
3653
3654 if (!PyArg_ParseTuple(args, ":get_current_size"))
3655 return NULL;
3656 CHECK_CURSOR_NOT_CLOSED(self);
3657 CLEAR_DBT(key);
3658 CLEAR_DBT(data);
3659
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003660 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003661 getting the record size. */
3662 data.flags = DB_DBT_USERMEM;
3663 data.ulen = 0;
3664 MYDB_BEGIN_ALLOW_THREADS;
3665 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3666 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003667 if (err == DB_BUFFER_SMALL || !err) {
3668 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003669 retval = PyInt_FromLong((long)data.size);
3670 err = 0;
3671 }
3672
3673 FREE_DBT(key);
3674 FREE_DBT(data);
3675 RETURN_IF_ERR();
3676 return retval;
3677}
3678
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003679static PyObject*
3680DBC_set_both(DBCursorObject* self, PyObject* args)
3681{
3682 int flags=0;
3683 PyObject *keyobj, *dataobj;
3684
3685 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3686 return NULL;
3687
Gregory P. Smith7441e652003-11-03 21:35:31 +00003688 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003689 CHECK_CURSOR_NOT_CLOSED(self);
3690
3691 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3692 self->mydb->moduleFlags.cursorSetReturnsNone);
3693}
3694
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003695
3696static PyObject*
3697DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3698{
3699 int err, irecno, flags=0;
3700 db_recno_t recno;
3701 DBT key, data;
3702 PyObject* retval;
3703 int dlen = -1;
3704 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003705 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003706
3707 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3708 &irecno, &flags, &dlen, &doff))
3709 return NULL;
3710
3711 CHECK_CURSOR_NOT_CLOSED(self);
3712
3713 CLEAR_DBT(key);
3714 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003715 /* use allocated space so DB will be able to realloc room for the real
3716 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717 key.data = malloc(sizeof(db_recno_t));
3718 if (key.data == NULL) {
3719 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3720 return NULL;
3721 }
3722 key.size = sizeof(db_recno_t);
3723 key.ulen = key.size;
3724 memcpy(key.data, &recno, sizeof(db_recno_t));
3725 key.flags = DB_DBT_REALLOC;
3726
3727 CLEAR_DBT(data);
3728 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3729 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3730 data.flags = DB_DBT_MALLOC;
3731 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003732 if (!add_partial_dbt(&data, dlen, doff)) {
3733 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003735 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736
3737 MYDB_BEGIN_ALLOW_THREADS;
3738 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3739 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003740 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3741 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003742 Py_INCREF(Py_None);
3743 retval = Py_None;
3744 }
3745 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003746 retval = NULL;
3747 }
3748 else { /* Can only be used for BTrees, so no need to return int key */
3749 retval = Py_BuildValue("s#s#", key.data, key.size,
3750 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003751 FREE_DBT(data);
3752 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003753 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754
3755 return retval;
3756}
3757
3758
3759static PyObject*
3760DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3761{
3762 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3763}
3764
3765
3766static PyObject*
3767DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3768{
3769 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3770}
3771
3772
3773static PyObject*
3774DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3775{
3776 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3777}
3778
3779
3780static PyObject*
3781DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3782{
3783 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3784}
3785
3786
3787static PyObject*
3788DBC_join_item(DBCursorObject* self, PyObject* args)
3789{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003790 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791 DBT key, data;
3792 PyObject* retval;
3793
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003794 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003795 return NULL;
3796
3797 CHECK_CURSOR_NOT_CLOSED(self);
3798
3799 CLEAR_DBT(key);
3800 CLEAR_DBT(data);
3801 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3802 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3803 key.flags = DB_DBT_MALLOC;
3804 }
3805
3806 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003807 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003808 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003809 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3810 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003811 Py_INCREF(Py_None);
3812 retval = Py_None;
3813 }
3814 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815 retval = NULL;
3816 }
3817 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003818 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003819 FREE_DBT(key);
3820 }
3821
3822 return retval;
3823}
3824
3825
3826
3827/* --------------------------------------------------------------------- */
3828/* DBEnv methods */
3829
3830
3831static PyObject*
3832DBEnv_close(DBEnvObject* self, PyObject* args)
3833{
3834 int err, flags = 0;
3835
3836 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3837 return NULL;
3838 if (!self->closed) { /* Don't close more than once */
3839 MYDB_BEGIN_ALLOW_THREADS;
3840 err = self->db_env->close(self->db_env, flags);
3841 MYDB_END_ALLOW_THREADS;
3842 /* after calling DBEnv->close, regardless of error, this DBEnv
3843 * may not be accessed again (BerkeleyDB docs). */
3844 self->closed = 1;
3845 self->db_env = NULL;
3846 RETURN_IF_ERR();
3847 }
3848 RETURN_NONE();
3849}
3850
3851
3852static PyObject*
3853DBEnv_open(DBEnvObject* self, PyObject* args)
3854{
3855 int err, flags=0, mode=0660;
3856 char *db_home;
3857
3858 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3859 return NULL;
3860
3861 CHECK_ENV_NOT_CLOSED(self);
3862
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->open(self->db_env, db_home, flags, mode);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 self->closed = 0;
3868 self->flags = flags;
3869 RETURN_NONE();
3870}
3871
3872
3873static PyObject*
3874DBEnv_remove(DBEnvObject* self, PyObject* args)
3875{
3876 int err, flags=0;
3877 char *db_home;
3878
3879 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3880 return NULL;
3881 CHECK_ENV_NOT_CLOSED(self);
3882 MYDB_BEGIN_ALLOW_THREADS;
3883 err = self->db_env->remove(self->db_env, db_home, flags);
3884 MYDB_END_ALLOW_THREADS;
3885 RETURN_IF_ERR();
3886 RETURN_NONE();
3887}
3888
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003889#if (DBVER >= 41)
3890static PyObject*
3891DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3892{
3893 int err;
3894 u_int32_t flags=0;
3895 char *file = NULL;
3896 char *database = NULL;
3897 PyObject *txnobj = NULL;
3898 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003899 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003900 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003901
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003903 &file, &database, &txnobj, &flags)) {
3904 return NULL;
3905 }
3906 if (!checkTxnObj(txnobj, &txn)) {
3907 return NULL;
3908 }
3909 CHECK_ENV_NOT_CLOSED(self);
3910 MYDB_BEGIN_ALLOW_THREADS;
3911 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3912 MYDB_END_ALLOW_THREADS;
3913 RETURN_IF_ERR();
3914 RETURN_NONE();
3915}
3916
3917static PyObject*
3918DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3919{
3920 int err;
3921 u_int32_t flags=0;
3922 char *file = NULL;
3923 char *database = NULL;
3924 char *newname = NULL;
3925 PyObject *txnobj = NULL;
3926 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003927 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003928 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003929
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003931 &file, &database, &newname, &txnobj, &flags)) {
3932 return NULL;
3933 }
3934 if (!checkTxnObj(txnobj, &txn)) {
3935 return NULL;
3936 }
3937 CHECK_ENV_NOT_CLOSED(self);
3938 MYDB_BEGIN_ALLOW_THREADS;
3939 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3940 flags);
3941 MYDB_END_ALLOW_THREADS;
3942 RETURN_IF_ERR();
3943 RETURN_NONE();
3944}
3945
3946static PyObject*
3947DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3948{
3949 int err;
3950 u_int32_t flags=0;
3951 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003952 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003953
3954 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3955 &passwd, &flags)) {
3956 return NULL;
3957 }
3958
3959 MYDB_BEGIN_ALLOW_THREADS;
3960 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3961 MYDB_END_ALLOW_THREADS;
3962
3963 RETURN_IF_ERR();
3964 RETURN_NONE();
3965}
3966#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003967
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003968#if (DBVER >= 40)
3969static PyObject*
3970DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3971{
3972 int err;
3973 u_int32_t flags=0;
3974 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003975 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003976
3977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3978 &timeout, &flags)) {
3979 return NULL;
3980 }
3981
3982 MYDB_BEGIN_ALLOW_THREADS;
3983 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3984 MYDB_END_ALLOW_THREADS;
3985
3986 RETURN_IF_ERR();
3987 RETURN_NONE();
3988}
3989#endif /* DBVER >= 40 */
3990
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003992DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3993{
3994 int err;
3995 long shm_key = 0;
3996
3997 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3998 return NULL;
3999 CHECK_ENV_NOT_CLOSED(self);
4000
4001 err = self->db_env->set_shm_key(self->db_env, shm_key);
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004007DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4008{
4009 int err, gbytes=0, bytes=0, ncache=0;
4010
4011 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4012 &gbytes, &bytes, &ncache))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4015
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4021}
4022
4023
4024#if (DBVER >= 32)
4025static PyObject*
4026DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4027{
4028 int err, flags=0, onoff=0;
4029
4030 if (!PyArg_ParseTuple(args, "ii:set_flags",
4031 &flags, &onoff))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4034
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_flags(self->db_env, flags, onoff);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4040}
4041#endif
4042
4043
4044static PyObject*
4045DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4046{
4047 int err;
4048 char *dir;
4049
4050 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_data_dir(self->db_env, dir);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4064{
4065 int err, lg_bsize;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
4079static PyObject*
4080DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4081{
4082 int err;
4083 char *dir;
4084
4085 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4086 return NULL;
4087 CHECK_ENV_NOT_CLOSED(self);
4088
4089 MYDB_BEGIN_ALLOW_THREADS;
4090 err = self->db_env->set_lg_dir(self->db_env, dir);
4091 MYDB_END_ALLOW_THREADS;
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
4095
4096static PyObject*
4097DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4098{
4099 int err, lg_max;
4100
4101 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4102 return NULL;
4103 CHECK_ENV_NOT_CLOSED(self);
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_lg_max(self->db_env, lg_max);
4107 MYDB_END_ALLOW_THREADS;
4108 RETURN_IF_ERR();
4109 RETURN_NONE();
4110}
4111
4112
Neal Norwitz84562352005-10-20 04:30:15 +00004113#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004115DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4116{
4117 int err, lg_max;
4118
4119 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
Neal Norwitz84562352005-10-20 04:30:15 +00004129#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004130
4131
4132static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004133DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4134{
4135 int err, lk_detect;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004149#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004150static PyObject*
4151DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4152{
4153 int err, max;
4154
4155 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lk_max(self->db_env, max);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4164}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004166
4167
4168#if (DBVER >= 32)
4169
4170static PyObject*
4171DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4172{
4173 int err, max;
4174
4175 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4176 return NULL;
4177 CHECK_ENV_NOT_CLOSED(self);
4178
4179 MYDB_BEGIN_ALLOW_THREADS;
4180 err = self->db_env->set_lk_max_locks(self->db_env, max);
4181 MYDB_END_ALLOW_THREADS;
4182 RETURN_IF_ERR();
4183 RETURN_NONE();
4184}
4185
4186
4187static PyObject*
4188DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4189{
4190 int err, max;
4191
4192 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4193 return NULL;
4194 CHECK_ENV_NOT_CLOSED(self);
4195
4196 MYDB_BEGIN_ALLOW_THREADS;
4197 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4198 MYDB_END_ALLOW_THREADS;
4199 RETURN_IF_ERR();
4200 RETURN_NONE();
4201}
4202
4203
4204static PyObject*
4205DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4206{
4207 int err, max;
4208
4209 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_lk_max_objects(self->db_env, max);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
4220#endif
4221
4222
4223static PyObject*
4224DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4225{
4226 int err, mp_mmapsize;
4227
4228 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4229 return NULL;
4230 CHECK_ENV_NOT_CLOSED(self);
4231
4232 MYDB_BEGIN_ALLOW_THREADS;
4233 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4234 MYDB_END_ALLOW_THREADS;
4235 RETURN_IF_ERR();
4236 RETURN_NONE();
4237}
4238
4239
4240static PyObject*
4241DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4242{
4243 int err;
4244 char *dir;
4245
4246 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4247 return NULL;
4248 CHECK_ENV_NOT_CLOSED(self);
4249
4250 MYDB_BEGIN_ALLOW_THREADS;
4251 err = self->db_env->set_tmp_dir(self->db_env, dir);
4252 MYDB_END_ALLOW_THREADS;
4253 RETURN_IF_ERR();
4254 RETURN_NONE();
4255}
4256
4257
4258static PyObject*
4259DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4260{
4261 int flags = 0;
4262 PyObject* txnobj = NULL;
4263 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004264 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004265
4266 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4267 &txnobj, &flags))
4268 return NULL;
4269
4270 if (!checkTxnObj(txnobj, &txn))
4271 return NULL;
4272 CHECK_ENV_NOT_CLOSED(self);
4273
4274 return (PyObject*)newDBTxnObject(self, txn, flags);
4275}
4276
4277
4278static PyObject*
4279DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4280{
4281 int err, kbyte=0, min=0, flags=0;
4282
4283 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4284 return NULL;
4285 CHECK_ENV_NOT_CLOSED(self);
4286
4287 MYDB_BEGIN_ALLOW_THREADS;
4288#if (DBVER >= 40)
4289 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4290#else
4291 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4292#endif
4293 MYDB_END_ALLOW_THREADS;
4294 RETURN_IF_ERR();
4295 RETURN_NONE();
4296}
4297
4298
4299static PyObject*
4300DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4301{
4302 int err, max;
4303
4304 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4305 return NULL;
4306 CHECK_ENV_NOT_CLOSED(self);
4307
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004308 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004309 RETURN_IF_ERR();
4310 RETURN_NONE();
4311}
4312
4313
4314static PyObject*
4315DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4316{
4317 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004318 long stamp;
4319 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004320
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004321 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004322 return NULL;
4323 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004324 timestamp = (time_t)stamp;
4325 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004326 RETURN_IF_ERR();
4327 RETURN_NONE();
4328}
4329
4330
4331static PyObject*
4332DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4333{
4334 int err, atype, flags=0;
4335 int aborted = 0;
4336
4337 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4338 return NULL;
4339 CHECK_ENV_NOT_CLOSED(self);
4340
4341 MYDB_BEGIN_ALLOW_THREADS;
4342#if (DBVER >= 40)
4343 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4344#else
4345 err = lock_detect(self->db_env, flags, atype, &aborted);
4346#endif
4347 MYDB_END_ALLOW_THREADS;
4348 RETURN_IF_ERR();
4349 return PyInt_FromLong(aborted);
4350}
4351
4352
4353static PyObject*
4354DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4355{
4356 int flags=0;
4357 int locker, lock_mode;
4358 DBT obj;
4359 PyObject* objobj;
4360
4361 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4362 return NULL;
4363
4364
4365 if (!make_dbt(objobj, &obj))
4366 return NULL;
4367
4368 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4369}
4370
4371
4372static PyObject*
4373DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4374{
4375 int err;
4376 u_int32_t theID;
4377
4378 if (!PyArg_ParseTuple(args, ":lock_id"))
4379 return NULL;
4380
4381 CHECK_ENV_NOT_CLOSED(self);
4382 MYDB_BEGIN_ALLOW_THREADS;
4383#if (DBVER >= 40)
4384 err = self->db_env->lock_id(self->db_env, &theID);
4385#else
4386 err = lock_id(self->db_env, &theID);
4387#endif
4388 MYDB_END_ALLOW_THREADS;
4389 RETURN_IF_ERR();
4390
4391 return PyInt_FromLong((long)theID);
4392}
4393
4394
4395static PyObject*
4396DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4397{
4398 int err;
4399 DBLockObject* dblockobj;
4400
4401 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4402 return NULL;
4403
4404 CHECK_ENV_NOT_CLOSED(self);
4405 MYDB_BEGIN_ALLOW_THREADS;
4406#if (DBVER >= 40)
4407 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4408#else
4409 err = lock_put(self->db_env, &dblockobj->lock);
4410#endif
4411 MYDB_END_ALLOW_THREADS;
4412 RETURN_IF_ERR();
4413 RETURN_NONE();
4414}
4415
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004416#if (DBVER >= 44)
4417static PyObject*
4418DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4419{
4420 int err;
4421 char *file;
4422 u_int32_t flags = 0;
4423 static char* kwnames[] = { "file", "flags", NULL};
4424
4425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4426 &file, &flags))
4427 return NULL;
4428 CHECK_ENV_NOT_CLOSED(self);
4429
4430 MYDB_BEGIN_ALLOW_THREADS;
4431 err = self->db_env->lsn_reset(self->db_env, file, flags);
4432 MYDB_END_ALLOW_THREADS;
4433 RETURN_IF_ERR();
4434 RETURN_NONE();
4435}
4436#endif /* DBVER >= 4.4 */
4437
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004438#if (DBVER >= 40)
4439static PyObject*
4440DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4441{
4442 int err;
4443 DB_LOG_STAT* statp = NULL;
4444 PyObject* d = NULL;
4445 u_int32_t flags = 0;
4446
4447 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4448 return NULL;
4449 CHECK_ENV_NOT_CLOSED(self);
4450
4451 MYDB_BEGIN_ALLOW_THREADS;
4452 err = self->db_env->log_stat(self->db_env, &statp, flags);
4453 MYDB_END_ALLOW_THREADS;
4454 RETURN_IF_ERR();
4455
4456 /* Turn the stat structure into a dictionary */
4457 d = PyDict_New();
4458 if (d == NULL) {
4459 if (statp)
4460 free(statp);
4461 return NULL;
4462 }
4463
4464#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4465
4466 MAKE_ENTRY(magic);
4467 MAKE_ENTRY(version);
4468 MAKE_ENTRY(mode);
4469 MAKE_ENTRY(lg_bsize);
4470#if (DBVER >= 44)
4471 MAKE_ENTRY(lg_size);
4472 MAKE_ENTRY(record);
4473#endif
4474#if (DBVER <= 40)
4475 MAKE_ENTRY(lg_max);
4476#endif
4477 MAKE_ENTRY(w_mbytes);
4478 MAKE_ENTRY(w_bytes);
4479 MAKE_ENTRY(wc_mbytes);
4480 MAKE_ENTRY(wc_bytes);
4481 MAKE_ENTRY(wcount);
4482 MAKE_ENTRY(wcount_fill);
4483#if (DBVER >= 44)
4484 MAKE_ENTRY(rcount);
4485#endif
4486 MAKE_ENTRY(scount);
4487 MAKE_ENTRY(cur_file);
4488 MAKE_ENTRY(cur_offset);
4489 MAKE_ENTRY(disk_file);
4490 MAKE_ENTRY(disk_offset);
4491 MAKE_ENTRY(maxcommitperflush);
4492 MAKE_ENTRY(mincommitperflush);
4493 MAKE_ENTRY(regsize);
4494 MAKE_ENTRY(region_wait);
4495 MAKE_ENTRY(region_nowait);
4496
4497#undef MAKE_ENTRY
4498 free(statp);
4499 return d;
4500} /* DBEnv_log_stat */
4501#endif /* DBVER >= 4.0 for log_stat method */
4502
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004503
4504static PyObject*
4505DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4506{
4507 int err;
4508 DB_LOCK_STAT* sp;
4509 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004510 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004511
4512 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4513 return NULL;
4514 CHECK_ENV_NOT_CLOSED(self);
4515
4516 MYDB_BEGIN_ALLOW_THREADS;
4517#if (DBVER >= 40)
4518 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4519#else
4520#if (DBVER >= 33)
4521 err = lock_stat(self->db_env, &sp);
4522#else
4523 err = lock_stat(self->db_env, &sp, NULL);
4524#endif
4525#endif
4526 MYDB_END_ALLOW_THREADS;
4527 RETURN_IF_ERR();
4528
4529 /* Turn the stat structure into a dictionary */
4530 d = PyDict_New();
4531 if (d == NULL) {
4532 free(sp);
4533 return NULL;
4534 }
4535
4536#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4537
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004538#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004540#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MAKE_ENTRY(nmodes);
4542#if (DBVER >= 32)
4543 MAKE_ENTRY(maxlocks);
4544 MAKE_ENTRY(maxlockers);
4545 MAKE_ENTRY(maxobjects);
4546 MAKE_ENTRY(nlocks);
4547 MAKE_ENTRY(maxnlocks);
4548#endif
4549 MAKE_ENTRY(nlockers);
4550 MAKE_ENTRY(maxnlockers);
4551#if (DBVER >= 32)
4552 MAKE_ENTRY(nobjects);
4553 MAKE_ENTRY(maxnobjects);
4554#endif
4555 MAKE_ENTRY(nrequests);
4556 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004557#if (DBVER < 44)
4558 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004560#else
4561 MAKE_ENTRY(lock_nowait);
4562 MAKE_ENTRY(lock_wait);
4563#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004564 MAKE_ENTRY(ndeadlocks);
4565 MAKE_ENTRY(regsize);
4566 MAKE_ENTRY(region_wait);
4567 MAKE_ENTRY(region_nowait);
4568
4569#undef MAKE_ENTRY
4570 free(sp);
4571 return d;
4572}
4573
4574
4575static PyObject*
4576DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4577{
4578 int flags=0;
4579 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004580 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004581 PyObject* list;
4582 PyObject* item = NULL;
4583
4584 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4585 return NULL;
4586
4587 CHECK_ENV_NOT_CLOSED(self);
4588 MYDB_BEGIN_ALLOW_THREADS;
4589#if (DBVER >= 40)
4590 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4591#elif (DBVER == 33)
4592 err = log_archive(self->db_env, &log_list, flags);
4593#else
4594 err = log_archive(self->db_env, &log_list, flags, NULL);
4595#endif
4596 MYDB_END_ALLOW_THREADS;
4597 RETURN_IF_ERR();
4598
Gregory P. Smithbad47452006-06-05 00:33:35 +00004599 list = PyList_New(0);
4600 if (list == NULL) {
4601 if (log_list)
4602 free(log_list);
4603 return NULL;
4604 }
4605
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004607 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4609 item = PyString_FromString (*log_list);
4610 if (item == NULL) {
4611 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 list = NULL;
4613 break;
4614 }
4615 PyList_Append(list, item);
4616 Py_DECREF(item);
4617 }
4618 free(log_list_start);
4619 }
4620 return list;
4621}
4622
4623
4624static PyObject*
4625DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4626{
4627 int err;
4628 DB_TXN_STAT* sp;
4629 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004630 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004631
4632 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4633 return NULL;
4634 CHECK_ENV_NOT_CLOSED(self);
4635
4636 MYDB_BEGIN_ALLOW_THREADS;
4637#if (DBVER >= 40)
4638 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4639#elif (DBVER == 33)
4640 err = txn_stat(self->db_env, &sp);
4641#else
4642 err = txn_stat(self->db_env, &sp, NULL);
4643#endif
4644 MYDB_END_ALLOW_THREADS;
4645 RETURN_IF_ERR();
4646
4647 /* Turn the stat structure into a dictionary */
4648 d = PyDict_New();
4649 if (d == NULL) {
4650 free(sp);
4651 return NULL;
4652 }
4653
4654#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4655
4656 MAKE_ENTRY(time_ckp);
4657 MAKE_ENTRY(last_txnid);
4658 MAKE_ENTRY(maxtxns);
4659 MAKE_ENTRY(nactive);
4660 MAKE_ENTRY(maxnactive);
4661 MAKE_ENTRY(nbegins);
4662 MAKE_ENTRY(naborts);
4663 MAKE_ENTRY(ncommits);
4664 MAKE_ENTRY(regsize);
4665 MAKE_ENTRY(region_wait);
4666 MAKE_ENTRY(region_nowait);
4667
4668#undef MAKE_ENTRY
4669 free(sp);
4670 return d;
4671}
4672
4673
4674static PyObject*
4675DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4676{
4677 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004678 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004679
4680 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4681 return NULL;
4682 CHECK_ENV_NOT_CLOSED(self);
4683
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004684 if (self->moduleFlags.getReturnsNone)
4685 ++oldValue;
4686 if (self->moduleFlags.cursorSetReturnsNone)
4687 ++oldValue;
4688 self->moduleFlags.getReturnsNone = (flags >= 1);
4689 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004690 return PyInt_FromLong(oldValue);
4691}
4692
4693
4694/* --------------------------------------------------------------------- */
4695/* DBTxn methods */
4696
4697
4698static PyObject*
4699DBTxn_commit(DBTxnObject* self, PyObject* args)
4700{
4701 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004702 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004703
4704 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4705 return NULL;
4706
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004707 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004708 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4709 "after txn_commit or txn_abort");
4710 PyErr_SetObject(DBError, t);
4711 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004712 return NULL;
4713 }
4714 txn = self->txn;
4715 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004716 MYDB_BEGIN_ALLOW_THREADS;
4717#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004718 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004719#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004720 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004721#endif
4722 MYDB_END_ALLOW_THREADS;
4723 RETURN_IF_ERR();
4724 RETURN_NONE();
4725}
4726
4727static PyObject*
4728DBTxn_prepare(DBTxnObject* self, PyObject* args)
4729{
4730#if (DBVER >= 33)
4731 int err;
4732 char* gid=NULL;
4733 int gid_size=0;
4734
4735 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4736 return NULL;
4737
4738 if (gid_size != DB_XIDDATASIZE) {
4739 PyErr_SetString(PyExc_TypeError,
4740 "gid must be DB_XIDDATASIZE bytes long");
4741 return NULL;
4742 }
4743
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004744 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004745 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4746 "after txn_commit or txn_abort");
4747 PyErr_SetObject(DBError, t);
4748 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004749 return NULL;
4750 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004751 MYDB_BEGIN_ALLOW_THREADS;
4752#if (DBVER >= 40)
4753 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4754#else
4755 err = txn_prepare(self->txn, (u_int8_t*)gid);
4756#endif
4757 MYDB_END_ALLOW_THREADS;
4758 RETURN_IF_ERR();
4759 RETURN_NONE();
4760#else
4761 int err;
4762
4763 if (!PyArg_ParseTuple(args, ":prepare"))
4764 return NULL;
4765
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004766 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004767 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4768 "after txn_commit or txn_abort");
4769 PyErr_SetObject(DBError, t);
4770 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004771 return NULL;
4772 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004773 MYDB_BEGIN_ALLOW_THREADS;
4774 err = txn_prepare(self->txn);
4775 MYDB_END_ALLOW_THREADS;
4776 RETURN_IF_ERR();
4777 RETURN_NONE();
4778#endif
4779}
4780
4781
4782static PyObject*
4783DBTxn_abort(DBTxnObject* self, PyObject* args)
4784{
4785 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004786 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004787
4788 if (!PyArg_ParseTuple(args, ":abort"))
4789 return NULL;
4790
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004791 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004792 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4793 "after txn_commit or txn_abort");
4794 PyErr_SetObject(DBError, t);
4795 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004796 return NULL;
4797 }
4798 txn = self->txn;
4799 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004800 MYDB_BEGIN_ALLOW_THREADS;
4801#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004802 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004803#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004805#endif
4806 MYDB_END_ALLOW_THREADS;
4807 RETURN_IF_ERR();
4808 RETURN_NONE();
4809}
4810
4811
4812static PyObject*
4813DBTxn_id(DBTxnObject* self, PyObject* args)
4814{
4815 int id;
4816
4817 if (!PyArg_ParseTuple(args, ":id"))
4818 return NULL;
4819
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004820 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004821 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4822 "after txn_commit or txn_abort");
4823 PyErr_SetObject(DBError, t);
4824 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004825 return NULL;
4826 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004827 MYDB_BEGIN_ALLOW_THREADS;
4828#if (DBVER >= 40)
4829 id = self->txn->id(self->txn);
4830#else
4831 id = txn_id(self->txn);
4832#endif
4833 MYDB_END_ALLOW_THREADS;
4834 return PyInt_FromLong(id);
4835}
4836
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004837#if (DBVER >= 43)
4838/* --------------------------------------------------------------------- */
4839/* DBSequence methods */
4840
4841
4842static PyObject*
4843DBSequence_close(DBSequenceObject* self, PyObject* args)
4844{
4845 int err, flags=0;
4846 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4847 return NULL;
4848 CHECK_SEQUENCE_NOT_CLOSED(self)
4849
4850 MYDB_BEGIN_ALLOW_THREADS
4851 err = self->sequence->close(self->sequence, flags);
4852 self->sequence = NULL;
4853 MYDB_END_ALLOW_THREADS
4854
4855 RETURN_IF_ERR();
4856
4857 RETURN_NONE();
4858}
4859
4860static PyObject*
4861DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4862{
4863 int err, flags = 0;
4864 int delta = 1;
4865 db_seq_t value;
4866 PyObject *txnobj = NULL;
4867 DB_TXN *txn = NULL;
4868 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4869 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4870 return NULL;
4871 CHECK_SEQUENCE_NOT_CLOSED(self)
4872
4873 if (!checkTxnObj(txnobj, &txn))
4874 return NULL;
4875
4876 MYDB_BEGIN_ALLOW_THREADS
4877 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4878 MYDB_END_ALLOW_THREADS
4879
4880 RETURN_IF_ERR();
4881 return PyLong_FromLongLong(value);
4882
4883}
4884
4885static PyObject*
4886DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4887{
4888 if (!PyArg_ParseTuple(args,":get_dbp"))
4889 return NULL;
4890 CHECK_SEQUENCE_NOT_CLOSED(self)
4891 Py_INCREF(self->mydb);
4892 return (PyObject* )self->mydb;
4893}
4894
4895static PyObject*
4896DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4897{
4898 int err;
4899 DBT key;
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004900 PyObject *retval;
4901 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004902 CHECK_SEQUENCE_NOT_CLOSED(self)
4903 MYDB_BEGIN_ALLOW_THREADS
4904 err = self->sequence->get_key(self->sequence, &key);
4905 MYDB_END_ALLOW_THREADS
4906
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004907 if (!err)
4908 retval = PyString_FromStringAndSize(key.data, key.size);
4909
4910 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004911 RETURN_IF_ERR();
4912
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004913 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004914}
4915
4916static PyObject*
4917DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4918{
4919 int err;
4920 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004921 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004922 return NULL;
4923 CHECK_SEQUENCE_NOT_CLOSED(self)
4924
4925 MYDB_BEGIN_ALLOW_THREADS
4926 err = self->sequence->initial_value(self->sequence, value);
4927 MYDB_END_ALLOW_THREADS
4928
4929 RETURN_IF_ERR();
4930
4931 RETURN_NONE();
4932}
4933
4934static PyObject*
4935DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4936{
4937 int err, flags = 0;
4938 PyObject* keyobj;
4939 PyObject *txnobj = NULL;
4940 DB_TXN *txn = NULL;
4941 DBT key;
4942
4943 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004944 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004945 return NULL;
4946
4947 if (!checkTxnObj(txnobj, &txn))
4948 return NULL;
4949
4950 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4951 return NULL;
4952
4953 MYDB_BEGIN_ALLOW_THREADS
4954 err = self->sequence->open(self->sequence, txn, &key, flags);
4955 MYDB_END_ALLOW_THREADS
4956
4957 CLEAR_DBT(key);
4958 RETURN_IF_ERR();
4959
4960 RETURN_NONE();
4961}
4962
4963static PyObject*
4964DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4965{
4966 int err, flags = 0;
4967 PyObject *txnobj = NULL;
4968 DB_TXN *txn = NULL;
4969
4970 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004971 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004972 return NULL;
4973
4974 if (!checkTxnObj(txnobj, &txn))
4975 return NULL;
4976
4977 CHECK_SEQUENCE_NOT_CLOSED(self)
4978
4979 MYDB_BEGIN_ALLOW_THREADS
4980 err = self->sequence->remove(self->sequence, txn, flags);
4981 MYDB_END_ALLOW_THREADS
4982
4983 RETURN_IF_ERR();
4984 RETURN_NONE();
4985}
4986
4987static PyObject*
4988DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4989{
4990 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004991 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004992 return NULL;
4993 CHECK_SEQUENCE_NOT_CLOSED(self)
4994
4995 MYDB_BEGIN_ALLOW_THREADS
4996 err = self->sequence->set_cachesize(self->sequence, size);
4997 MYDB_END_ALLOW_THREADS
4998
4999 RETURN_IF_ERR();
5000 RETURN_NONE();
5001}
5002
5003static PyObject*
5004DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5005{
5006 int err, size;
5007 if (!PyArg_ParseTuple(args,":get_cachesize"))
5008 return NULL;
5009 CHECK_SEQUENCE_NOT_CLOSED(self)
5010
5011 MYDB_BEGIN_ALLOW_THREADS
5012 err = self->sequence->get_cachesize(self->sequence, &size);
5013 MYDB_END_ALLOW_THREADS
5014
5015 RETURN_IF_ERR();
5016 return PyInt_FromLong(size);
5017}
5018
5019static PyObject*
5020DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5021{
5022 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005023 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005024 return NULL;
5025 CHECK_SEQUENCE_NOT_CLOSED(self)
5026
5027 MYDB_BEGIN_ALLOW_THREADS
5028 err = self->sequence->set_flags(self->sequence, flags);
5029 MYDB_END_ALLOW_THREADS
5030
5031 RETURN_IF_ERR();
5032 RETURN_NONE();
5033
5034}
5035
5036static PyObject*
5037DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5038{
5039 unsigned int flags;
5040 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005041 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005042 return NULL;
5043 CHECK_SEQUENCE_NOT_CLOSED(self)
5044
5045 MYDB_BEGIN_ALLOW_THREADS
5046 err = self->sequence->get_flags(self->sequence, &flags);
5047 MYDB_END_ALLOW_THREADS
5048
5049 RETURN_IF_ERR();
5050 return PyInt_FromLong((int)flags);
5051}
5052
5053static PyObject*
5054DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5055{
5056 int err;
5057 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005058 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005059 return NULL;
5060 CHECK_SEQUENCE_NOT_CLOSED(self)
5061
5062 MYDB_BEGIN_ALLOW_THREADS
5063 err = self->sequence->set_range(self->sequence, min, max);
5064 MYDB_END_ALLOW_THREADS
5065
5066 RETURN_IF_ERR();
5067 RETURN_NONE();
5068}
5069
5070static PyObject*
5071DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5072{
5073 int err;
5074 db_seq_t min, max;
5075 if (!PyArg_ParseTuple(args,":get_range"))
5076 return NULL;
5077 CHECK_SEQUENCE_NOT_CLOSED(self)
5078
5079 MYDB_BEGIN_ALLOW_THREADS
5080 err = self->sequence->get_range(self->sequence, &min, &max);
5081 MYDB_END_ALLOW_THREADS
5082
5083 RETURN_IF_ERR();
5084 return Py_BuildValue("(LL)", min, max);
5085}
5086
5087static PyObject*
5088DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5089{
5090 int err, flags = 0;
5091 DB_SEQUENCE_STAT* sp = NULL;
5092 PyObject* dict_stat;
5093 static char* kwnames[] = {"flags", NULL };
5094 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5095 return NULL;
5096 CHECK_SEQUENCE_NOT_CLOSED(self);
5097
5098 MYDB_BEGIN_ALLOW_THREADS;
5099 err = self->sequence->stat(self->sequence, &sp, flags);
5100 MYDB_END_ALLOW_THREADS;
5101 RETURN_IF_ERR();
5102
5103 if ((dict_stat = PyDict_New()) == NULL) {
5104 free(sp);
5105 return NULL;
5106 }
5107
5108
5109#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5110#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5111
5112 MAKE_INT_ENTRY(wait);
5113 MAKE_INT_ENTRY(nowait);
5114 MAKE_LONG_LONG_ENTRY(current);
5115 MAKE_LONG_LONG_ENTRY(value);
5116 MAKE_LONG_LONG_ENTRY(last_value);
5117 MAKE_LONG_LONG_ENTRY(min);
5118 MAKE_LONG_LONG_ENTRY(max);
5119 MAKE_INT_ENTRY(cache_size);
5120 MAKE_INT_ENTRY(flags);
5121
5122#undef MAKE_INT_ENTRY
5123#undef MAKE_LONG_LONG_ENTRY
5124
5125 free(sp);
5126 return dict_stat;
5127}
5128#endif
5129
5130
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005131/* --------------------------------------------------------------------- */
5132/* Method definition tables and type objects */
5133
5134static PyMethodDef DB_methods[] = {
5135 {"append", (PyCFunction)DB_append, METH_VARARGS},
5136#if (DBVER >= 33)
5137 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5138#endif
5139 {"close", (PyCFunction)DB_close, METH_VARARGS},
5140#if (DBVER >= 32)
5141 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5142 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5143#endif
5144 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5145 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5146 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5147 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005148#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005149 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005150#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005151 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5152 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5153 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5154 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5155 {"join", (PyCFunction)DB_join, METH_VARARGS},
5156 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5157 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5158 {"items", (PyCFunction)DB_items, METH_VARARGS},
5159 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5160 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5161 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5162 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5163 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5164 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005165#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005166 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005168 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005169#if (DBVER >= 41)
5170 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5171#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005172 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5173 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5174 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5175 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5176 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5177 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5178 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5179 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5180 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5181#if (DBVER >= 32)
5182 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5183#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005184 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005185 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5186#if (DBVER >= 33)
5187 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5188#endif
5189 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5190 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5191 {"values", (PyCFunction)DB_values, METH_VARARGS},
5192 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5193 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5194 {NULL, NULL} /* sentinel */
5195};
5196
5197
5198static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005199 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005200 (binaryfunc)DB_subscript, /*mp_subscript*/
5201 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5202};
5203
5204
5205static PyMethodDef DBCursor_methods[] = {
5206 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5207 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5208 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5209 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5210 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5211 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5212 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005213#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005214 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005215#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005216 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5217 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5218 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5219 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5220 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5221 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5222 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5223 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005224 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005225 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005226 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5227 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5228 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5229 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5230 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5231 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5232 {NULL, NULL} /* sentinel */
5233};
5234
5235
5236static PyMethodDef DBEnv_methods[] = {
5237 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5238 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5239 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005240#if (DBVER >= 41)
5241 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5242 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5243 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5244#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005245#if (DBVER >= 40)
5246 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5247#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005248 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005249 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5250 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5251#if (DBVER >= 32)
5252 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5253#endif
5254 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5255 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5256 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005257#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005258 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005259#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005261#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264#if (DBVER >= 32)
5265 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5266 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5267 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5268#endif
5269 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5270 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5271 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5272 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5273 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5274 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005275 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005276 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5277 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5278 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5279 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5280 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5281 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005282#if (DBVER >= 40)
5283 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5284#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005285#if (DBVER >= 44)
5286 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5287#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005288 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5289 {NULL, NULL} /* sentinel */
5290};
5291
5292
5293static PyMethodDef DBTxn_methods[] = {
5294 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5295 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5296 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5297 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5298 {NULL, NULL} /* sentinel */
5299};
5300
5301
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005302#if (DBVER >= 43)
5303static PyMethodDef DBSequence_methods[] = {
5304 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5305 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5306 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5307 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005308 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5309 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5310 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5311 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5312 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5313 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5314 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5315 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5316 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5317 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5318 {NULL, NULL} /* sentinel */
5319};
5320#endif
5321
5322
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005323static PyObject*
5324DB_getattr(DBObject* self, char *name)
5325{
5326 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5327}
5328
5329
5330static PyObject*
5331DBEnv_getattr(DBEnvObject* self, char *name)
5332{
5333 if (!strcmp(name, "db_home")) {
5334 CHECK_ENV_NOT_CLOSED(self);
5335 if (self->db_env->db_home == NULL) {
5336 RETURN_NONE();
5337 }
5338 return PyString_FromString(self->db_env->db_home);
5339 }
5340
5341 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5342}
5343
5344
5345static PyObject*
5346DBCursor_getattr(DBCursorObject* self, char *name)
5347{
5348 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5349}
5350
5351static PyObject*
5352DBTxn_getattr(DBTxnObject* self, char *name)
5353{
5354 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5355}
5356
5357static PyObject*
5358DBLock_getattr(DBLockObject* self, char *name)
5359{
5360 return NULL;
5361}
5362
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005363#if (DBVER >= 43)
5364static PyObject*
5365DBSequence_getattr(DBSequenceObject* self, char *name)
5366{
5367 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5368}
5369#endif
5370
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005371statichere PyTypeObject DB_Type = {
5372 PyObject_HEAD_INIT(NULL)
5373 0, /*ob_size*/
5374 "DB", /*tp_name*/
5375 sizeof(DBObject), /*tp_basicsize*/
5376 0, /*tp_itemsize*/
5377 /* methods */
5378 (destructor)DB_dealloc, /*tp_dealloc*/
5379 0, /*tp_print*/
5380 (getattrfunc)DB_getattr, /*tp_getattr*/
5381 0, /*tp_setattr*/
5382 0, /*tp_compare*/
5383 0, /*tp_repr*/
5384 0, /*tp_as_number*/
5385 0, /*tp_as_sequence*/
5386 &DB_mapping,/*tp_as_mapping*/
5387 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005388#ifdef HAVE_WEAKREF
5389 0, /* tp_call */
5390 0, /* tp_str */
5391 0, /* tp_getattro */
5392 0, /* tp_setattro */
5393 0, /* tp_as_buffer */
5394 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5395 0, /* tp_doc */
5396 0, /* tp_traverse */
5397 0, /* tp_clear */
5398 0, /* tp_richcompare */
5399 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5400#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005401};
5402
5403
5404statichere PyTypeObject DBCursor_Type = {
5405 PyObject_HEAD_INIT(NULL)
5406 0, /*ob_size*/
5407 "DBCursor", /*tp_name*/
5408 sizeof(DBCursorObject), /*tp_basicsize*/
5409 0, /*tp_itemsize*/
5410 /* methods */
5411 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5412 0, /*tp_print*/
5413 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5414 0, /*tp_setattr*/
5415 0, /*tp_compare*/
5416 0, /*tp_repr*/
5417 0, /*tp_as_number*/
5418 0, /*tp_as_sequence*/
5419 0, /*tp_as_mapping*/
5420 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005421#ifdef HAVE_WEAKREF
5422 0, /* tp_call */
5423 0, /* tp_str */
5424 0, /* tp_getattro */
5425 0, /* tp_setattro */
5426 0, /* tp_as_buffer */
5427 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5428 0, /* tp_doc */
5429 0, /* tp_traverse */
5430 0, /* tp_clear */
5431 0, /* tp_richcompare */
5432 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5433#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434};
5435
5436
5437statichere PyTypeObject DBEnv_Type = {
5438 PyObject_HEAD_INIT(NULL)
5439 0, /*ob_size*/
5440 "DBEnv", /*tp_name*/
5441 sizeof(DBEnvObject), /*tp_basicsize*/
5442 0, /*tp_itemsize*/
5443 /* methods */
5444 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5445 0, /*tp_print*/
5446 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5447 0, /*tp_setattr*/
5448 0, /*tp_compare*/
5449 0, /*tp_repr*/
5450 0, /*tp_as_number*/
5451 0, /*tp_as_sequence*/
5452 0, /*tp_as_mapping*/
5453 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005454#ifdef HAVE_WEAKREF
5455 0, /* tp_call */
5456 0, /* tp_str */
5457 0, /* tp_getattro */
5458 0, /* tp_setattro */
5459 0, /* tp_as_buffer */
5460 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5461 0, /* tp_doc */
5462 0, /* tp_traverse */
5463 0, /* tp_clear */
5464 0, /* tp_richcompare */
5465 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5466#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005467};
5468
5469statichere PyTypeObject DBTxn_Type = {
5470 PyObject_HEAD_INIT(NULL)
5471 0, /*ob_size*/
5472 "DBTxn", /*tp_name*/
5473 sizeof(DBTxnObject), /*tp_basicsize*/
5474 0, /*tp_itemsize*/
5475 /* methods */
5476 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5477 0, /*tp_print*/
5478 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5479 0, /*tp_setattr*/
5480 0, /*tp_compare*/
5481 0, /*tp_repr*/
5482 0, /*tp_as_number*/
5483 0, /*tp_as_sequence*/
5484 0, /*tp_as_mapping*/
5485 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005486#ifdef HAVE_WEAKREF
5487 0, /* tp_call */
5488 0, /* tp_str */
5489 0, /* tp_getattro */
5490 0, /* tp_setattro */
5491 0, /* tp_as_buffer */
5492 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5493 0, /* tp_doc */
5494 0, /* tp_traverse */
5495 0, /* tp_clear */
5496 0, /* tp_richcompare */
5497 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499};
5500
5501
5502statichere PyTypeObject DBLock_Type = {
5503 PyObject_HEAD_INIT(NULL)
5504 0, /*ob_size*/
5505 "DBLock", /*tp_name*/
5506 sizeof(DBLockObject), /*tp_basicsize*/
5507 0, /*tp_itemsize*/
5508 /* methods */
5509 (destructor)DBLock_dealloc, /*tp_dealloc*/
5510 0, /*tp_print*/
5511 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5512 0, /*tp_setattr*/
5513 0, /*tp_compare*/
5514 0, /*tp_repr*/
5515 0, /*tp_as_number*/
5516 0, /*tp_as_sequence*/
5517 0, /*tp_as_mapping*/
5518 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005519#ifdef HAVE_WEAKREF
5520 0, /* tp_call */
5521 0, /* tp_str */
5522 0, /* tp_getattro */
5523 0, /* tp_setattro */
5524 0, /* tp_as_buffer */
5525 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5526 0, /* tp_doc */
5527 0, /* tp_traverse */
5528 0, /* tp_clear */
5529 0, /* tp_richcompare */
5530 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5531#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005532};
5533
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005534#if (DBVER >= 43)
5535statichere PyTypeObject DBSequence_Type = {
5536 PyObject_HEAD_INIT(NULL)
5537 0, /*ob_size*/
5538 "DBSequence", /*tp_name*/
5539 sizeof(DBSequenceObject), /*tp_basicsize*/
5540 0, /*tp_itemsize*/
5541 /* methods */
5542 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5543 0, /*tp_print*/
5544 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5545 0, /*tp_setattr*/
5546 0, /*tp_compare*/
5547 0, /*tp_repr*/
5548 0, /*tp_as_number*/
5549 0, /*tp_as_sequence*/
5550 0, /*tp_as_mapping*/
5551 0, /*tp_hash*/
5552#ifdef HAVE_WEAKREF
5553 0, /* tp_call */
5554 0, /* tp_str */
5555 0, /* tp_getattro */
5556 0, /* tp_setattro */
5557 0, /* tp_as_buffer */
5558 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5559 0, /* tp_doc */
5560 0, /* tp_traverse */
5561 0, /* tp_clear */
5562 0, /* tp_richcompare */
5563 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5564#endif
5565};
5566#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005567
5568/* --------------------------------------------------------------------- */
5569/* Module-level functions */
5570
5571static PyObject*
5572DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5573{
5574 PyObject* dbenvobj = NULL;
5575 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005576 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005577
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5579 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005580 return NULL;
5581 if (dbenvobj == Py_None)
5582 dbenvobj = NULL;
5583 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5584 makeTypeError("DBEnv", dbenvobj);
5585 return NULL;
5586 }
5587
5588 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5589}
5590
5591
5592static PyObject*
5593DBEnv_construct(PyObject* self, PyObject* args)
5594{
5595 int flags = 0;
5596 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5597 return (PyObject* )newDBEnvObject(flags);
5598}
5599
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005600#if (DBVER >= 43)
5601static PyObject*
5602DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5603{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005604 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005605 int flags = 0;
5606 static char* kwnames[] = { "db", "flags", NULL};
5607
5608 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5609 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005610 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005611 makeTypeError("DB", dbobj);
5612 return NULL;
5613 }
5614 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5615}
5616#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005617
5618static char bsddb_version_doc[] =
5619"Returns a tuple of major, minor, and patch release numbers of the\n\
5620underlying DB library.";
5621
5622static PyObject*
5623bsddb_version(PyObject* self, PyObject* args)
5624{
5625 int major, minor, patch;
5626
5627 if (!PyArg_ParseTuple(args, ":version"))
5628 return NULL;
5629 db_version(&major, &minor, &patch);
5630 return Py_BuildValue("(iii)", major, minor, patch);
5631}
5632
5633
5634/* List of functions defined in the module */
5635
5636static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005637 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5638 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5639#if (DBVER >= 43)
5640 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5641#endif
5642 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005643 {NULL, NULL} /* sentinel */
5644};
5645
5646
5647/* --------------------------------------------------------------------- */
5648/* Module initialization */
5649
5650
5651/* Convenience routine to export an integer value.
5652 * Errors are silently ignored, for better or for worse...
5653 */
5654#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5655
Gregory P. Smith41631e82003-09-21 00:08:14 +00005656#define MODULE_NAME_MAX_LEN 11
5657static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005658
5659DL_EXPORT(void) init_bsddb(void)
5660{
5661 PyObject* m;
5662 PyObject* d;
5663 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5664 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5665 PyObject* cvsid_s = PyString_FromString( rcs_id );
5666
5667 /* Initialize the type of the new type objects here; doing it here
5668 is required for portability to Windows without requiring C++. */
5669 DB_Type.ob_type = &PyType_Type;
5670 DBCursor_Type.ob_type = &PyType_Type;
5671 DBEnv_Type.ob_type = &PyType_Type;
5672 DBTxn_Type.ob_type = &PyType_Type;
5673 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005674#if (DBVER >= 43)
5675 DBSequence_Type.ob_type = &PyType_Type;
5676#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005677
5678
Mark Hammonda69d4092003-04-22 23:13:27 +00005679#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005680 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005681 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682#endif
5683
5684 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005685 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005686 if (m == NULL)
5687 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005688
5689 /* Add some symbolic constants to the module */
5690 d = PyModule_GetDict(m);
5691 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5692 PyDict_SetItemString(d, "cvsid", cvsid_s);
5693 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5694 Py_DECREF(pybsddb_version_s);
5695 pybsddb_version_s = NULL;
5696 Py_DECREF(cvsid_s);
5697 cvsid_s = NULL;
5698 Py_DECREF(db_version_s);
5699 db_version_s = NULL;
5700
5701 ADD_INT(d, DB_VERSION_MAJOR);
5702 ADD_INT(d, DB_VERSION_MINOR);
5703 ADD_INT(d, DB_VERSION_PATCH);
5704
5705 ADD_INT(d, DB_MAX_PAGES);
5706 ADD_INT(d, DB_MAX_RECORDS);
5707
Gregory P. Smith41631e82003-09-21 00:08:14 +00005708#if (DBVER >= 42)
5709 ADD_INT(d, DB_RPCCLIENT);
5710#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005712 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5713 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5714#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005715 ADD_INT(d, DB_XA_CREATE);
5716
5717 ADD_INT(d, DB_CREATE);
5718 ADD_INT(d, DB_NOMMAP);
5719 ADD_INT(d, DB_THREAD);
5720
5721 ADD_INT(d, DB_FORCE);
5722 ADD_INT(d, DB_INIT_CDB);
5723 ADD_INT(d, DB_INIT_LOCK);
5724 ADD_INT(d, DB_INIT_LOG);
5725 ADD_INT(d, DB_INIT_MPOOL);
5726 ADD_INT(d, DB_INIT_TXN);
5727#if (DBVER >= 32)
5728 ADD_INT(d, DB_JOINENV);
5729#endif
5730
5731 ADD_INT(d, DB_RECOVER);
5732 ADD_INT(d, DB_RECOVER_FATAL);
5733 ADD_INT(d, DB_TXN_NOSYNC);
5734 ADD_INT(d, DB_USE_ENVIRON);
5735 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5736
5737 ADD_INT(d, DB_LOCKDOWN);
5738 ADD_INT(d, DB_PRIVATE);
5739 ADD_INT(d, DB_SYSTEM_MEM);
5740
5741 ADD_INT(d, DB_TXN_SYNC);
5742 ADD_INT(d, DB_TXN_NOWAIT);
5743
5744 ADD_INT(d, DB_EXCL);
5745 ADD_INT(d, DB_FCNTL_LOCKING);
5746 ADD_INT(d, DB_ODDFILESIZE);
5747 ADD_INT(d, DB_RDWRMASTER);
5748 ADD_INT(d, DB_RDONLY);
5749 ADD_INT(d, DB_TRUNCATE);
5750#if (DBVER >= 32)
5751 ADD_INT(d, DB_EXTENT);
5752 ADD_INT(d, DB_CDB_ALLDB);
5753 ADD_INT(d, DB_VERIFY);
5754#endif
5755 ADD_INT(d, DB_UPGRADE);
5756
5757 ADD_INT(d, DB_AGGRESSIVE);
5758 ADD_INT(d, DB_NOORDERCHK);
5759 ADD_INT(d, DB_ORDERCHKONLY);
5760 ADD_INT(d, DB_PR_PAGE);
5761#if ! (DBVER >= 33)
5762 ADD_INT(d, DB_VRFY_FLAGMASK);
5763 ADD_INT(d, DB_PR_HEADERS);
5764#endif
5765 ADD_INT(d, DB_PR_RECOVERYTEST);
5766 ADD_INT(d, DB_SALVAGE);
5767
5768 ADD_INT(d, DB_LOCK_NORUN);
5769 ADD_INT(d, DB_LOCK_DEFAULT);
5770 ADD_INT(d, DB_LOCK_OLDEST);
5771 ADD_INT(d, DB_LOCK_RANDOM);
5772 ADD_INT(d, DB_LOCK_YOUNGEST);
5773#if (DBVER >= 33)
5774 ADD_INT(d, DB_LOCK_MAXLOCKS);
5775 ADD_INT(d, DB_LOCK_MINLOCKS);
5776 ADD_INT(d, DB_LOCK_MINWRITE);
5777#endif
5778
5779
5780#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005781 /* docs say to use zero instead */
5782 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005783#else
5784 ADD_INT(d, DB_LOCK_CONFLICT);
5785#endif
5786
5787 ADD_INT(d, DB_LOCK_DUMP);
5788 ADD_INT(d, DB_LOCK_GET);
5789 ADD_INT(d, DB_LOCK_INHERIT);
5790 ADD_INT(d, DB_LOCK_PUT);
5791 ADD_INT(d, DB_LOCK_PUT_ALL);
5792 ADD_INT(d, DB_LOCK_PUT_OBJ);
5793
5794 ADD_INT(d, DB_LOCK_NG);
5795 ADD_INT(d, DB_LOCK_READ);
5796 ADD_INT(d, DB_LOCK_WRITE);
5797 ADD_INT(d, DB_LOCK_NOWAIT);
5798#if (DBVER >= 32)
5799 ADD_INT(d, DB_LOCK_WAIT);
5800#endif
5801 ADD_INT(d, DB_LOCK_IWRITE);
5802 ADD_INT(d, DB_LOCK_IREAD);
5803 ADD_INT(d, DB_LOCK_IWR);
5804#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005805#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005806 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005807#else
5808 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5809#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005810 ADD_INT(d, DB_LOCK_WWRITE);
5811#endif
5812
5813 ADD_INT(d, DB_LOCK_RECORD);
5814 ADD_INT(d, DB_LOCK_UPGRADE);
5815#if (DBVER >= 32)
5816 ADD_INT(d, DB_LOCK_SWITCH);
5817#endif
5818#if (DBVER >= 33)
5819 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5820#endif
5821
5822 ADD_INT(d, DB_LOCK_NOWAIT);
5823 ADD_INT(d, DB_LOCK_RECORD);
5824 ADD_INT(d, DB_LOCK_UPGRADE);
5825
5826#if (DBVER >= 33)
5827 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005828#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005830#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005831 ADD_INT(d, DB_LSTAT_FREE);
5832 ADD_INT(d, DB_LSTAT_HELD);
5833#if (DBVER == 33)
5834 ADD_INT(d, DB_LSTAT_NOGRANT);
5835#endif
5836 ADD_INT(d, DB_LSTAT_PENDING);
5837 ADD_INT(d, DB_LSTAT_WAITING);
5838#endif
5839
5840 ADD_INT(d, DB_ARCH_ABS);
5841 ADD_INT(d, DB_ARCH_DATA);
5842 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005843#if (DBVER >= 42)
5844 ADD_INT(d, DB_ARCH_REMOVE);
5845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846
5847 ADD_INT(d, DB_BTREE);
5848 ADD_INT(d, DB_HASH);
5849 ADD_INT(d, DB_RECNO);
5850 ADD_INT(d, DB_QUEUE);
5851 ADD_INT(d, DB_UNKNOWN);
5852
5853 ADD_INT(d, DB_DUP);
5854 ADD_INT(d, DB_DUPSORT);
5855 ADD_INT(d, DB_RECNUM);
5856 ADD_INT(d, DB_RENUMBER);
5857 ADD_INT(d, DB_REVSPLITOFF);
5858 ADD_INT(d, DB_SNAPSHOT);
5859
5860 ADD_INT(d, DB_JOIN_NOSORT);
5861
5862 ADD_INT(d, DB_AFTER);
5863 ADD_INT(d, DB_APPEND);
5864 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005865#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005866 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005867#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005868#if (DBVER >= 41)
5869 _addIntToDict(d, "DB_CHECKPOINT", 0);
5870#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005871 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005872 ADD_INT(d, DB_CURLSN);
5873#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005874#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875 ADD_INT(d, DB_COMMIT);
5876#endif
5877 ADD_INT(d, DB_CONSUME);
5878#if (DBVER >= 32)
5879 ADD_INT(d, DB_CONSUME_WAIT);
5880#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881 ADD_INT(d, DB_CURRENT);
5882#if (DBVER >= 33)
5883 ADD_INT(d, DB_FAST_STAT);
5884#endif
5885 ADD_INT(d, DB_FIRST);
5886 ADD_INT(d, DB_FLUSH);
5887 ADD_INT(d, DB_GET_BOTH);
5888 ADD_INT(d, DB_GET_RECNO);
5889 ADD_INT(d, DB_JOIN_ITEM);
5890 ADD_INT(d, DB_KEYFIRST);
5891 ADD_INT(d, DB_KEYLAST);
5892 ADD_INT(d, DB_LAST);
5893 ADD_INT(d, DB_NEXT);
5894 ADD_INT(d, DB_NEXT_DUP);
5895 ADD_INT(d, DB_NEXT_NODUP);
5896 ADD_INT(d, DB_NODUPDATA);
5897 ADD_INT(d, DB_NOOVERWRITE);
5898 ADD_INT(d, DB_NOSYNC);
5899 ADD_INT(d, DB_POSITION);
5900 ADD_INT(d, DB_PREV);
5901 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005902#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005903 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005904#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005905 ADD_INT(d, DB_SET);
5906 ADD_INT(d, DB_SET_RANGE);
5907 ADD_INT(d, DB_SET_RECNO);
5908 ADD_INT(d, DB_WRITECURSOR);
5909
5910 ADD_INT(d, DB_OPFLAGS_MASK);
5911 ADD_INT(d, DB_RMW);
5912#if (DBVER >= 33)
5913 ADD_INT(d, DB_DIRTY_READ);
5914 ADD_INT(d, DB_MULTIPLE);
5915 ADD_INT(d, DB_MULTIPLE_KEY);
5916#endif
5917
Gregory P. Smith29602d22006-01-24 09:46:48 +00005918#if (DBVER >= 44)
5919 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5920 ADD_INT(d, DB_READ_COMMITTED);
5921#endif
5922
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005923#if (DBVER >= 33)
5924 ADD_INT(d, DB_DONOTINDEX);
5925#endif
5926
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005927#if (DBVER >= 41)
5928 _addIntToDict(d, "DB_INCOMPLETE", 0);
5929#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005931#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005932 ADD_INT(d, DB_KEYEMPTY);
5933 ADD_INT(d, DB_KEYEXIST);
5934 ADD_INT(d, DB_LOCK_DEADLOCK);
5935 ADD_INT(d, DB_LOCK_NOTGRANTED);
5936 ADD_INT(d, DB_NOSERVER);
5937 ADD_INT(d, DB_NOSERVER_HOME);
5938 ADD_INT(d, DB_NOSERVER_ID);
5939 ADD_INT(d, DB_NOTFOUND);
5940 ADD_INT(d, DB_OLD_VERSION);
5941 ADD_INT(d, DB_RUNRECOVERY);
5942 ADD_INT(d, DB_VERIFY_BAD);
5943#if (DBVER >= 33)
5944 ADD_INT(d, DB_PAGE_NOTFOUND);
5945 ADD_INT(d, DB_SECONDARY_BAD);
5946#endif
5947#if (DBVER >= 40)
5948 ADD_INT(d, DB_STAT_CLEAR);
5949 ADD_INT(d, DB_REGION_INIT);
5950 ADD_INT(d, DB_NOLOCKING);
5951 ADD_INT(d, DB_YIELDCPU);
5952 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5953 ADD_INT(d, DB_NOPANIC);
5954#endif
5955
Gregory P. Smith41631e82003-09-21 00:08:14 +00005956#if (DBVER >= 42)
5957 ADD_INT(d, DB_TIME_NOTGRANTED);
5958 ADD_INT(d, DB_TXN_NOT_DURABLE);
5959 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5960 ADD_INT(d, DB_LOG_AUTOREMOVE);
5961 ADD_INT(d, DB_DIRECT_LOG);
5962 ADD_INT(d, DB_DIRECT_DB);
5963 ADD_INT(d, DB_INIT_REP);
5964 ADD_INT(d, DB_ENCRYPT);
5965 ADD_INT(d, DB_CHKSUM);
5966#endif
5967
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005968#if (DBVER >= 43)
5969 ADD_INT(d, DB_LOG_INMEMORY);
5970 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005971 ADD_INT(d, DB_SEQ_DEC);
5972 ADD_INT(d, DB_SEQ_INC);
5973 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005974#endif
5975
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005976#if (DBVER >= 41)
5977 ADD_INT(d, DB_ENCRYPT_AES);
5978 ADD_INT(d, DB_AUTO_COMMIT);
5979#else
5980 /* allow berkeleydb 4.1 aware apps to run on older versions */
5981 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5982#endif
5983
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984 ADD_INT(d, EINVAL);
5985 ADD_INT(d, EACCES);
5986 ADD_INT(d, ENOSPC);
5987 ADD_INT(d, ENOMEM);
5988 ADD_INT(d, EAGAIN);
5989 ADD_INT(d, EBUSY);
5990 ADD_INT(d, EEXIST);
5991 ADD_INT(d, ENOENT);
5992 ADD_INT(d, EPERM);
5993
Barry Warsaw1baa9822003-03-31 19:51:29 +00005994#if (DBVER >= 40)
5995 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5996 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5997#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005998
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005999 /* The exception name must be correct for pickled exception *
6000 * objects to unpickle properly. */
6001#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6002#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6003#else
6004#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6005#endif
6006
6007 /* All the rest of the exceptions derive only from DBError */
6008#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6009 PyDict_SetItemString(d, #name, name)
6010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006011 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006012 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6013 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014
Gregory P. Smithe9477062005-06-04 06:46:59 +00006015 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6016 * from both DBError and KeyError, since the API only supports
6017 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006018 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006019 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6020 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006021 Py_file_input, d, d);
6022 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006023 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006024 PyDict_DelItemString(d, "KeyError");
6025
6026
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006027#if !INCOMPLETE_IS_WARNING
6028 MAKE_EX(DBIncompleteError);
6029#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006030 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006031 MAKE_EX(DBKeyEmptyError);
6032 MAKE_EX(DBKeyExistError);
6033 MAKE_EX(DBLockDeadlockError);
6034 MAKE_EX(DBLockNotGrantedError);
6035 MAKE_EX(DBOldVersionError);
6036 MAKE_EX(DBRunRecoveryError);
6037 MAKE_EX(DBVerifyBadError);
6038 MAKE_EX(DBNoServerError);
6039 MAKE_EX(DBNoServerHomeError);
6040 MAKE_EX(DBNoServerIDError);
6041#if (DBVER >= 33)
6042 MAKE_EX(DBPageNotFoundError);
6043 MAKE_EX(DBSecondaryBadError);
6044#endif
6045
6046 MAKE_EX(DBInvalidArgError);
6047 MAKE_EX(DBAccessError);
6048 MAKE_EX(DBNoSpaceError);
6049 MAKE_EX(DBNoMemoryError);
6050 MAKE_EX(DBAgainError);
6051 MAKE_EX(DBBusyError);
6052 MAKE_EX(DBFileExistsError);
6053 MAKE_EX(DBNoSuchFileError);
6054 MAKE_EX(DBPermissionsError);
6055
6056#undef MAKE_EX
6057
6058 /* Check for errors */
6059 if (PyErr_Occurred()) {
6060 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006061 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006062 }
6063}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006064
6065/* allow this module to be named _pybsddb so that it can be installed
6066 * and imported on top of python >= 2.3 that includes its own older
6067 * copy of the library named _bsddb without importing the old version. */
6068DL_EXPORT(void) init_pybsddb(void)
6069{
6070 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6071 init_bsddb();
6072}