blob: 9c9a6b3477f9c9efc00626e7a3f8fb5be4d63e8c [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 }
Gregory P. Smith0812de62008-05-17 06:46:39 +0000837 Py_DECREF(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) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000916 /* If the underlying database has been closed, we don't
917 need to do anything. If the environment has been closed
918 we need to leak, as BerkeleyDB will crash trying to access
919 the environment. There was an exception when the
920 user closed the environment even though there still was
921 a database open. */
922 if (self->mydb->db && self->mydb->myenvobj &&
923 !self->mydb->myenvobj->closed)
Gregory P. Smith946de922008-02-03 07:26:23 +0000924 /* test for: open db + no environment or non-closed environment */
925 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
926 !self->mydb->myenvobj->closed))) {
927 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000928 err = self->dbc->c_close(self->dbc);
Gregory P. Smith946de922008-02-03 07:26:23 +0000929 MYDB_END_ALLOW_THREADS;
930 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 }
933 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935}
936
937
938static DBEnvObject*
939newDBEnvObject(int flags)
940{
941 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000942 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943 if (self == NULL)
944 return NULL;
945
946 self->closed = 1;
947 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000948 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
949 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000950#ifdef HAVE_WEAKREF
951 self->in_weakreflist = NULL;
952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953
954 MYDB_BEGIN_ALLOW_THREADS;
955 err = db_env_create(&self->db_env, flags);
956 MYDB_END_ALLOW_THREADS;
957 if (makeDBError(err)) {
Gregory P. Smith0812de62008-05-17 06:46:39 +0000958 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000959 self = NULL;
960 }
961 else {
962 self->db_env->set_errcall(self->db_env, _db_errorCallback);
963 }
964 return self;
965}
966
967
968static void
969DBEnv_dealloc(DBEnvObject* self)
970{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000971#ifdef HAVE_WEAKREF
972 if (self->in_weakreflist != NULL) {
973 PyObject_ClearWeakRefs((PyObject *) self);
974 }
975#endif
976
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000977 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 MYDB_BEGIN_ALLOW_THREADS;
979 self->db_env->close(self->db_env, 0);
980 MYDB_END_ALLOW_THREADS;
981 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983}
984
985
986static DBTxnObject*
987newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
988{
989 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000990 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 if (self == NULL)
992 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000993 Py_INCREF(myenv);
994 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000995#ifdef HAVE_WEAKREF
996 self->in_weakreflist = NULL;
997#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000998
999 MYDB_BEGIN_ALLOW_THREADS;
1000#if (DBVER >= 40)
1001 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1002#else
1003 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1004#endif
1005 MYDB_END_ALLOW_THREADS;
1006 if (makeDBError(err)) {
Gregory P. Smith0812de62008-05-17 06:46:39 +00001007 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001008 self = NULL;
1009 }
1010 return self;
1011}
1012
1013
1014static void
1015DBTxn_dealloc(DBTxnObject* self)
1016{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001017#ifdef HAVE_WEAKREF
1018 if (self->in_weakreflist != NULL) {
1019 PyObject_ClearWeakRefs((PyObject *) self);
1020 }
1021#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022
Gregory P. Smith31c50652004-06-28 01:20:40 +00001023#ifdef HAVE_WARNINGS
1024 if (self->txn) {
1025 /* it hasn't been finalized, abort it! */
1026 MYDB_BEGIN_ALLOW_THREADS;
1027#if (DBVER >= 40)
1028 self->txn->abort(self->txn);
1029#else
1030 txn_abort(self->txn);
1031#endif
1032 MYDB_END_ALLOW_THREADS;
1033 PyErr_Warn(PyExc_RuntimeWarning,
1034 "DBTxn aborted in destructor. No prior commit() or abort().");
1035 }
1036#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037
Neal Norwitz62a21122006-01-25 05:21:55 +00001038 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001039 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040}
1041
1042
1043static DBLockObject*
1044newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1045 db_lockmode_t lock_mode, int flags)
1046{
1047 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001048 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001049 if (self == NULL)
1050 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001051#ifdef HAVE_WEAKREF
1052 self->in_weakreflist = NULL;
1053#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001054
1055 MYDB_BEGIN_ALLOW_THREADS;
1056#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001057 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1058 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001059#else
1060 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1061#endif
1062 MYDB_END_ALLOW_THREADS;
1063 if (makeDBError(err)) {
Gregory P. Smith0812de62008-05-17 06:46:39 +00001064 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065 self = NULL;
1066 }
1067
1068 return self;
1069}
1070
1071
1072static void
1073DBLock_dealloc(DBLockObject* self)
1074{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001075#ifdef HAVE_WEAKREF
1076 if (self->in_weakreflist != NULL) {
1077 PyObject_ClearWeakRefs((PyObject *) self);
1078 }
1079#endif
1080 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001081
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001082 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001083}
1084
1085
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001086#if (DBVER >= 43)
1087static DBSequenceObject*
1088newDBSequenceObject(DBObject* mydb, int flags)
1089{
1090 int err;
1091 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1092 if (self == NULL)
1093 return NULL;
1094 Py_INCREF(mydb);
1095 self->mydb = mydb;
1096#ifdef HAVE_WEAKREF
1097 self->in_weakreflist = NULL;
1098#endif
1099
1100
1101 MYDB_BEGIN_ALLOW_THREADS;
1102 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1103 MYDB_END_ALLOW_THREADS;
1104 if (makeDBError(err)) {
Gregory P. Smith0812de62008-05-17 06:46:39 +00001105 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001106 self = NULL;
1107 }
1108
1109 return self;
1110}
1111
1112
1113static void
1114DBSequence_dealloc(DBSequenceObject* self)
1115{
1116#ifdef HAVE_WEAKREF
1117 if (self->in_weakreflist != NULL) {
1118 PyObject_ClearWeakRefs((PyObject *) self);
1119 }
1120#endif
1121
1122 Py_DECREF(self->mydb);
1123 PyObject_Del(self);
1124}
1125#endif
1126
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127/* --------------------------------------------------------------------- */
1128/* DB methods */
1129
1130static PyObject*
1131DB_append(DBObject* self, PyObject* args)
1132{
1133 PyObject* txnobj = NULL;
1134 PyObject* dataobj;
1135 db_recno_t recno;
1136 DBT key, data;
1137 DB_TXN *txn = NULL;
1138
Georg Brandl96a8c392006-05-29 21:04:52 +00001139 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001140 return NULL;
1141
1142 CHECK_DB_NOT_CLOSED(self);
1143
1144 /* make a dummy key out of a recno */
1145 recno = 0;
1146 CLEAR_DBT(key);
1147 key.data = &recno;
1148 key.size = sizeof(recno);
1149 key.ulen = key.size;
1150 key.flags = DB_DBT_USERMEM;
1151
1152 if (!make_dbt(dataobj, &data)) return NULL;
1153 if (!checkTxnObj(txnobj, &txn)) return NULL;
1154
1155 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1156 return NULL;
1157
1158 return PyInt_FromLong(recno);
1159}
1160
1161
1162#if (DBVER >= 33)
1163
1164static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001165_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1166 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001167{
1168 int retval = DB_DONOTINDEX;
1169 DBObject* secondaryDB = (DBObject*)db->app_private;
1170 PyObject* callback = secondaryDB->associateCallback;
1171 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001173 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174
1175
1176 if (callback != NULL) {
1177 MYDB_BEGIN_BLOCK_THREADS;
1178
Thomas Woutersb3153832006-03-08 01:47:19 +00001179 if (type == DB_RECNO || type == DB_QUEUE)
1180 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1181 priData->data, priData->size);
1182 else
1183 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1184 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001185 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001186 result = PyEval_CallObject(callback, args);
1187 }
1188 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001189 PyErr_Print();
1190 }
1191 else if (result == Py_None) {
1192 retval = DB_DONOTINDEX;
1193 }
1194 else if (PyInt_Check(result)) {
1195 retval = PyInt_AsLong(result);
1196 }
1197 else if (PyString_Check(result)) {
1198 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001199 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001200
1201 CLEAR_DBT(*secKey);
1202#if PYTHON_API_VERSION <= 1007
1203 /* 1.5 compatibility */
1204 size = PyString_Size(result);
1205 data = PyString_AsString(result);
1206#else
1207 PyString_AsStringAndSize(result, &data, &size);
1208#endif
1209 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1210 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001211 if (secKey->data) {
1212 memcpy(secKey->data, data, size);
1213 secKey->size = size;
1214 retval = 0;
1215 }
1216 else {
1217 PyErr_SetString(PyExc_MemoryError,
1218 "malloc failed in _db_associateCallback");
1219 PyErr_Print();
1220 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001221 }
1222 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001223 PyErr_SetString(
1224 PyExc_TypeError,
1225 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001226 PyErr_Print();
1227 }
1228
Thomas Woutersb3153832006-03-08 01:47:19 +00001229 Py_XDECREF(args);
1230 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001231
1232 MYDB_END_BLOCK_THREADS;
1233 }
1234 return retval;
1235}
1236
1237
1238static PyObject*
1239DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1240{
1241 int err, flags=0;
1242 DBObject* secondaryDB;
1243 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001244#if (DBVER >= 41)
1245 PyObject *txnobj = NULL;
1246 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001247 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001248 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001249#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001250 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001251#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001252
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001253#if (DBVER >= 41)
1254 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1255 &secondaryDB, &callback, &flags,
1256 &txnobj)) {
1257#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001259 &secondaryDB, &callback, &flags)) {
1260#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001261 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001262 }
1263
1264#if (DBVER >= 41)
1265 if (!checkTxnObj(txnobj, &txn)) return NULL;
1266#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001267
1268 CHECK_DB_NOT_CLOSED(self);
1269 if (!DBObject_Check(secondaryDB)) {
1270 makeTypeError("DB", (PyObject*)secondaryDB);
1271 return NULL;
1272 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001273 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001274 if (callback == Py_None) {
1275 callback = NULL;
1276 }
1277 else if (!PyCallable_Check(callback)) {
1278 makeTypeError("Callable", callback);
1279 return NULL;
1280 }
1281
1282 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001283 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001284 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 secondaryDB->associateCallback = callback;
1286 secondaryDB->primaryDBType = _DB_get_type(self);
1287
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001288 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1289 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1290 * The global interepreter lock is not initialized until the first
1291 * thread is created using thread.start_new_thread() or fork() is
1292 * called. that would cause the ALLOW_THREADS here to segfault due
1293 * to a null pointer reference if no threads or child processes
1294 * have been created. This works around that and is a no-op if
1295 * threads have already been initialized.
1296 * (see pybsddb-users mailing list post on 2002-08-07)
1297 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001298#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001299 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001300#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001301 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001302#if (DBVER >= 41)
1303 err = self->db->associate(self->db,
1304 txn,
1305 secondaryDB->db,
1306 _db_associateCallback,
1307 flags);
1308#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001309 err = self->db->associate(self->db,
1310 secondaryDB->db,
1311 _db_associateCallback,
1312 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001313#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 MYDB_END_ALLOW_THREADS;
1315
1316 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001317 Py_XDECREF(secondaryDB->associateCallback);
1318 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319 secondaryDB->primaryDBType = 0;
1320 }
1321
1322 RETURN_IF_ERR();
1323 RETURN_NONE();
1324}
1325
1326
1327#endif
1328
1329
1330static PyObject*
1331DB_close(DBObject* self, PyObject* args)
1332{
1333 int err, flags=0;
1334 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1335 return NULL;
1336 if (self->db != NULL) {
1337 if (self->myenvobj)
1338 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001339 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 self->db = NULL;
1341 RETURN_IF_ERR();
1342 }
1343 RETURN_NONE();
1344}
1345
1346
1347#if (DBVER >= 32)
1348static PyObject*
1349_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1350{
1351 int err, flags=0, type;
1352 PyObject* txnobj = NULL;
1353 PyObject* retval = NULL;
1354 DBT key, data;
1355 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001356 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001357
1358 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1359 &txnobj, &flags))
1360 return NULL;
1361
1362 CHECK_DB_NOT_CLOSED(self);
1363 type = _DB_get_type(self);
1364 if (type == -1)
1365 return NULL;
1366 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001367 PyErr_SetString(PyExc_TypeError,
1368 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369 return NULL;
1370 }
1371 if (!checkTxnObj(txnobj, &txn))
1372 return NULL;
1373
1374 CLEAR_DBT(key);
1375 CLEAR_DBT(data);
1376 if (CHECK_DBFLAG(self, DB_THREAD)) {
1377 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1378 data.flags = DB_DBT_MALLOC;
1379 key.flags = DB_DBT_MALLOC;
1380 }
1381
1382 MYDB_BEGIN_ALLOW_THREADS;
1383 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1384 MYDB_END_ALLOW_THREADS;
1385
Gregory P. Smithe9477062005-06-04 06:46:59 +00001386 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1387 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001388 err = 0;
1389 Py_INCREF(Py_None);
1390 retval = Py_None;
1391 }
1392 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001393 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1394 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001395 FREE_DBT(key);
1396 FREE_DBT(data);
1397 }
1398
1399 RETURN_IF_ERR();
1400 return retval;
1401}
1402
1403static PyObject*
1404DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1405{
1406 return _DB_consume(self, args, kwargs, DB_CONSUME);
1407}
1408
1409static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001410DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1411 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412{
1413 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1414}
1415#endif
1416
1417
1418
1419static PyObject*
1420DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1421{
1422 int err, flags=0;
1423 DBC* dbc;
1424 PyObject* txnobj = NULL;
1425 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001426 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1429 &txnobj, &flags))
1430 return NULL;
1431 CHECK_DB_NOT_CLOSED(self);
1432 if (!checkTxnObj(txnobj, &txn))
1433 return NULL;
1434
1435 MYDB_BEGIN_ALLOW_THREADS;
1436 err = self->db->cursor(self->db, txn, &dbc, flags);
1437 MYDB_END_ALLOW_THREADS;
1438 RETURN_IF_ERR();
1439 return (PyObject*) newDBCursorObject(dbc, self);
1440}
1441
1442
1443static PyObject*
1444DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1445{
1446 PyObject* txnobj = NULL;
1447 int flags = 0;
1448 PyObject* keyobj;
1449 DBT key;
1450 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001451 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001452
1453 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1454 &keyobj, &txnobj, &flags))
1455 return NULL;
1456 CHECK_DB_NOT_CLOSED(self);
1457 if (!make_key_dbt(self, keyobj, &key, NULL))
1458 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001459 if (!checkTxnObj(txnobj, &txn)) {
1460 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001462 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001463
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001464 if (-1 == _DB_delete(self, txn, &key, 0)) {
1465 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001467 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001468
1469 FREE_DBT(key);
1470 RETURN_NONE();
1471}
1472
1473
1474static PyObject*
1475DB_fd(DBObject* self, PyObject* args)
1476{
1477 int err, the_fd;
1478
1479 if (!PyArg_ParseTuple(args,":fd"))
1480 return NULL;
1481 CHECK_DB_NOT_CLOSED(self);
1482
1483 MYDB_BEGIN_ALLOW_THREADS;
1484 err = self->db->fd(self->db, &the_fd);
1485 MYDB_END_ALLOW_THREADS;
1486 RETURN_IF_ERR();
1487 return PyInt_FromLong(the_fd);
1488}
1489
1490
1491static PyObject*
1492DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1493{
1494 int err, flags=0;
1495 PyObject* txnobj = NULL;
1496 PyObject* keyobj;
1497 PyObject* dfltobj = NULL;
1498 PyObject* retval = NULL;
1499 int dlen = -1;
1500 int doff = -1;
1501 DBT key, data;
1502 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001503 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001504 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505
1506 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001507 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1508 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001509 return NULL;
1510
1511 CHECK_DB_NOT_CLOSED(self);
1512 if (!make_key_dbt(self, keyobj, &key, &flags))
1513 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001514 if (!checkTxnObj(txnobj, &txn)) {
1515 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001516 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001517 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518
1519 CLEAR_DBT(data);
1520 if (CHECK_DBFLAG(self, DB_THREAD)) {
1521 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1522 data.flags = DB_DBT_MALLOC;
1523 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001524 if (!add_partial_dbt(&data, dlen, doff)) {
1525 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001526 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001527 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528
1529 MYDB_BEGIN_ALLOW_THREADS;
1530 err = self->db->get(self->db, txn, &key, &data, flags);
1531 MYDB_END_ALLOW_THREADS;
1532
Gregory P. Smithe9477062005-06-04 06:46:59 +00001533 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 err = 0;
1535 Py_INCREF(dfltobj);
1536 retval = dfltobj;
1537 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001538 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1539 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001540 err = 0;
1541 Py_INCREF(Py_None);
1542 retval = Py_None;
1543 }
1544 else if (!err) {
1545 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001546 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1547 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001548 else /* return just the data */
1549 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550 FREE_DBT(data);
1551 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001552 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001553
1554 RETURN_IF_ERR();
1555 return retval;
1556}
1557
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001558#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001559static PyObject*
1560DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1561{
1562 int err, flags=0;
1563 PyObject* txnobj = NULL;
1564 PyObject* keyobj;
1565 PyObject* dfltobj = NULL;
1566 PyObject* retval = NULL;
1567 int dlen = -1;
1568 int doff = -1;
1569 DBT key, pkey, data;
1570 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001571 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001572 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001573
1574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1575 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1576 &doff))
1577 return NULL;
1578
1579 CHECK_DB_NOT_CLOSED(self);
1580 if (!make_key_dbt(self, keyobj, &key, &flags))
1581 return NULL;
1582 if (!checkTxnObj(txnobj, &txn)) {
1583 FREE_DBT(key);
1584 return NULL;
1585 }
1586
1587 CLEAR_DBT(data);
1588 if (CHECK_DBFLAG(self, DB_THREAD)) {
1589 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1590 data.flags = DB_DBT_MALLOC;
1591 }
1592 if (!add_partial_dbt(&data, dlen, doff)) {
1593 FREE_DBT(key);
1594 return NULL;
1595 }
1596
1597 CLEAR_DBT(pkey);
1598 pkey.flags = DB_DBT_MALLOC;
1599
1600 MYDB_BEGIN_ALLOW_THREADS;
1601 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1602 MYDB_END_ALLOW_THREADS;
1603
Gregory P. Smithe9477062005-06-04 06:46:59 +00001604 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001605 err = 0;
1606 Py_INCREF(dfltobj);
1607 retval = dfltobj;
1608 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001609 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1610 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001611 err = 0;
1612 Py_INCREF(Py_None);
1613 retval = Py_None;
1614 }
1615 else if (!err) {
1616 PyObject *pkeyObj;
1617 PyObject *dataObj;
1618 dataObj = PyString_FromStringAndSize(data.data, data.size);
1619
1620 if (self->primaryDBType == DB_RECNO ||
1621 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001622 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001623 else
1624 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1625
1626 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1627 {
1628 PyObject *keyObj;
1629 int type = _DB_get_type(self);
1630 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001631 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632 else
1633 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001634#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001635 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001636#else
1637 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1638#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001639 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001640 }
1641 else /* return just the pkey and data */
1642 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001643#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001644 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001645#else
1646 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1647#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001648 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001649 Py_DECREF(dataObj);
1650 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001651 FREE_DBT(pkey);
1652 FREE_DBT(data);
1653 }
1654 FREE_DBT(key);
1655
1656 RETURN_IF_ERR();
1657 return retval;
1658}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001659#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661
1662/* Return size of entry */
1663static PyObject*
1664DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1665{
1666 int err, flags=0;
1667 PyObject* txnobj = NULL;
1668 PyObject* keyobj;
1669 PyObject* retval = NULL;
1670 DBT key, data;
1671 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001672 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001673
1674 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1675 &keyobj, &txnobj))
1676 return NULL;
1677 CHECK_DB_NOT_CLOSED(self);
1678 if (!make_key_dbt(self, keyobj, &key, &flags))
1679 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001680 if (!checkTxnObj(txnobj, &txn)) {
1681 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001682 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001683 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001684 CLEAR_DBT(data);
1685
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001686 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1687 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001688 data.flags = DB_DBT_USERMEM;
1689 data.ulen = 0;
1690 MYDB_BEGIN_ALLOW_THREADS;
1691 err = self->db->get(self->db, txn, &key, &data, flags);
1692 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001693 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001694 retval = PyInt_FromLong((long)data.size);
1695 err = 0;
1696 }
1697
1698 FREE_DBT(key);
1699 FREE_DBT(data);
1700 RETURN_IF_ERR();
1701 return retval;
1702}
1703
1704
1705static PyObject*
1706DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1707{
1708 int err, flags=0;
1709 PyObject* txnobj = NULL;
1710 PyObject* keyobj;
1711 PyObject* dataobj;
1712 PyObject* retval = NULL;
1713 DBT key, data;
Neal Norwitzdf738022007-05-20 02:14:48 +00001714 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001716 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717
1718
1719 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1720 &keyobj, &dataobj, &txnobj, &flags))
1721 return NULL;
1722
1723 CHECK_DB_NOT_CLOSED(self);
1724 if (!make_key_dbt(self, keyobj, &key, NULL))
1725 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001726 if ( !make_dbt(dataobj, &data) ||
1727 !checkTxnObj(txnobj, &txn) )
1728 {
1729 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001730 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001731 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732
1733 flags |= DB_GET_BOTH;
Neal Norwitzdf738022007-05-20 02:14:48 +00001734 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001735
1736 if (CHECK_DBFLAG(self, DB_THREAD)) {
1737 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitzdf738022007-05-20 02:14:48 +00001738 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001739 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001740 }
1741
1742 MYDB_BEGIN_ALLOW_THREADS;
1743 err = self->db->get(self->db, txn, &key, &data, flags);
1744 MYDB_END_ALLOW_THREADS;
1745
Gregory P. Smithe9477062005-06-04 06:46:59 +00001746 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1747 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001748 err = 0;
1749 Py_INCREF(Py_None);
1750 retval = Py_None;
1751 }
1752 else if (!err) {
Neal Norwitzdf738022007-05-20 02:14:48 +00001753 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001754 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitzdf738022007-05-20 02:14:48 +00001755
1756 /* Even though the flags require DB_DBT_MALLOC, data is not always
1757 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1758 if (data.data != orig_data)
1759 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001760 }
1761
1762 FREE_DBT(key);
1763 RETURN_IF_ERR();
1764 return retval;
1765}
1766
1767
1768static PyObject*
1769DB_get_byteswapped(DBObject* self, PyObject* args)
1770{
1771#if (DBVER >= 33)
1772 int err = 0;
1773#endif
1774 int retval = -1;
1775
1776 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1777 return NULL;
1778 CHECK_DB_NOT_CLOSED(self);
1779
1780#if (DBVER >= 33)
1781 MYDB_BEGIN_ALLOW_THREADS;
1782 err = self->db->get_byteswapped(self->db, &retval);
1783 MYDB_END_ALLOW_THREADS;
1784 RETURN_IF_ERR();
1785#else
1786 MYDB_BEGIN_ALLOW_THREADS;
1787 retval = self->db->get_byteswapped(self->db);
1788 MYDB_END_ALLOW_THREADS;
1789#endif
1790 return PyInt_FromLong(retval);
1791}
1792
1793
1794static PyObject*
1795DB_get_type(DBObject* self, PyObject* args)
1796{
1797 int type;
1798
1799 if (!PyArg_ParseTuple(args,":get_type"))
1800 return NULL;
1801 CHECK_DB_NOT_CLOSED(self);
1802
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001803 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001804 if (type == -1)
1805 return NULL;
1806 return PyInt_FromLong(type);
1807}
1808
1809
1810static PyObject*
1811DB_join(DBObject* self, PyObject* args)
1812{
1813 int err, flags=0;
1814 int length, x;
1815 PyObject* cursorsObj;
1816 DBC** cursors;
1817 DBC* dbc;
1818
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001819 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1820 return NULL;
1821
1822 CHECK_DB_NOT_CLOSED(self);
1823
1824 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001825 PyErr_SetString(PyExc_TypeError,
1826 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001827 return NULL;
1828 }
1829
1830 length = PyObject_Length(cursorsObj);
1831 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001832 if (!cursors) {
1833 PyErr_NoMemory();
1834 return NULL;
1835 }
1836
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001837 cursors[length] = NULL;
1838 for (x=0; x<length; x++) {
1839 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001840 if (item == NULL) {
1841 free(cursors);
1842 return NULL;
1843 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001845 PyErr_SetString(PyExc_TypeError,
1846 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001847 free(cursors);
1848 return NULL;
1849 }
1850 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001851 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 }
1853
1854 MYDB_BEGIN_ALLOW_THREADS;
1855 err = self->db->join(self->db, cursors, &dbc, flags);
1856 MYDB_END_ALLOW_THREADS;
1857 free(cursors);
1858 RETURN_IF_ERR();
1859
Gregory P. Smith7441e652003-11-03 21:35:31 +00001860 /* FIXME: this is a buggy interface. The returned cursor
1861 contains internal references to the passed in cursors
1862 but does not hold python references to them or prevent
1863 them from being closed prematurely. This can cause
1864 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 return (PyObject*) newDBCursorObject(dbc, self);
1866}
1867
1868
1869static PyObject*
1870DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1871{
1872 int err, flags=0;
1873 PyObject* txnobj = NULL;
1874 PyObject* keyobj;
1875 DBT key;
1876 DB_TXN *txn = NULL;
1877 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001878 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001879
1880 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1881 &keyobj, &txnobj, &flags))
1882 return NULL;
1883 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001884 if (!make_dbt(keyobj, &key))
1885 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001886 return NULL;
1887 if (!checkTxnObj(txnobj, &txn))
1888 return NULL;
1889
1890 MYDB_BEGIN_ALLOW_THREADS;
1891 err = self->db->key_range(self->db, txn, &key, &range, flags);
1892 MYDB_END_ALLOW_THREADS;
1893
1894 RETURN_IF_ERR();
1895 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1896}
1897
1898
1899static PyObject*
1900DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1901{
1902 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1903 char* filename = NULL;
1904 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001905#if (DBVER >= 41)
1906 PyObject *txnobj = NULL;
1907 DB_TXN *txn = NULL;
1908 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001909 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001910 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1911 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001912 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001913 "filename", "dbtype", "flags", "mode", "txn", NULL};
1914#else
1915 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001916 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001917 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1918 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001919 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001920 "filename", "dbtype", "flags", "mode", NULL};
1921#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001922
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001923#if (DBVER >= 41)
1924 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1925 &filename, &dbname, &type, &flags, &mode,
1926 &txnobj))
1927#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001929 &filename, &dbname, &type, &flags,
1930 &mode))
1931#endif
1932 {
1933 PyErr_Clear();
1934 type = DB_UNKNOWN; flags = 0; mode = 0660;
1935 filename = NULL; dbname = NULL;
1936#if (DBVER >= 41)
1937 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1938 kwnames_basic,
1939 &filename, &type, &flags, &mode,
1940 &txnobj))
1941 return NULL;
1942#else
1943 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1944 kwnames_basic,
1945 &filename, &type, &flags, &mode))
1946 return NULL;
1947#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 }
1949
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001950#if (DBVER >= 41)
1951 if (!checkTxnObj(txnobj, &txn)) return NULL;
1952#endif
1953
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001955 PyObject *t = Py_BuildValue("(is)", 0,
1956 "Cannot call open() twice for DB object");
1957 PyErr_SetObject(DBError, t);
1958 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001959 return NULL;
1960 }
1961
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001962#if 0 && (DBVER >= 41)
1963 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1964 && (self->myenvobj->flags & DB_INIT_TXN))
1965 {
1966 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1967 * explicitly passed) but we are in a transaction ready environment:
1968 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1969 * to work on BerkeleyDB 4.1 without needing to modify their
1970 * DBEnv or DB open calls.
1971 * TODO make this behaviour of the library configurable.
1972 */
1973 flags |= DB_AUTO_COMMIT;
1974 }
1975#endif
1976
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001977 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001978#if (DBVER >= 41)
1979 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1980#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001981 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001982#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 MYDB_END_ALLOW_THREADS;
1984 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001985 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001986 self->db = NULL;
1987 return NULL;
1988 }
1989
1990 self->flags = flags;
1991 RETURN_NONE();
1992}
1993
1994
1995static PyObject*
1996DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1997{
1998 int flags=0;
1999 PyObject* txnobj = NULL;
2000 int dlen = -1;
2001 int doff = -1;
2002 PyObject* keyobj, *dataobj, *retval;
2003 DBT key, data;
2004 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002005 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002006 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002007
2008 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2009 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2010 return NULL;
2011
2012 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002013 if (!make_key_dbt(self, keyobj, &key, NULL))
2014 return NULL;
2015 if ( !make_dbt(dataobj, &data) ||
2016 !add_partial_dbt(&data, dlen, doff) ||
2017 !checkTxnObj(txnobj, &txn) )
2018 {
2019 FREE_DBT(key);
2020 return NULL;
2021 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002022
2023 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2024 FREE_DBT(key);
2025 return NULL;
2026 }
2027
2028 if (flags & DB_APPEND)
2029 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2030 else {
2031 retval = Py_None;
2032 Py_INCREF(retval);
2033 }
2034 FREE_DBT(key);
2035 return retval;
2036}
2037
2038
2039
2040static PyObject*
2041DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2042{
2043 char* filename;
2044 char* database = NULL;
2045 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002046 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002047
2048 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2049 &filename, &database, &flags))
2050 return NULL;
2051 CHECK_DB_NOT_CLOSED(self);
2052
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002054 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002055 RETURN_IF_ERR();
2056 RETURN_NONE();
2057}
2058
2059
2060
2061static PyObject*
2062DB_rename(DBObject* self, PyObject* args)
2063{
2064 char* filename;
2065 char* database;
2066 char* newname;
2067 int err, flags=0;
2068
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002069 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2070 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002071 return NULL;
2072 CHECK_DB_NOT_CLOSED(self);
2073
2074 MYDB_BEGIN_ALLOW_THREADS;
2075 err = self->db->rename(self->db, filename, database, newname, flags);
2076 MYDB_END_ALLOW_THREADS;
2077 RETURN_IF_ERR();
2078 RETURN_NONE();
2079}
2080
2081
2082static PyObject*
2083DB_set_bt_minkey(DBObject* self, PyObject* args)
2084{
2085 int err, minkey;
2086
2087 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2088 return NULL;
2089 CHECK_DB_NOT_CLOSED(self);
2090
2091 MYDB_BEGIN_ALLOW_THREADS;
2092 err = self->db->set_bt_minkey(self->db, minkey);
2093 MYDB_END_ALLOW_THREADS;
2094 RETURN_IF_ERR();
2095 RETURN_NONE();
2096}
2097
Neal Norwitz84562352005-10-20 04:30:15 +00002098#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002099static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002100_default_cmp(const DBT *leftKey,
2101 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002102{
2103 int res;
2104 int lsize = leftKey->size, rsize = rightKey->size;
2105
Georg Brandlef1701f2006-03-07 14:57:48 +00002106 res = memcmp(leftKey->data, rightKey->data,
2107 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108
2109 if (res == 0) {
2110 if (lsize < rsize) {
2111 res = -1;
2112 }
2113 else if (lsize > rsize) {
2114 res = 1;
2115 }
2116 }
2117 return res;
2118}
2119
2120static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002121_db_compareCallback(DB* db,
2122 const DBT *leftKey,
2123 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002124{
2125 int res = 0;
2126 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002127 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002129
2130 if (self == NULL || self->btCompareCallback == NULL) {
2131 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 PyErr_SetString(PyExc_TypeError,
2133 (self == 0
2134 ? "DB_bt_compare db is NULL."
2135 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002136 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002137 PyErr_Print();
2138 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002139 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002140 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002141 MYDB_BEGIN_BLOCK_THREADS;
2142
Thomas Woutersb3153832006-03-08 01:47:19 +00002143 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2144 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002146 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002151 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002152 PyErr_Print();
2153 res = _default_cmp(leftKey, rightKey);
2154 } else if (PyInt_Check(result)) {
2155 res = PyInt_AsLong(result);
2156 } else {
2157 PyErr_SetString(PyExc_TypeError,
2158 "DB_bt_compare callback MUST return an int.");
2159 /* we're in a callback within the DB code, we can't raise */
2160 PyErr_Print();
2161 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162 }
2163
Thomas Woutersb3153832006-03-08 01:47:19 +00002164 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002165 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166
2167 MYDB_END_BLOCK_THREADS;
2168 }
2169 return res;
2170}
2171
2172static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002173DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002174{
2175 int err;
2176 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002177 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178
Georg Brandlef1701f2006-03-07 14:57:48 +00002179 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002180 return NULL;
2181
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183
Georg Brandlef1701f2006-03-07 14:57:48 +00002184 if (!PyCallable_Check(comparator)) {
2185 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002186 return NULL;
2187 }
2188
2189 /*
2190 * Perform a test call of the comparator function with two empty
2191 * string objects here. verify that it returns an int (0).
2192 * err if not.
2193 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002194 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002195 result = PyEval_CallObject(comparator, tuple);
2196 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002197 if (result == NULL)
2198 return NULL;
2199 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002200 PyErr_SetString(PyExc_TypeError,
2201 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002202 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002203 } else if (PyInt_AsLong(result) != 0) {
2204 PyErr_SetString(PyExc_TypeError,
2205 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002206 return NULL;
2207 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002208 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002209
2210 /* We don't accept multiple set_bt_compare operations, in order to
2211 * simplify the code. This would have no real use, as one cannot
2212 * change the function once the db is opened anyway */
2213 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002214 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002215 return NULL;
2216 }
2217
Georg Brandlef1701f2006-03-07 14:57:48 +00002218 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219 self->btCompareCallback = comparator;
2220
2221 /* This is to workaround a problem with un-initialized threads (see
2222 comment in DB_associate) */
2223#ifdef WITH_THREAD
2224 PyEval_InitThreads();
2225#endif
2226
Thomas Woutersb3153832006-03-08 01:47:19 +00002227 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002228
2229 if (err) {
2230 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002231 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002232 self->btCompareCallback = NULL;
2233 }
2234
Georg Brandlef1701f2006-03-07 14:57:48 +00002235 RETURN_IF_ERR();
2236 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002237}
Neal Norwitz84562352005-10-20 04:30:15 +00002238#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002239
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002240
2241static PyObject*
2242DB_set_cachesize(DBObject* self, PyObject* args)
2243{
2244 int err;
2245 int gbytes = 0, bytes = 0, ncache = 0;
2246
2247 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2248 &gbytes,&bytes,&ncache))
2249 return NULL;
2250 CHECK_DB_NOT_CLOSED(self);
2251
2252 MYDB_BEGIN_ALLOW_THREADS;
2253 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2254 MYDB_END_ALLOW_THREADS;
2255 RETURN_IF_ERR();
2256 RETURN_NONE();
2257}
2258
2259
2260static PyObject*
2261DB_set_flags(DBObject* self, PyObject* args)
2262{
2263 int err, flags;
2264
2265 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2266 return NULL;
2267 CHECK_DB_NOT_CLOSED(self);
2268
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->set_flags(self->db, flags);
2271 MYDB_END_ALLOW_THREADS;
2272 RETURN_IF_ERR();
2273
2274 self->setflags |= flags;
2275 RETURN_NONE();
2276}
2277
2278
2279static PyObject*
2280DB_set_h_ffactor(DBObject* self, PyObject* args)
2281{
2282 int err, ffactor;
2283
2284 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2285 return NULL;
2286 CHECK_DB_NOT_CLOSED(self);
2287
2288 MYDB_BEGIN_ALLOW_THREADS;
2289 err = self->db->set_h_ffactor(self->db, ffactor);
2290 MYDB_END_ALLOW_THREADS;
2291 RETURN_IF_ERR();
2292 RETURN_NONE();
2293}
2294
2295
2296static PyObject*
2297DB_set_h_nelem(DBObject* self, PyObject* args)
2298{
2299 int err, nelem;
2300
2301 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2302 return NULL;
2303 CHECK_DB_NOT_CLOSED(self);
2304
2305 MYDB_BEGIN_ALLOW_THREADS;
2306 err = self->db->set_h_nelem(self->db, nelem);
2307 MYDB_END_ALLOW_THREADS;
2308 RETURN_IF_ERR();
2309 RETURN_NONE();
2310}
2311
2312
2313static PyObject*
2314DB_set_lorder(DBObject* self, PyObject* args)
2315{
2316 int err, lorder;
2317
2318 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2319 return NULL;
2320 CHECK_DB_NOT_CLOSED(self);
2321
2322 MYDB_BEGIN_ALLOW_THREADS;
2323 err = self->db->set_lorder(self->db, lorder);
2324 MYDB_END_ALLOW_THREADS;
2325 RETURN_IF_ERR();
2326 RETURN_NONE();
2327}
2328
2329
2330static PyObject*
2331DB_set_pagesize(DBObject* self, PyObject* args)
2332{
2333 int err, pagesize;
2334
2335 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2336 return NULL;
2337 CHECK_DB_NOT_CLOSED(self);
2338
2339 MYDB_BEGIN_ALLOW_THREADS;
2340 err = self->db->set_pagesize(self->db, pagesize);
2341 MYDB_END_ALLOW_THREADS;
2342 RETURN_IF_ERR();
2343 RETURN_NONE();
2344}
2345
2346
2347static PyObject*
2348DB_set_re_delim(DBObject* self, PyObject* args)
2349{
2350 int err;
2351 char delim;
2352
2353 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2354 PyErr_Clear();
2355 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2356 return NULL;
2357 }
2358
2359 CHECK_DB_NOT_CLOSED(self);
2360
2361 MYDB_BEGIN_ALLOW_THREADS;
2362 err = self->db->set_re_delim(self->db, delim);
2363 MYDB_END_ALLOW_THREADS;
2364 RETURN_IF_ERR();
2365 RETURN_NONE();
2366}
2367
2368static PyObject*
2369DB_set_re_len(DBObject* self, PyObject* args)
2370{
2371 int err, len;
2372
2373 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2374 return NULL;
2375 CHECK_DB_NOT_CLOSED(self);
2376
2377 MYDB_BEGIN_ALLOW_THREADS;
2378 err = self->db->set_re_len(self->db, len);
2379 MYDB_END_ALLOW_THREADS;
2380 RETURN_IF_ERR();
2381 RETURN_NONE();
2382}
2383
2384
2385static PyObject*
2386DB_set_re_pad(DBObject* self, PyObject* args)
2387{
2388 int err;
2389 char pad;
2390
2391 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2392 PyErr_Clear();
2393 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2394 return NULL;
2395 }
2396 CHECK_DB_NOT_CLOSED(self);
2397
2398 MYDB_BEGIN_ALLOW_THREADS;
2399 err = self->db->set_re_pad(self->db, pad);
2400 MYDB_END_ALLOW_THREADS;
2401 RETURN_IF_ERR();
2402 RETURN_NONE();
2403}
2404
2405
2406static PyObject*
2407DB_set_re_source(DBObject* self, PyObject* args)
2408{
2409 int err;
2410 char *re_source;
2411
2412 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2413 return NULL;
2414 CHECK_DB_NOT_CLOSED(self);
2415
2416 MYDB_BEGIN_ALLOW_THREADS;
2417 err = self->db->set_re_source(self->db, re_source);
2418 MYDB_END_ALLOW_THREADS;
2419 RETURN_IF_ERR();
2420 RETURN_NONE();
2421}
2422
2423
2424#if (DBVER >= 32)
2425static PyObject*
2426DB_set_q_extentsize(DBObject* self, PyObject* args)
2427{
2428 int err;
2429 int extentsize;
2430
2431 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2432 return NULL;
2433 CHECK_DB_NOT_CLOSED(self);
2434
2435 MYDB_BEGIN_ALLOW_THREADS;
2436 err = self->db->set_q_extentsize(self->db, extentsize);
2437 MYDB_END_ALLOW_THREADS;
2438 RETURN_IF_ERR();
2439 RETURN_NONE();
2440}
2441#endif
2442
2443static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002444DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002445{
2446 int err, flags = 0, type;
2447 void* sp;
2448 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002449#if (DBVER >= 43)
2450 PyObject* txnobj = NULL;
2451 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002452 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002453#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002454 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002455#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002456
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002457#if (DBVER >= 43)
2458 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2459 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002460 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002461 if (!checkTxnObj(txnobj, &txn))
2462 return NULL;
2463#else
2464 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2465 return NULL;
2466#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002467 CHECK_DB_NOT_CLOSED(self);
2468
2469 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002470#if (DBVER >= 43)
2471 err = self->db->stat(self->db, txn, &sp, flags);
2472#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002473 err = self->db->stat(self->db, &sp, flags);
2474#else
2475 err = self->db->stat(self->db, &sp, NULL, flags);
2476#endif
2477 MYDB_END_ALLOW_THREADS;
2478 RETURN_IF_ERR();
2479
2480 self->haveStat = 1;
2481
2482 /* Turn the stat structure into a dictionary */
2483 type = _DB_get_type(self);
2484 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2485 free(sp);
2486 return NULL;
2487 }
2488
2489#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2490#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2491#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2492
2493 switch (type) {
2494 case DB_HASH:
2495 MAKE_HASH_ENTRY(magic);
2496 MAKE_HASH_ENTRY(version);
2497 MAKE_HASH_ENTRY(nkeys);
2498 MAKE_HASH_ENTRY(ndata);
2499 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002500#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002501 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002502#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002503 MAKE_HASH_ENTRY(ffactor);
2504 MAKE_HASH_ENTRY(buckets);
2505 MAKE_HASH_ENTRY(free);
2506 MAKE_HASH_ENTRY(bfree);
2507 MAKE_HASH_ENTRY(bigpages);
2508 MAKE_HASH_ENTRY(big_bfree);
2509 MAKE_HASH_ENTRY(overflows);
2510 MAKE_HASH_ENTRY(ovfl_free);
2511 MAKE_HASH_ENTRY(dup);
2512 MAKE_HASH_ENTRY(dup_free);
2513 break;
2514
2515 case DB_BTREE:
2516 case DB_RECNO:
2517 MAKE_BT_ENTRY(magic);
2518 MAKE_BT_ENTRY(version);
2519 MAKE_BT_ENTRY(nkeys);
2520 MAKE_BT_ENTRY(ndata);
2521 MAKE_BT_ENTRY(pagesize);
2522 MAKE_BT_ENTRY(minkey);
2523 MAKE_BT_ENTRY(re_len);
2524 MAKE_BT_ENTRY(re_pad);
2525 MAKE_BT_ENTRY(levels);
2526 MAKE_BT_ENTRY(int_pg);
2527 MAKE_BT_ENTRY(leaf_pg);
2528 MAKE_BT_ENTRY(dup_pg);
2529 MAKE_BT_ENTRY(over_pg);
2530 MAKE_BT_ENTRY(free);
2531 MAKE_BT_ENTRY(int_pgfree);
2532 MAKE_BT_ENTRY(leaf_pgfree);
2533 MAKE_BT_ENTRY(dup_pgfree);
2534 MAKE_BT_ENTRY(over_pgfree);
2535 break;
2536
2537 case DB_QUEUE:
2538 MAKE_QUEUE_ENTRY(magic);
2539 MAKE_QUEUE_ENTRY(version);
2540 MAKE_QUEUE_ENTRY(nkeys);
2541 MAKE_QUEUE_ENTRY(ndata);
2542 MAKE_QUEUE_ENTRY(pagesize);
2543 MAKE_QUEUE_ENTRY(pages);
2544 MAKE_QUEUE_ENTRY(re_len);
2545 MAKE_QUEUE_ENTRY(re_pad);
2546 MAKE_QUEUE_ENTRY(pgfree);
2547#if (DBVER == 31)
2548 MAKE_QUEUE_ENTRY(start);
2549#endif
2550 MAKE_QUEUE_ENTRY(first_recno);
2551 MAKE_QUEUE_ENTRY(cur_recno);
2552 break;
2553
2554 default:
2555 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2556 Py_DECREF(d);
2557 d = NULL;
2558 }
2559
2560#undef MAKE_HASH_ENTRY
2561#undef MAKE_BT_ENTRY
2562#undef MAKE_QUEUE_ENTRY
2563
2564 free(sp);
2565 return d;
2566}
2567
2568static PyObject*
2569DB_sync(DBObject* self, PyObject* args)
2570{
2571 int err;
2572 int flags = 0;
2573
2574 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2575 return NULL;
2576 CHECK_DB_NOT_CLOSED(self);
2577
2578 MYDB_BEGIN_ALLOW_THREADS;
2579 err = self->db->sync(self->db, flags);
2580 MYDB_END_ALLOW_THREADS;
2581 RETURN_IF_ERR();
2582 RETURN_NONE();
2583}
2584
2585
2586#if (DBVER >= 33)
2587static PyObject*
2588DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2589{
2590 int err, flags=0;
2591 u_int32_t count=0;
2592 PyObject* txnobj = NULL;
2593 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002594 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002595
2596 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2597 &txnobj, &flags))
2598 return NULL;
2599 CHECK_DB_NOT_CLOSED(self);
2600 if (!checkTxnObj(txnobj, &txn))
2601 return NULL;
2602
2603 MYDB_BEGIN_ALLOW_THREADS;
2604 err = self->db->truncate(self->db, txn, &count, flags);
2605 MYDB_END_ALLOW_THREADS;
2606 RETURN_IF_ERR();
2607 return PyInt_FromLong(count);
2608}
2609#endif
2610
2611
2612static PyObject*
2613DB_upgrade(DBObject* self, PyObject* args)
2614{
2615 int err, flags=0;
2616 char *filename;
2617
2618 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2619 return NULL;
2620 CHECK_DB_NOT_CLOSED(self);
2621
2622 MYDB_BEGIN_ALLOW_THREADS;
2623 err = self->db->upgrade(self->db, filename, flags);
2624 MYDB_END_ALLOW_THREADS;
2625 RETURN_IF_ERR();
2626 RETURN_NONE();
2627}
2628
2629
2630static PyObject*
2631DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2632{
2633 int err, flags=0;
2634 char* fileName;
2635 char* dbName=NULL;
2636 char* outFileName=NULL;
2637 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002638 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002639 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002640
2641 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2642 &fileName, &dbName, &outFileName, &flags))
2643 return NULL;
2644
2645 CHECK_DB_NOT_CLOSED(self);
2646 if (outFileName)
2647 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002648 /* XXX(nnorwitz): it should probably be an exception if outFile
2649 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002650
2651 MYDB_BEGIN_ALLOW_THREADS;
2652 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2653 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002654 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002655 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002656
2657 /* DB.verify acts as a DB handle destructor (like close); this was
2658 * documented in BerkeleyDB 4.2 but had the undocumented effect
2659 * of not being safe in prior versions while still requiring an explicit
2660 * DB.close call afterwards. Lets call close for the user to emulate
2661 * the safe 4.2 behaviour. */
2662#if (DBVER <= 41)
2663 self->db->close(self->db, 0);
2664#endif
2665 self->db = NULL;
2666
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002667 RETURN_IF_ERR();
2668 RETURN_NONE();
2669}
2670
2671
2672static PyObject*
2673DB_set_get_returns_none(DBObject* self, PyObject* args)
2674{
2675 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002676 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002677
2678 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2679 return NULL;
2680 CHECK_DB_NOT_CLOSED(self);
2681
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002682 if (self->moduleFlags.getReturnsNone)
2683 ++oldValue;
2684 if (self->moduleFlags.cursorSetReturnsNone)
2685 ++oldValue;
2686 self->moduleFlags.getReturnsNone = (flags >= 1);
2687 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 return PyInt_FromLong(oldValue);
2689}
2690
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002691#if (DBVER >= 41)
2692static PyObject*
2693DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2694{
2695 int err;
2696 u_int32_t flags=0;
2697 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002698 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002699
2700 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2701 &passwd, &flags)) {
2702 return NULL;
2703 }
2704
2705 MYDB_BEGIN_ALLOW_THREADS;
2706 err = self->db->set_encrypt(self->db, passwd, flags);
2707 MYDB_END_ALLOW_THREADS;
2708
2709 RETURN_IF_ERR();
2710 RETURN_NONE();
2711}
2712#endif /* DBVER >= 41 */
2713
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002714
2715/*-------------------------------------------------------------- */
2716/* Mapping and Dictionary-like access routines */
2717
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002718Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002719{
2720 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002721 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002722 int flags = 0;
2723 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002724 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002725
2726 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002727 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2728 PyErr_SetObject(DBError, t);
2729 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002730 return -1;
2731 }
2732
2733 if (self->haveStat) { /* Has the stat function been called recently? If
2734 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002735 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 }
2737
2738 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002739redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002740#if (DBVER >= 43)
2741 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2742#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002743 err = self->db->stat(self->db, &sp, flags);
2744#else
2745 err = self->db->stat(self->db, &sp, NULL, flags);
2746#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002747
2748 /* All the stat structures have matching fields upto the ndata field,
2749 so we can use any of them for the type cast */
2750 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2751
2752 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2753 * redo a full stat to make sure.
2754 * Fixes SF python bug 1493322, pybsddb bug 1184012
2755 */
2756 if (size == 0 && (flags & DB_FAST_STAT)) {
2757 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002758 if (!err)
2759 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002760 goto redo_stat_for_length;
2761 }
2762
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002763 MYDB_END_ALLOW_THREADS;
2764
2765 if (err)
2766 return -1;
2767
2768 self->haveStat = 1;
2769
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002770 free(sp);
2771 return size;
2772}
2773
2774
2775PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2776{
2777 int err;
2778 PyObject* retval;
2779 DBT key;
2780 DBT data;
2781
2782 CHECK_DB_NOT_CLOSED(self);
2783 if (!make_key_dbt(self, keyobj, &key, NULL))
2784 return NULL;
2785
2786 CLEAR_DBT(data);
2787 if (CHECK_DBFLAG(self, DB_THREAD)) {
2788 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2789 data.flags = DB_DBT_MALLOC;
2790 }
2791 MYDB_BEGIN_ALLOW_THREADS;
2792 err = self->db->get(self->db, NULL, &key, &data, 0);
2793 MYDB_END_ALLOW_THREADS;
2794 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2795 PyErr_SetObject(PyExc_KeyError, keyobj);
2796 retval = NULL;
2797 }
2798 else if (makeDBError(err)) {
2799 retval = NULL;
2800 }
2801 else {
2802 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2803 FREE_DBT(data);
2804 }
2805
2806 FREE_DBT(key);
2807 return retval;
2808}
2809
2810
2811static int
2812DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2813{
2814 DBT key, data;
2815 int retval;
2816 int flags = 0;
2817
2818 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002819 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2820 PyErr_SetObject(DBError, t);
2821 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002822 return -1;
2823 }
2824
2825 if (!make_key_dbt(self, keyobj, &key, NULL))
2826 return -1;
2827
2828 if (dataobj != NULL) {
2829 if (!make_dbt(dataobj, &data))
2830 retval = -1;
2831 else {
2832 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002833 /* dictionaries shouldn't have duplicate keys */
2834 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 retval = _DB_put(self, NULL, &key, &data, flags);
2836
2837 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002838 /* try deleting any old record that matches and then PUT it
2839 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002840 _DB_delete(self, NULL, &key, 0);
2841 PyErr_Clear();
2842 retval = _DB_put(self, NULL, &key, &data, flags);
2843 }
2844 }
2845 }
2846 else {
2847 /* dataobj == NULL, so delete the key */
2848 retval = _DB_delete(self, NULL, &key, 0);
2849 }
2850 FREE_DBT(key);
2851 return retval;
2852}
2853
2854
2855static PyObject*
2856DB_has_key(DBObject* self, PyObject* args)
2857{
2858 int err;
2859 PyObject* keyobj;
2860 DBT key, data;
2861 PyObject* txnobj = NULL;
2862 DB_TXN *txn = NULL;
2863
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002864 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002865 return NULL;
2866 CHECK_DB_NOT_CLOSED(self);
2867 if (!make_key_dbt(self, keyobj, &key, NULL))
2868 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002869 if (!checkTxnObj(txnobj, &txn)) {
2870 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002871 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002872 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002874 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875 it has a record but can't allocate a buffer for the data. This saves
2876 having to deal with data we won't be using.
2877 */
2878 CLEAR_DBT(data);
2879 data.flags = DB_DBT_USERMEM;
2880
2881 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002882 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002883 MYDB_END_ALLOW_THREADS;
2884 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002885
2886 if (err == DB_BUFFER_SMALL || err == 0) {
2887 return PyInt_FromLong(1);
2888 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2889 return PyInt_FromLong(0);
2890 }
2891
2892 makeDBError(err);
2893 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894}
2895
2896
2897#define _KEYS_LIST 1
2898#define _VALUES_LIST 2
2899#define _ITEMS_LIST 3
2900
2901static PyObject*
2902_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2903{
2904 int err, dbtype;
2905 DBT key;
2906 DBT data;
2907 DBC *cursor;
2908 PyObject* list;
2909 PyObject* item = NULL;
2910
2911 CHECK_DB_NOT_CLOSED(self);
2912 CLEAR_DBT(key);
2913 CLEAR_DBT(data);
2914
2915 dbtype = _DB_get_type(self);
2916 if (dbtype == -1)
2917 return NULL;
2918
2919 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002920 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002921 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002922
2923 /* get a cursor */
2924 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002925 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002926 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002927 if (makeDBError(err)) {
2928 Py_DECREF(list);
2929 return NULL;
2930 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002931
2932 if (CHECK_DBFLAG(self, DB_THREAD)) {
2933 key.flags = DB_DBT_REALLOC;
2934 data.flags = DB_DBT_REALLOC;
2935 }
2936
2937 while (1) { /* use the cursor to traverse the DB, collecting items */
2938 MYDB_BEGIN_ALLOW_THREADS;
2939 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2940 MYDB_END_ALLOW_THREADS;
2941
2942 if (err) {
2943 /* for any error, break out of the loop */
2944 break;
2945 }
2946
2947 switch (type) {
2948 case _KEYS_LIST:
2949 switch(dbtype) {
2950 case DB_BTREE:
2951 case DB_HASH:
2952 default:
2953 item = PyString_FromStringAndSize((char*)key.data, key.size);
2954 break;
2955 case DB_RECNO:
2956 case DB_QUEUE:
2957 item = PyInt_FromLong(*((db_recno_t*)key.data));
2958 break;
2959 }
2960 break;
2961
2962 case _VALUES_LIST:
2963 item = PyString_FromStringAndSize((char*)data.data, data.size);
2964 break;
2965
2966 case _ITEMS_LIST:
2967 switch(dbtype) {
2968 case DB_BTREE:
2969 case DB_HASH:
2970 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002971 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2972 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002973 break;
2974 case DB_RECNO:
2975 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002976 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2977 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002978 break;
2979 }
2980 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002981 default:
2982 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2983 item = NULL;
2984 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002985 }
2986 if (item == NULL) {
2987 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002988 list = NULL;
2989 goto done;
2990 }
2991 PyList_Append(list, item);
2992 Py_DECREF(item);
2993 }
2994
Gregory P. Smithe9477062005-06-04 06:46:59 +00002995 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2996 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002997 Py_DECREF(list);
2998 list = NULL;
2999 }
3000
3001 done:
3002 FREE_DBT(key);
3003 FREE_DBT(data);
3004 MYDB_BEGIN_ALLOW_THREADS;
3005 cursor->c_close(cursor);
3006 MYDB_END_ALLOW_THREADS;
3007 return list;
3008}
3009
3010
3011static PyObject*
3012DB_keys(DBObject* self, PyObject* args)
3013{
3014 PyObject* txnobj = NULL;
3015 DB_TXN *txn = NULL;
3016
Georg Brandl96a8c392006-05-29 21:04:52 +00003017 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003018 return NULL;
3019 if (!checkTxnObj(txnobj, &txn))
3020 return NULL;
3021 return _DB_make_list(self, txn, _KEYS_LIST);
3022}
3023
3024
3025static PyObject*
3026DB_items(DBObject* self, PyObject* args)
3027{
3028 PyObject* txnobj = NULL;
3029 DB_TXN *txn = NULL;
3030
Georg Brandl96a8c392006-05-29 21:04:52 +00003031 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003032 return NULL;
3033 if (!checkTxnObj(txnobj, &txn))
3034 return NULL;
3035 return _DB_make_list(self, txn, _ITEMS_LIST);
3036}
3037
3038
3039static PyObject*
3040DB_values(DBObject* self, PyObject* args)
3041{
3042 PyObject* txnobj = NULL;
3043 DB_TXN *txn = NULL;
3044
Georg Brandl96a8c392006-05-29 21:04:52 +00003045 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046 return NULL;
3047 if (!checkTxnObj(txnobj, &txn))
3048 return NULL;
3049 return _DB_make_list(self, txn, _VALUES_LIST);
3050}
3051
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003052/* --------------------------------------------------------------------- */
3053/* DBCursor methods */
3054
3055
3056static PyObject*
3057DBC_close(DBCursorObject* self, PyObject* args)
3058{
3059 int err = 0;
3060
3061 if (!PyArg_ParseTuple(args, ":close"))
3062 return NULL;
3063
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003064 if (self->dbc != NULL) {
3065 MYDB_BEGIN_ALLOW_THREADS;
3066 err = self->dbc->c_close(self->dbc);
3067 self->dbc = NULL;
3068 MYDB_END_ALLOW_THREADS;
3069 }
3070 RETURN_IF_ERR();
3071 RETURN_NONE();
3072}
3073
3074
3075static PyObject*
3076DBC_count(DBCursorObject* self, PyObject* args)
3077{
3078 int err = 0;
3079 db_recno_t count;
3080 int flags = 0;
3081
3082 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3083 return NULL;
3084
3085 CHECK_CURSOR_NOT_CLOSED(self);
3086
3087 MYDB_BEGIN_ALLOW_THREADS;
3088 err = self->dbc->c_count(self->dbc, &count, flags);
3089 MYDB_END_ALLOW_THREADS;
3090 RETURN_IF_ERR();
3091
3092 return PyInt_FromLong(count);
3093}
3094
3095
3096static PyObject*
3097DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3098{
3099 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3100}
3101
3102
3103static PyObject*
3104DBC_delete(DBCursorObject* self, PyObject* args)
3105{
3106 int err, flags=0;
3107
3108 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3109 return NULL;
3110
3111 CHECK_CURSOR_NOT_CLOSED(self);
3112
3113 MYDB_BEGIN_ALLOW_THREADS;
3114 err = self->dbc->c_del(self->dbc, flags);
3115 MYDB_END_ALLOW_THREADS;
3116 RETURN_IF_ERR();
3117
3118 self->mydb->haveStat = 0;
3119 RETURN_NONE();
3120}
3121
3122
3123static PyObject*
3124DBC_dup(DBCursorObject* self, PyObject* args)
3125{
3126 int err, flags =0;
3127 DBC* dbc = NULL;
3128
3129 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3130 return NULL;
3131
3132 CHECK_CURSOR_NOT_CLOSED(self);
3133
3134 MYDB_BEGIN_ALLOW_THREADS;
3135 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3136 MYDB_END_ALLOW_THREADS;
3137 RETURN_IF_ERR();
3138
3139 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3140}
3141
3142static PyObject*
3143DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3144{
3145 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3146}
3147
3148
3149static PyObject*
3150DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3151{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003152 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003153 PyObject* keyobj = NULL;
3154 PyObject* dataobj = NULL;
3155 PyObject* retval = NULL;
3156 int dlen = -1;
3157 int doff = -1;
3158 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003159 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003160 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003161
3162 CLEAR_DBT(key);
3163 CLEAR_DBT(data);
3164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003165 &flags, &dlen, &doff))
3166 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003168 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3169 &kwnames[1],
3170 &keyobj, &flags, &dlen, &doff))
3171 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003173 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3174 kwnames, &keyobj, &dataobj,
3175 &flags, &dlen, &doff))
3176 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 return NULL;
3178 }
3179 }
3180 }
3181
3182 CHECK_CURSOR_NOT_CLOSED(self);
3183
3184 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3185 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003186 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3187 (!add_partial_dbt(&data, dlen, doff)) )
3188 {
3189 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003191 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003192
3193 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3194 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003195 if (!(key.flags & DB_DBT_REALLOC)) {
3196 key.flags |= DB_DBT_MALLOC;
3197 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003198 }
3199
3200 MYDB_BEGIN_ALLOW_THREADS;
3201 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3202 MYDB_END_ALLOW_THREADS;
3203
Gregory P. Smithe9477062005-06-04 06:46:59 +00003204 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3205 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003206 Py_INCREF(Py_None);
3207 retval = Py_None;
3208 }
3209 else if (makeDBError(err)) {
3210 retval = NULL;
3211 }
3212 else {
3213 switch (_DB_get_type(self->mydb)) {
3214 case -1:
3215 retval = NULL;
3216 break;
3217 case DB_BTREE:
3218 case DB_HASH:
3219 default:
3220 retval = Py_BuildValue("s#s#", key.data, key.size,
3221 data.data, data.size);
3222 break;
3223 case DB_RECNO:
3224 case DB_QUEUE:
3225 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3226 data.data, data.size);
3227 break;
3228 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003229 FREE_DBT(data);
3230 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003231 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003232 return retval;
3233}
3234
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003235#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003236static PyObject*
3237DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3238{
3239 int err, flags=0;
3240 PyObject* keyobj = NULL;
3241 PyObject* dataobj = NULL;
3242 PyObject* retval = NULL;
3243 int dlen = -1;
3244 int doff = -1;
3245 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003246 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3247 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003248
3249 CLEAR_DBT(key);
3250 CLEAR_DBT(data);
3251 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3252 &flags, &dlen, &doff))
3253 {
3254 PyErr_Clear();
3255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003256 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003257 &keyobj, &flags, &dlen, &doff))
3258 {
3259 PyErr_Clear();
3260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3261 kwnames, &keyobj, &dataobj,
3262 &flags, &dlen, &doff))
3263 {
3264 return NULL;
3265 }
3266 }
3267 }
3268
3269 CHECK_CURSOR_NOT_CLOSED(self);
3270
3271 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3272 return NULL;
3273 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3274 (!add_partial_dbt(&data, dlen, doff)) ) {
3275 FREE_DBT(key);
3276 return NULL;
3277 }
3278
3279 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3280 data.flags = DB_DBT_MALLOC;
3281 if (!(key.flags & DB_DBT_REALLOC)) {
3282 key.flags |= DB_DBT_MALLOC;
3283 }
3284 }
3285
3286 CLEAR_DBT(pkey);
3287 pkey.flags = DB_DBT_MALLOC;
3288
3289 MYDB_BEGIN_ALLOW_THREADS;
3290 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3291 MYDB_END_ALLOW_THREADS;
3292
Gregory P. Smithe9477062005-06-04 06:46:59 +00003293 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3294 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003295 Py_INCREF(Py_None);
3296 retval = Py_None;
3297 }
3298 else if (makeDBError(err)) {
3299 retval = NULL;
3300 }
3301 else {
3302 PyObject *pkeyObj;
3303 PyObject *dataObj;
3304 dataObj = PyString_FromStringAndSize(data.data, data.size);
3305
3306 if (self->mydb->primaryDBType == DB_RECNO ||
3307 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003308 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003309 else
3310 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3311
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003312 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313 {
3314 PyObject *keyObj;
3315 int type = _DB_get_type(self->mydb);
3316 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003317 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003318 else
3319 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003320#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003321 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003322#else
3323 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3324#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003325 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003326 FREE_DBT(key);
3327 }
3328 else /* return just the pkey and data */
3329 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003330#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003331 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003332#else
3333 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3334#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003335 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003336 Py_DECREF(dataObj);
3337 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003338 FREE_DBT(pkey);
3339 FREE_DBT(data);
3340 }
3341 /* the only time REALLOC should be set is if we used an integer
3342 * key that make_key_dbt malloc'd for us. always free these. */
3343 if (key.flags & DB_DBT_REALLOC) {
3344 FREE_DBT(key);
3345 }
3346 return retval;
3347}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003348#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003349
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003350
3351static PyObject*
3352DBC_get_recno(DBCursorObject* self, PyObject* args)
3353{
3354 int err;
3355 db_recno_t recno;
3356 DBT key;
3357 DBT data;
3358
3359 if (!PyArg_ParseTuple(args, ":get_recno"))
3360 return NULL;
3361
3362 CHECK_CURSOR_NOT_CLOSED(self);
3363
3364 CLEAR_DBT(key);
3365 CLEAR_DBT(data);
3366 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3367 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3368 data.flags = DB_DBT_MALLOC;
3369 key.flags = DB_DBT_MALLOC;
3370 }
3371
3372 MYDB_BEGIN_ALLOW_THREADS;
3373 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3374 MYDB_END_ALLOW_THREADS;
3375 RETURN_IF_ERR();
3376
3377 recno = *((db_recno_t*)data.data);
3378 FREE_DBT(key);
3379 FREE_DBT(data);
3380 return PyInt_FromLong(recno);
3381}
3382
3383
3384static PyObject*
3385DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3386{
3387 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3388}
3389
3390
3391static PyObject*
3392DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3393{
3394 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3395}
3396
3397
3398static PyObject*
3399DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3400{
3401 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3402}
3403
3404
3405static PyObject*
3406DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3407{
3408 int err, flags = 0;
3409 PyObject* keyobj, *dataobj;
3410 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003411 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003412 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003413 int dlen = -1;
3414 int doff = -1;
3415
3416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3417 &keyobj, &dataobj, &flags, &dlen, &doff))
3418 return NULL;
3419
3420 CHECK_CURSOR_NOT_CLOSED(self);
3421
3422 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3423 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003424 if (!make_dbt(dataobj, &data) ||
3425 !add_partial_dbt(&data, dlen, doff) )
3426 {
3427 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003429 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003430
3431 MYDB_BEGIN_ALLOW_THREADS;
3432 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3433 MYDB_END_ALLOW_THREADS;
3434 FREE_DBT(key);
3435 RETURN_IF_ERR();
3436 self->mydb->haveStat = 0;
3437 RETURN_NONE();
3438}
3439
3440
3441static PyObject*
3442DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3443{
3444 int err, flags = 0;
3445 DBT key, data;
3446 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003447 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448 int dlen = -1;
3449 int doff = -1;
3450
3451 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3452 &keyobj, &flags, &dlen, &doff))
3453 return NULL;
3454
3455 CHECK_CURSOR_NOT_CLOSED(self);
3456
3457 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3458 return NULL;
3459
3460 CLEAR_DBT(data);
3461 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3462 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3463 data.flags = DB_DBT_MALLOC;
3464 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003465 if (!add_partial_dbt(&data, dlen, doff)) {
3466 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003468 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469
3470 MYDB_BEGIN_ALLOW_THREADS;
3471 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3472 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003473 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3474 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003475 Py_INCREF(Py_None);
3476 retval = Py_None;
3477 }
3478 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 retval = NULL;
3480 }
3481 else {
3482 switch (_DB_get_type(self->mydb)) {
3483 case -1:
3484 retval = NULL;
3485 break;
3486 case DB_BTREE:
3487 case DB_HASH:
3488 default:
3489 retval = Py_BuildValue("s#s#", key.data, key.size,
3490 data.data, data.size);
3491 break;
3492 case DB_RECNO:
3493 case DB_QUEUE:
3494 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3495 data.data, data.size);
3496 break;
3497 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003499 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003500 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003501 /* the only time REALLOC should be set is if we used an integer
3502 * key that make_key_dbt malloc'd for us. always free these. */
3503 if (key.flags & DB_DBT_REALLOC) {
3504 FREE_DBT(key);
3505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003506
3507 return retval;
3508}
3509
3510
3511static PyObject*
3512DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3513{
3514 int err, flags = 0;
3515 DBT key, data;
3516 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003517 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003518 int dlen = -1;
3519 int doff = -1;
3520
3521 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3522 &keyobj, &flags, &dlen, &doff))
3523 return NULL;
3524
3525 CHECK_CURSOR_NOT_CLOSED(self);
3526
3527 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3528 return NULL;
3529
3530 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003531 if (!add_partial_dbt(&data, dlen, doff)) {
3532 FREE_DBT(key);
3533 return NULL;
3534 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3536 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003537 data.flags |= DB_DBT_MALLOC;
3538 /* only BTREE databases will return anything in the key */
3539 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3540 key.flags |= DB_DBT_MALLOC;
3541 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003542 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543 MYDB_BEGIN_ALLOW_THREADS;
3544 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3545 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003546 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3547 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003548 Py_INCREF(Py_None);
3549 retval = Py_None;
3550 }
3551 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552 retval = NULL;
3553 }
3554 else {
3555 switch (_DB_get_type(self->mydb)) {
3556 case -1:
3557 retval = NULL;
3558 break;
3559 case DB_BTREE:
3560 case DB_HASH:
3561 default:
3562 retval = Py_BuildValue("s#s#", key.data, key.size,
3563 data.data, data.size);
3564 break;
3565 case DB_RECNO:
3566 case DB_QUEUE:
3567 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3568 data.data, data.size);
3569 break;
3570 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003571 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572 FREE_DBT(data);
3573 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003574 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003575 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003576 if (key.flags & DB_DBT_REALLOC) {
3577 FREE_DBT(key);
3578 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579
3580 return retval;
3581}
3582
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003584_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3585 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003587 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003589 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590
Gregory P. Smith7441e652003-11-03 21:35:31 +00003591 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3593 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003594 if (!make_dbt(dataobj, &data)) {
3595 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003597 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003598
3599 MYDB_BEGIN_ALLOW_THREADS;
3600 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3601 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003602 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003603 Py_INCREF(Py_None);
3604 retval = Py_None;
3605 }
3606 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003607 retval = NULL;
3608 }
3609 else {
3610 switch (_DB_get_type(self->mydb)) {
3611 case -1:
3612 retval = NULL;
3613 break;
3614 case DB_BTREE:
3615 case DB_HASH:
3616 default:
3617 retval = Py_BuildValue("s#s#", key.data, key.size,
3618 data.data, data.size);
3619 break;
3620 case DB_RECNO:
3621 case DB_QUEUE:
3622 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3623 data.data, data.size);
3624 break;
3625 }
3626 }
3627
3628 FREE_DBT(key);
3629 return retval;
3630}
3631
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003632static PyObject*
3633DBC_get_both(DBCursorObject* self, PyObject* args)
3634{
3635 int flags=0;
3636 PyObject *keyobj, *dataobj;
3637
3638 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3639 return NULL;
3640
Gregory P. Smith7441e652003-11-03 21:35:31 +00003641 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 CHECK_CURSOR_NOT_CLOSED(self);
3643
3644 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3645 self->mydb->moduleFlags.getReturnsNone);
3646}
3647
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003648/* Return size of entry */
3649static PyObject*
3650DBC_get_current_size(DBCursorObject* self, PyObject* args)
3651{
3652 int err, flags=DB_CURRENT;
3653 PyObject* retval = NULL;
3654 DBT key, data;
3655
3656 if (!PyArg_ParseTuple(args, ":get_current_size"))
3657 return NULL;
3658 CHECK_CURSOR_NOT_CLOSED(self);
3659 CLEAR_DBT(key);
3660 CLEAR_DBT(data);
3661
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003662 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003663 getting the record size. */
3664 data.flags = DB_DBT_USERMEM;
3665 data.ulen = 0;
3666 MYDB_BEGIN_ALLOW_THREADS;
3667 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3668 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003669 if (err == DB_BUFFER_SMALL || !err) {
3670 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003671 retval = PyInt_FromLong((long)data.size);
3672 err = 0;
3673 }
3674
3675 FREE_DBT(key);
3676 FREE_DBT(data);
3677 RETURN_IF_ERR();
3678 return retval;
3679}
3680
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003681static PyObject*
3682DBC_set_both(DBCursorObject* self, PyObject* args)
3683{
3684 int flags=0;
3685 PyObject *keyobj, *dataobj;
3686
3687 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3688 return NULL;
3689
Gregory P. Smith7441e652003-11-03 21:35:31 +00003690 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003691 CHECK_CURSOR_NOT_CLOSED(self);
3692
3693 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3694 self->mydb->moduleFlags.cursorSetReturnsNone);
3695}
3696
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697
3698static PyObject*
3699DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3700{
3701 int err, irecno, flags=0;
3702 db_recno_t recno;
3703 DBT key, data;
3704 PyObject* retval;
3705 int dlen = -1;
3706 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003707 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708
3709 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3710 &irecno, &flags, &dlen, &doff))
3711 return NULL;
3712
3713 CHECK_CURSOR_NOT_CLOSED(self);
3714
3715 CLEAR_DBT(key);
3716 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003717 /* use allocated space so DB will be able to realloc room for the real
3718 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 key.data = malloc(sizeof(db_recno_t));
3720 if (key.data == NULL) {
3721 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3722 return NULL;
3723 }
3724 key.size = sizeof(db_recno_t);
3725 key.ulen = key.size;
3726 memcpy(key.data, &recno, sizeof(db_recno_t));
3727 key.flags = DB_DBT_REALLOC;
3728
3729 CLEAR_DBT(data);
3730 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3731 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3732 data.flags = DB_DBT_MALLOC;
3733 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003734 if (!add_partial_dbt(&data, dlen, doff)) {
3735 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003737 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738
3739 MYDB_BEGIN_ALLOW_THREADS;
3740 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3741 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003742 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3743 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003744 Py_INCREF(Py_None);
3745 retval = Py_None;
3746 }
3747 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003748 retval = NULL;
3749 }
3750 else { /* Can only be used for BTrees, so no need to return int key */
3751 retval = Py_BuildValue("s#s#", key.data, key.size,
3752 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003753 FREE_DBT(data);
3754 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003755 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003756
3757 return retval;
3758}
3759
3760
3761static PyObject*
3762DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3763{
3764 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3765}
3766
3767
3768static PyObject*
3769DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3770{
3771 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3772}
3773
3774
3775static PyObject*
3776DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3777{
3778 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3779}
3780
3781
3782static PyObject*
3783DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3784{
3785 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3786}
3787
3788
3789static PyObject*
3790DBC_join_item(DBCursorObject* self, PyObject* args)
3791{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003793 DBT key, data;
3794 PyObject* retval;
3795
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003796 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003797 return NULL;
3798
3799 CHECK_CURSOR_NOT_CLOSED(self);
3800
3801 CLEAR_DBT(key);
3802 CLEAR_DBT(data);
3803 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3804 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3805 key.flags = DB_DBT_MALLOC;
3806 }
3807
3808 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003809 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003810 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003811 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3812 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003813 Py_INCREF(Py_None);
3814 retval = Py_None;
3815 }
3816 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003817 retval = NULL;
3818 }
3819 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003820 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003821 FREE_DBT(key);
3822 }
3823
3824 return retval;
3825}
3826
3827
3828
3829/* --------------------------------------------------------------------- */
3830/* DBEnv methods */
3831
3832
3833static PyObject*
3834DBEnv_close(DBEnvObject* self, PyObject* args)
3835{
3836 int err, flags = 0;
3837
3838 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3839 return NULL;
3840 if (!self->closed) { /* Don't close more than once */
3841 MYDB_BEGIN_ALLOW_THREADS;
3842 err = self->db_env->close(self->db_env, flags);
3843 MYDB_END_ALLOW_THREADS;
3844 /* after calling DBEnv->close, regardless of error, this DBEnv
3845 * may not be accessed again (BerkeleyDB docs). */
3846 self->closed = 1;
3847 self->db_env = NULL;
3848 RETURN_IF_ERR();
3849 }
3850 RETURN_NONE();
3851}
3852
3853
3854static PyObject*
3855DBEnv_open(DBEnvObject* self, PyObject* args)
3856{
3857 int err, flags=0, mode=0660;
3858 char *db_home;
3859
3860 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3861 return NULL;
3862
3863 CHECK_ENV_NOT_CLOSED(self);
3864
3865 MYDB_BEGIN_ALLOW_THREADS;
3866 err = self->db_env->open(self->db_env, db_home, flags, mode);
3867 MYDB_END_ALLOW_THREADS;
3868 RETURN_IF_ERR();
3869 self->closed = 0;
3870 self->flags = flags;
3871 RETURN_NONE();
3872}
3873
3874
3875static PyObject*
3876DBEnv_remove(DBEnvObject* self, PyObject* args)
3877{
3878 int err, flags=0;
3879 char *db_home;
3880
3881 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3882 return NULL;
3883 CHECK_ENV_NOT_CLOSED(self);
3884 MYDB_BEGIN_ALLOW_THREADS;
3885 err = self->db_env->remove(self->db_env, db_home, flags);
3886 MYDB_END_ALLOW_THREADS;
3887 RETURN_IF_ERR();
3888 RETURN_NONE();
3889}
3890
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003891#if (DBVER >= 41)
3892static PyObject*
3893DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3894{
3895 int err;
3896 u_int32_t flags=0;
3897 char *file = NULL;
3898 char *database = NULL;
3899 PyObject *txnobj = NULL;
3900 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003901 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003902 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003903
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003905 &file, &database, &txnobj, &flags)) {
3906 return NULL;
3907 }
3908 if (!checkTxnObj(txnobj, &txn)) {
3909 return NULL;
3910 }
3911 CHECK_ENV_NOT_CLOSED(self);
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3917}
3918
3919static PyObject*
3920DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3921{
3922 int err;
3923 u_int32_t flags=0;
3924 char *file = NULL;
3925 char *database = NULL;
3926 char *newname = NULL;
3927 PyObject *txnobj = NULL;
3928 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003929 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003930 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003931
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003932 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003933 &file, &database, &newname, &txnobj, &flags)) {
3934 return NULL;
3935 }
3936 if (!checkTxnObj(txnobj, &txn)) {
3937 return NULL;
3938 }
3939 CHECK_ENV_NOT_CLOSED(self);
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3942 flags);
3943 MYDB_END_ALLOW_THREADS;
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3946}
3947
3948static PyObject*
3949DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3950{
3951 int err;
3952 u_int32_t flags=0;
3953 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003954 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003955
3956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3957 &passwd, &flags)) {
3958 return NULL;
3959 }
3960
3961 MYDB_BEGIN_ALLOW_THREADS;
3962 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3963 MYDB_END_ALLOW_THREADS;
3964
3965 RETURN_IF_ERR();
3966 RETURN_NONE();
3967}
3968#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003969
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003970#if (DBVER >= 40)
3971static PyObject*
3972DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3973{
3974 int err;
3975 u_int32_t flags=0;
3976 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003977 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003978
3979 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3980 &timeout, &flags)) {
3981 return NULL;
3982 }
3983
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3986 MYDB_END_ALLOW_THREADS;
3987
3988 RETURN_IF_ERR();
3989 RETURN_NONE();
3990}
3991#endif /* DBVER >= 40 */
3992
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003994DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3995{
3996 int err;
3997 long shm_key = 0;
3998
3999 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4000 return NULL;
4001 CHECK_ENV_NOT_CLOSED(self);
4002
4003 err = self->db_env->set_shm_key(self->db_env, shm_key);
4004 RETURN_IF_ERR();
4005 RETURN_NONE();
4006}
4007
4008static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004009DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4010{
4011 int err, gbytes=0, bytes=0, ncache=0;
4012
4013 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4014 &gbytes, &bytes, &ncache))
4015 return NULL;
4016 CHECK_ENV_NOT_CLOSED(self);
4017
4018 MYDB_BEGIN_ALLOW_THREADS;
4019 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4020 MYDB_END_ALLOW_THREADS;
4021 RETURN_IF_ERR();
4022 RETURN_NONE();
4023}
4024
4025
4026#if (DBVER >= 32)
4027static PyObject*
4028DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4029{
4030 int err, flags=0, onoff=0;
4031
4032 if (!PyArg_ParseTuple(args, "ii:set_flags",
4033 &flags, &onoff))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_flags(self->db_env, flags, onoff);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043#endif
4044
4045
4046static PyObject*
4047DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4048{
4049 int err;
4050 char *dir;
4051
4052 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4053 return NULL;
4054 CHECK_ENV_NOT_CLOSED(self);
4055
4056 MYDB_BEGIN_ALLOW_THREADS;
4057 err = self->db_env->set_data_dir(self->db_env, dir);
4058 MYDB_END_ALLOW_THREADS;
4059 RETURN_IF_ERR();
4060 RETURN_NONE();
4061}
4062
4063
4064static PyObject*
4065DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4066{
4067 int err, lg_bsize;
4068
4069 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4070 return NULL;
4071 CHECK_ENV_NOT_CLOSED(self);
4072
4073 MYDB_BEGIN_ALLOW_THREADS;
4074 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4075 MYDB_END_ALLOW_THREADS;
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079
4080
4081static PyObject*
4082DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4083{
4084 int err;
4085 char *dir;
4086
4087 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_lg_dir(self->db_env, dir);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
4098static PyObject*
4099DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4100{
4101 int err, lg_max;
4102
4103 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4104 return NULL;
4105 CHECK_ENV_NOT_CLOSED(self);
4106
4107 MYDB_BEGIN_ALLOW_THREADS;
4108 err = self->db_env->set_lg_max(self->db_env, lg_max);
4109 MYDB_END_ALLOW_THREADS;
4110 RETURN_IF_ERR();
4111 RETURN_NONE();
4112}
4113
4114
Neal Norwitz84562352005-10-20 04:30:15 +00004115#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004116static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004117DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4118{
4119 int err, lg_max;
4120
4121 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4122 return NULL;
4123 CHECK_ENV_NOT_CLOSED(self);
4124
4125 MYDB_BEGIN_ALLOW_THREADS;
4126 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4127 MYDB_END_ALLOW_THREADS;
4128 RETURN_IF_ERR();
4129 RETURN_NONE();
4130}
Neal Norwitz84562352005-10-20 04:30:15 +00004131#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004132
4133
4134static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004135DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4136{
4137 int err, lk_detect;
4138
4139 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4142
4143 MYDB_BEGIN_ALLOW_THREADS;
4144 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4145 MYDB_END_ALLOW_THREADS;
4146 RETURN_IF_ERR();
4147 RETURN_NONE();
4148}
4149
4150
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004151#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004152static PyObject*
4153DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4154{
4155 int err, max;
4156
4157 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4158 return NULL;
4159 CHECK_ENV_NOT_CLOSED(self);
4160
4161 MYDB_BEGIN_ALLOW_THREADS;
4162 err = self->db_env->set_lk_max(self->db_env, max);
4163 MYDB_END_ALLOW_THREADS;
4164 RETURN_IF_ERR();
4165 RETURN_NONE();
4166}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004168
4169
4170#if (DBVER >= 32)
4171
4172static PyObject*
4173DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4174{
4175 int err, max;
4176
4177 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4178 return NULL;
4179 CHECK_ENV_NOT_CLOSED(self);
4180
4181 MYDB_BEGIN_ALLOW_THREADS;
4182 err = self->db_env->set_lk_max_locks(self->db_env, max);
4183 MYDB_END_ALLOW_THREADS;
4184 RETURN_IF_ERR();
4185 RETURN_NONE();
4186}
4187
4188
4189static PyObject*
4190DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4191{
4192 int err, max;
4193
4194 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4195 return NULL;
4196 CHECK_ENV_NOT_CLOSED(self);
4197
4198 MYDB_BEGIN_ALLOW_THREADS;
4199 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4200 MYDB_END_ALLOW_THREADS;
4201 RETURN_IF_ERR();
4202 RETURN_NONE();
4203}
4204
4205
4206static PyObject*
4207DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4208{
4209 int err, max;
4210
4211 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4212 return NULL;
4213 CHECK_ENV_NOT_CLOSED(self);
4214
4215 MYDB_BEGIN_ALLOW_THREADS;
4216 err = self->db_env->set_lk_max_objects(self->db_env, max);
4217 MYDB_END_ALLOW_THREADS;
4218 RETURN_IF_ERR();
4219 RETURN_NONE();
4220}
4221
4222#endif
4223
4224
4225static PyObject*
4226DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4227{
4228 int err, mp_mmapsize;
4229
4230 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4231 return NULL;
4232 CHECK_ENV_NOT_CLOSED(self);
4233
4234 MYDB_BEGIN_ALLOW_THREADS;
4235 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4236 MYDB_END_ALLOW_THREADS;
4237 RETURN_IF_ERR();
4238 RETURN_NONE();
4239}
4240
4241
4242static PyObject*
4243DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4244{
4245 int err;
4246 char *dir;
4247
4248 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4249 return NULL;
4250 CHECK_ENV_NOT_CLOSED(self);
4251
4252 MYDB_BEGIN_ALLOW_THREADS;
4253 err = self->db_env->set_tmp_dir(self->db_env, dir);
4254 MYDB_END_ALLOW_THREADS;
4255 RETURN_IF_ERR();
4256 RETURN_NONE();
4257}
4258
4259
4260static PyObject*
4261DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4262{
4263 int flags = 0;
4264 PyObject* txnobj = NULL;
4265 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004266 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004267
4268 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4269 &txnobj, &flags))
4270 return NULL;
4271
4272 if (!checkTxnObj(txnobj, &txn))
4273 return NULL;
4274 CHECK_ENV_NOT_CLOSED(self);
4275
4276 return (PyObject*)newDBTxnObject(self, txn, flags);
4277}
4278
4279
4280static PyObject*
4281DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4282{
4283 int err, kbyte=0, min=0, flags=0;
4284
4285 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
4288
4289 MYDB_BEGIN_ALLOW_THREADS;
4290#if (DBVER >= 40)
4291 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4292#else
4293 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4294#endif
4295 MYDB_END_ALLOW_THREADS;
4296 RETURN_IF_ERR();
4297 RETURN_NONE();
4298}
4299
4300
4301static PyObject*
4302DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4303{
4304 int err, max;
4305
4306 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4307 return NULL;
4308 CHECK_ENV_NOT_CLOSED(self);
4309
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004310 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004311 RETURN_IF_ERR();
4312 RETURN_NONE();
4313}
4314
4315
4316static PyObject*
4317DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4318{
4319 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004320 long stamp;
4321 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004322
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004323 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004324 return NULL;
4325 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004326 timestamp = (time_t)stamp;
4327 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004328 RETURN_IF_ERR();
4329 RETURN_NONE();
4330}
4331
4332
4333static PyObject*
4334DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4335{
4336 int err, atype, flags=0;
4337 int aborted = 0;
4338
4339 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4340 return NULL;
4341 CHECK_ENV_NOT_CLOSED(self);
4342
4343 MYDB_BEGIN_ALLOW_THREADS;
4344#if (DBVER >= 40)
4345 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4346#else
4347 err = lock_detect(self->db_env, flags, atype, &aborted);
4348#endif
4349 MYDB_END_ALLOW_THREADS;
4350 RETURN_IF_ERR();
4351 return PyInt_FromLong(aborted);
4352}
4353
4354
4355static PyObject*
4356DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4357{
4358 int flags=0;
4359 int locker, lock_mode;
4360 DBT obj;
4361 PyObject* objobj;
4362
4363 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4364 return NULL;
4365
4366
4367 if (!make_dbt(objobj, &obj))
4368 return NULL;
4369
4370 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4371}
4372
4373
4374static PyObject*
4375DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4376{
4377 int err;
4378 u_int32_t theID;
4379
4380 if (!PyArg_ParseTuple(args, ":lock_id"))
4381 return NULL;
4382
4383 CHECK_ENV_NOT_CLOSED(self);
4384 MYDB_BEGIN_ALLOW_THREADS;
4385#if (DBVER >= 40)
4386 err = self->db_env->lock_id(self->db_env, &theID);
4387#else
4388 err = lock_id(self->db_env, &theID);
4389#endif
4390 MYDB_END_ALLOW_THREADS;
4391 RETURN_IF_ERR();
4392
4393 return PyInt_FromLong((long)theID);
4394}
4395
4396
4397static PyObject*
4398DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4399{
4400 int err;
4401 DBLockObject* dblockobj;
4402
4403 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4404 return NULL;
4405
4406 CHECK_ENV_NOT_CLOSED(self);
4407 MYDB_BEGIN_ALLOW_THREADS;
4408#if (DBVER >= 40)
4409 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4410#else
4411 err = lock_put(self->db_env, &dblockobj->lock);
4412#endif
4413 MYDB_END_ALLOW_THREADS;
4414 RETURN_IF_ERR();
4415 RETURN_NONE();
4416}
4417
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004418#if (DBVER >= 44)
4419static PyObject*
4420DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4421{
4422 int err;
4423 char *file;
4424 u_int32_t flags = 0;
4425 static char* kwnames[] = { "file", "flags", NULL};
4426
4427 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4428 &file, &flags))
4429 return NULL;
4430 CHECK_ENV_NOT_CLOSED(self);
4431
4432 MYDB_BEGIN_ALLOW_THREADS;
4433 err = self->db_env->lsn_reset(self->db_env, file, flags);
4434 MYDB_END_ALLOW_THREADS;
4435 RETURN_IF_ERR();
4436 RETURN_NONE();
4437}
4438#endif /* DBVER >= 4.4 */
4439
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004440#if (DBVER >= 40)
4441static PyObject*
4442DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4443{
4444 int err;
4445 DB_LOG_STAT* statp = NULL;
4446 PyObject* d = NULL;
4447 u_int32_t flags = 0;
4448
4449 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4450 return NULL;
4451 CHECK_ENV_NOT_CLOSED(self);
4452
4453 MYDB_BEGIN_ALLOW_THREADS;
4454 err = self->db_env->log_stat(self->db_env, &statp, flags);
4455 MYDB_END_ALLOW_THREADS;
4456 RETURN_IF_ERR();
4457
4458 /* Turn the stat structure into a dictionary */
4459 d = PyDict_New();
4460 if (d == NULL) {
4461 if (statp)
4462 free(statp);
4463 return NULL;
4464 }
4465
4466#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4467
4468 MAKE_ENTRY(magic);
4469 MAKE_ENTRY(version);
4470 MAKE_ENTRY(mode);
4471 MAKE_ENTRY(lg_bsize);
4472#if (DBVER >= 44)
4473 MAKE_ENTRY(lg_size);
4474 MAKE_ENTRY(record);
4475#endif
4476#if (DBVER <= 40)
4477 MAKE_ENTRY(lg_max);
4478#endif
4479 MAKE_ENTRY(w_mbytes);
4480 MAKE_ENTRY(w_bytes);
4481 MAKE_ENTRY(wc_mbytes);
4482 MAKE_ENTRY(wc_bytes);
4483 MAKE_ENTRY(wcount);
4484 MAKE_ENTRY(wcount_fill);
4485#if (DBVER >= 44)
4486 MAKE_ENTRY(rcount);
4487#endif
4488 MAKE_ENTRY(scount);
4489 MAKE_ENTRY(cur_file);
4490 MAKE_ENTRY(cur_offset);
4491 MAKE_ENTRY(disk_file);
4492 MAKE_ENTRY(disk_offset);
4493 MAKE_ENTRY(maxcommitperflush);
4494 MAKE_ENTRY(mincommitperflush);
4495 MAKE_ENTRY(regsize);
4496 MAKE_ENTRY(region_wait);
4497 MAKE_ENTRY(region_nowait);
4498
4499#undef MAKE_ENTRY
4500 free(statp);
4501 return d;
4502} /* DBEnv_log_stat */
4503#endif /* DBVER >= 4.0 for log_stat method */
4504
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004505
4506static PyObject*
4507DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4508{
4509 int err;
4510 DB_LOCK_STAT* sp;
4511 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004512 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004513
4514 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4515 return NULL;
4516 CHECK_ENV_NOT_CLOSED(self);
4517
4518 MYDB_BEGIN_ALLOW_THREADS;
4519#if (DBVER >= 40)
4520 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4521#else
4522#if (DBVER >= 33)
4523 err = lock_stat(self->db_env, &sp);
4524#else
4525 err = lock_stat(self->db_env, &sp, NULL);
4526#endif
4527#endif
4528 MYDB_END_ALLOW_THREADS;
4529 RETURN_IF_ERR();
4530
4531 /* Turn the stat structure into a dictionary */
4532 d = PyDict_New();
4533 if (d == NULL) {
4534 free(sp);
4535 return NULL;
4536 }
4537
4538#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4539
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004540#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004542#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004543 MAKE_ENTRY(nmodes);
4544#if (DBVER >= 32)
4545 MAKE_ENTRY(maxlocks);
4546 MAKE_ENTRY(maxlockers);
4547 MAKE_ENTRY(maxobjects);
4548 MAKE_ENTRY(nlocks);
4549 MAKE_ENTRY(maxnlocks);
4550#endif
4551 MAKE_ENTRY(nlockers);
4552 MAKE_ENTRY(maxnlockers);
4553#if (DBVER >= 32)
4554 MAKE_ENTRY(nobjects);
4555 MAKE_ENTRY(maxnobjects);
4556#endif
4557 MAKE_ENTRY(nrequests);
4558 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004559#if (DBVER < 44)
4560 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004562#else
4563 MAKE_ENTRY(lock_nowait);
4564 MAKE_ENTRY(lock_wait);
4565#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004566 MAKE_ENTRY(ndeadlocks);
4567 MAKE_ENTRY(regsize);
4568 MAKE_ENTRY(region_wait);
4569 MAKE_ENTRY(region_nowait);
4570
4571#undef MAKE_ENTRY
4572 free(sp);
4573 return d;
4574}
4575
4576
4577static PyObject*
4578DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4579{
4580 int flags=0;
4581 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004582 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004583 PyObject* list;
4584 PyObject* item = NULL;
4585
4586 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4587 return NULL;
4588
4589 CHECK_ENV_NOT_CLOSED(self);
4590 MYDB_BEGIN_ALLOW_THREADS;
4591#if (DBVER >= 40)
4592 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4593#elif (DBVER == 33)
4594 err = log_archive(self->db_env, &log_list, flags);
4595#else
4596 err = log_archive(self->db_env, &log_list, flags, NULL);
4597#endif
4598 MYDB_END_ALLOW_THREADS;
4599 RETURN_IF_ERR();
4600
Gregory P. Smithbad47452006-06-05 00:33:35 +00004601 list = PyList_New(0);
4602 if (list == NULL) {
4603 if (log_list)
4604 free(log_list);
4605 return NULL;
4606 }
4607
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004609 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4611 item = PyString_FromString (*log_list);
4612 if (item == NULL) {
4613 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 list = NULL;
4615 break;
4616 }
4617 PyList_Append(list, item);
4618 Py_DECREF(item);
4619 }
4620 free(log_list_start);
4621 }
4622 return list;
4623}
4624
4625
4626static PyObject*
4627DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4628{
4629 int err;
4630 DB_TXN_STAT* sp;
4631 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004632 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004633
4634 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4635 return NULL;
4636 CHECK_ENV_NOT_CLOSED(self);
4637
4638 MYDB_BEGIN_ALLOW_THREADS;
4639#if (DBVER >= 40)
4640 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4641#elif (DBVER == 33)
4642 err = txn_stat(self->db_env, &sp);
4643#else
4644 err = txn_stat(self->db_env, &sp, NULL);
4645#endif
4646 MYDB_END_ALLOW_THREADS;
4647 RETURN_IF_ERR();
4648
4649 /* Turn the stat structure into a dictionary */
4650 d = PyDict_New();
4651 if (d == NULL) {
4652 free(sp);
4653 return NULL;
4654 }
4655
4656#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4657
4658 MAKE_ENTRY(time_ckp);
4659 MAKE_ENTRY(last_txnid);
4660 MAKE_ENTRY(maxtxns);
4661 MAKE_ENTRY(nactive);
4662 MAKE_ENTRY(maxnactive);
4663 MAKE_ENTRY(nbegins);
4664 MAKE_ENTRY(naborts);
4665 MAKE_ENTRY(ncommits);
4666 MAKE_ENTRY(regsize);
4667 MAKE_ENTRY(region_wait);
4668 MAKE_ENTRY(region_nowait);
4669
4670#undef MAKE_ENTRY
4671 free(sp);
4672 return d;
4673}
4674
4675
4676static PyObject*
4677DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4678{
4679 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004680 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004681
4682 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4683 return NULL;
4684 CHECK_ENV_NOT_CLOSED(self);
4685
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004686 if (self->moduleFlags.getReturnsNone)
4687 ++oldValue;
4688 if (self->moduleFlags.cursorSetReturnsNone)
4689 ++oldValue;
4690 self->moduleFlags.getReturnsNone = (flags >= 1);
4691 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004692 return PyInt_FromLong(oldValue);
4693}
4694
4695
4696/* --------------------------------------------------------------------- */
4697/* DBTxn methods */
4698
4699
4700static PyObject*
4701DBTxn_commit(DBTxnObject* self, PyObject* args)
4702{
4703 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004704 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004705
4706 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4707 return NULL;
4708
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004709 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004710 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4711 "after txn_commit or txn_abort");
4712 PyErr_SetObject(DBError, t);
4713 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004714 return NULL;
4715 }
4716 txn = self->txn;
4717 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 MYDB_BEGIN_ALLOW_THREADS;
4719#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004720 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004721#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004722 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004723#endif
4724 MYDB_END_ALLOW_THREADS;
4725 RETURN_IF_ERR();
4726 RETURN_NONE();
4727}
4728
4729static PyObject*
4730DBTxn_prepare(DBTxnObject* self, PyObject* args)
4731{
4732#if (DBVER >= 33)
4733 int err;
4734 char* gid=NULL;
4735 int gid_size=0;
4736
4737 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4738 return NULL;
4739
4740 if (gid_size != DB_XIDDATASIZE) {
4741 PyErr_SetString(PyExc_TypeError,
4742 "gid must be DB_XIDDATASIZE bytes long");
4743 return NULL;
4744 }
4745
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004746 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004747 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4748 "after txn_commit or txn_abort");
4749 PyErr_SetObject(DBError, t);
4750 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004751 return NULL;
4752 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004753 MYDB_BEGIN_ALLOW_THREADS;
4754#if (DBVER >= 40)
4755 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4756#else
4757 err = txn_prepare(self->txn, (u_int8_t*)gid);
4758#endif
4759 MYDB_END_ALLOW_THREADS;
4760 RETURN_IF_ERR();
4761 RETURN_NONE();
4762#else
4763 int err;
4764
4765 if (!PyArg_ParseTuple(args, ":prepare"))
4766 return NULL;
4767
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004769 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4770 "after txn_commit or txn_abort");
4771 PyErr_SetObject(DBError, t);
4772 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004773 return NULL;
4774 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004775 MYDB_BEGIN_ALLOW_THREADS;
4776 err = txn_prepare(self->txn);
4777 MYDB_END_ALLOW_THREADS;
4778 RETURN_IF_ERR();
4779 RETURN_NONE();
4780#endif
4781}
4782
4783
4784static PyObject*
4785DBTxn_abort(DBTxnObject* self, PyObject* args)
4786{
4787 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004788 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004789
4790 if (!PyArg_ParseTuple(args, ":abort"))
4791 return NULL;
4792
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004793 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004794 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4795 "after txn_commit or txn_abort");
4796 PyErr_SetObject(DBError, t);
4797 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004798 return NULL;
4799 }
4800 txn = self->txn;
4801 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004802 MYDB_BEGIN_ALLOW_THREADS;
4803#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004805#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807#endif
4808 MYDB_END_ALLOW_THREADS;
4809 RETURN_IF_ERR();
4810 RETURN_NONE();
4811}
4812
4813
4814static PyObject*
4815DBTxn_id(DBTxnObject* self, PyObject* args)
4816{
4817 int id;
4818
4819 if (!PyArg_ParseTuple(args, ":id"))
4820 return NULL;
4821
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004822 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004823 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4824 "after txn_commit or txn_abort");
4825 PyErr_SetObject(DBError, t);
4826 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004827 return NULL;
4828 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004829 MYDB_BEGIN_ALLOW_THREADS;
4830#if (DBVER >= 40)
4831 id = self->txn->id(self->txn);
4832#else
4833 id = txn_id(self->txn);
4834#endif
4835 MYDB_END_ALLOW_THREADS;
4836 return PyInt_FromLong(id);
4837}
4838
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004839#if (DBVER >= 43)
4840/* --------------------------------------------------------------------- */
4841/* DBSequence methods */
4842
4843
4844static PyObject*
4845DBSequence_close(DBSequenceObject* self, PyObject* args)
4846{
4847 int err, flags=0;
4848 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4849 return NULL;
4850 CHECK_SEQUENCE_NOT_CLOSED(self)
4851
4852 MYDB_BEGIN_ALLOW_THREADS
4853 err = self->sequence->close(self->sequence, flags);
4854 self->sequence = NULL;
4855 MYDB_END_ALLOW_THREADS
4856
4857 RETURN_IF_ERR();
4858
4859 RETURN_NONE();
4860}
4861
4862static PyObject*
4863DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4864{
4865 int err, flags = 0;
4866 int delta = 1;
4867 db_seq_t value;
4868 PyObject *txnobj = NULL;
4869 DB_TXN *txn = NULL;
4870 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4871 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4872 return NULL;
4873 CHECK_SEQUENCE_NOT_CLOSED(self)
4874
4875 if (!checkTxnObj(txnobj, &txn))
4876 return NULL;
4877
4878 MYDB_BEGIN_ALLOW_THREADS
4879 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4880 MYDB_END_ALLOW_THREADS
4881
4882 RETURN_IF_ERR();
4883 return PyLong_FromLongLong(value);
4884
4885}
4886
4887static PyObject*
4888DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4889{
4890 if (!PyArg_ParseTuple(args,":get_dbp"))
4891 return NULL;
4892 CHECK_SEQUENCE_NOT_CLOSED(self)
4893 Py_INCREF(self->mydb);
4894 return (PyObject* )self->mydb;
4895}
4896
4897static PyObject*
4898DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4899{
4900 int err;
4901 DBT key;
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004902 PyObject *retval;
4903 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004904 CHECK_SEQUENCE_NOT_CLOSED(self)
4905 MYDB_BEGIN_ALLOW_THREADS
4906 err = self->sequence->get_key(self->sequence, &key);
4907 MYDB_END_ALLOW_THREADS
4908
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004909 if (!err)
4910 retval = PyString_FromStringAndSize(key.data, key.size);
4911
4912 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004913 RETURN_IF_ERR();
4914
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004915 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004916}
4917
4918static PyObject*
4919DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4920{
4921 int err;
4922 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004923 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004924 return NULL;
4925 CHECK_SEQUENCE_NOT_CLOSED(self)
4926
4927 MYDB_BEGIN_ALLOW_THREADS
4928 err = self->sequence->initial_value(self->sequence, value);
4929 MYDB_END_ALLOW_THREADS
4930
4931 RETURN_IF_ERR();
4932
4933 RETURN_NONE();
4934}
4935
4936static PyObject*
4937DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4938{
4939 int err, flags = 0;
4940 PyObject* keyobj;
4941 PyObject *txnobj = NULL;
4942 DB_TXN *txn = NULL;
4943 DBT key;
4944
4945 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004947 return NULL;
4948
4949 if (!checkTxnObj(txnobj, &txn))
4950 return NULL;
4951
4952 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4953 return NULL;
4954
4955 MYDB_BEGIN_ALLOW_THREADS
4956 err = self->sequence->open(self->sequence, txn, &key, flags);
4957 MYDB_END_ALLOW_THREADS
4958
4959 CLEAR_DBT(key);
4960 RETURN_IF_ERR();
4961
4962 RETURN_NONE();
4963}
4964
4965static PyObject*
4966DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4967{
4968 int err, flags = 0;
4969 PyObject *txnobj = NULL;
4970 DB_TXN *txn = NULL;
4971
4972 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004973 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004974 return NULL;
4975
4976 if (!checkTxnObj(txnobj, &txn))
4977 return NULL;
4978
4979 CHECK_SEQUENCE_NOT_CLOSED(self)
4980
4981 MYDB_BEGIN_ALLOW_THREADS
4982 err = self->sequence->remove(self->sequence, txn, flags);
4983 MYDB_END_ALLOW_THREADS
4984
4985 RETURN_IF_ERR();
4986 RETURN_NONE();
4987}
4988
4989static PyObject*
4990DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4991{
4992 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004993 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004994 return NULL;
4995 CHECK_SEQUENCE_NOT_CLOSED(self)
4996
4997 MYDB_BEGIN_ALLOW_THREADS
4998 err = self->sequence->set_cachesize(self->sequence, size);
4999 MYDB_END_ALLOW_THREADS
5000
5001 RETURN_IF_ERR();
5002 RETURN_NONE();
5003}
5004
5005static PyObject*
5006DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5007{
5008 int err, size;
5009 if (!PyArg_ParseTuple(args,":get_cachesize"))
5010 return NULL;
5011 CHECK_SEQUENCE_NOT_CLOSED(self)
5012
5013 MYDB_BEGIN_ALLOW_THREADS
5014 err = self->sequence->get_cachesize(self->sequence, &size);
5015 MYDB_END_ALLOW_THREADS
5016
5017 RETURN_IF_ERR();
5018 return PyInt_FromLong(size);
5019}
5020
5021static PyObject*
5022DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5023{
5024 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005025 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005026 return NULL;
5027 CHECK_SEQUENCE_NOT_CLOSED(self)
5028
5029 MYDB_BEGIN_ALLOW_THREADS
5030 err = self->sequence->set_flags(self->sequence, flags);
5031 MYDB_END_ALLOW_THREADS
5032
5033 RETURN_IF_ERR();
5034 RETURN_NONE();
5035
5036}
5037
5038static PyObject*
5039DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5040{
5041 unsigned int flags;
5042 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005043 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005044 return NULL;
5045 CHECK_SEQUENCE_NOT_CLOSED(self)
5046
5047 MYDB_BEGIN_ALLOW_THREADS
5048 err = self->sequence->get_flags(self->sequence, &flags);
5049 MYDB_END_ALLOW_THREADS
5050
5051 RETURN_IF_ERR();
5052 return PyInt_FromLong((int)flags);
5053}
5054
5055static PyObject*
5056DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5057{
5058 int err;
5059 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005060 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005061 return NULL;
5062 CHECK_SEQUENCE_NOT_CLOSED(self)
5063
5064 MYDB_BEGIN_ALLOW_THREADS
5065 err = self->sequence->set_range(self->sequence, min, max);
5066 MYDB_END_ALLOW_THREADS
5067
5068 RETURN_IF_ERR();
5069 RETURN_NONE();
5070}
5071
5072static PyObject*
5073DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5074{
5075 int err;
5076 db_seq_t min, max;
5077 if (!PyArg_ParseTuple(args,":get_range"))
5078 return NULL;
5079 CHECK_SEQUENCE_NOT_CLOSED(self)
5080
5081 MYDB_BEGIN_ALLOW_THREADS
5082 err = self->sequence->get_range(self->sequence, &min, &max);
5083 MYDB_END_ALLOW_THREADS
5084
5085 RETURN_IF_ERR();
5086 return Py_BuildValue("(LL)", min, max);
5087}
5088
5089static PyObject*
5090DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5091{
5092 int err, flags = 0;
5093 DB_SEQUENCE_STAT* sp = NULL;
5094 PyObject* dict_stat;
5095 static char* kwnames[] = {"flags", NULL };
5096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5097 return NULL;
5098 CHECK_SEQUENCE_NOT_CLOSED(self);
5099
5100 MYDB_BEGIN_ALLOW_THREADS;
5101 err = self->sequence->stat(self->sequence, &sp, flags);
5102 MYDB_END_ALLOW_THREADS;
5103 RETURN_IF_ERR();
5104
5105 if ((dict_stat = PyDict_New()) == NULL) {
5106 free(sp);
5107 return NULL;
5108 }
5109
5110
5111#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5112#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5113
5114 MAKE_INT_ENTRY(wait);
5115 MAKE_INT_ENTRY(nowait);
5116 MAKE_LONG_LONG_ENTRY(current);
5117 MAKE_LONG_LONG_ENTRY(value);
5118 MAKE_LONG_LONG_ENTRY(last_value);
5119 MAKE_LONG_LONG_ENTRY(min);
5120 MAKE_LONG_LONG_ENTRY(max);
5121 MAKE_INT_ENTRY(cache_size);
5122 MAKE_INT_ENTRY(flags);
5123
5124#undef MAKE_INT_ENTRY
5125#undef MAKE_LONG_LONG_ENTRY
5126
5127 free(sp);
5128 return dict_stat;
5129}
5130#endif
5131
5132
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005133/* --------------------------------------------------------------------- */
5134/* Method definition tables and type objects */
5135
5136static PyMethodDef DB_methods[] = {
5137 {"append", (PyCFunction)DB_append, METH_VARARGS},
5138#if (DBVER >= 33)
5139 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5140#endif
5141 {"close", (PyCFunction)DB_close, METH_VARARGS},
5142#if (DBVER >= 32)
5143 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5144 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5145#endif
5146 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5147 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5148 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5149 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005150#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005151 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005152#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005153 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5154 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5155 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5156 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5157 {"join", (PyCFunction)DB_join, METH_VARARGS},
5158 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5159 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5160 {"items", (PyCFunction)DB_items, METH_VARARGS},
5161 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5162 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5163 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5164 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5165 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5166 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005167#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005168 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005170 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005171#if (DBVER >= 41)
5172 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5173#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005174 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5175 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5176 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5177 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5178 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5179 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5180 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5181 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5182 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5183#if (DBVER >= 32)
5184 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5185#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005186 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005187 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5188#if (DBVER >= 33)
5189 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5190#endif
5191 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5192 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5193 {"values", (PyCFunction)DB_values, METH_VARARGS},
5194 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5195 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5196 {NULL, NULL} /* sentinel */
5197};
5198
5199
5200static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005201 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005202 (binaryfunc)DB_subscript, /*mp_subscript*/
5203 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5204};
5205
5206
5207static PyMethodDef DBCursor_methods[] = {
5208 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5209 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5210 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5211 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5212 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5213 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5214 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005215#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005216 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005217#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5219 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5220 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5221 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5222 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5223 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5224 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5225 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005226 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005227 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005228 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5229 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5230 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5231 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5232 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5233 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5234 {NULL, NULL} /* sentinel */
5235};
5236
5237
5238static PyMethodDef DBEnv_methods[] = {
5239 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5240 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5241 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005242#if (DBVER >= 41)
5243 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5244 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5245 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5246#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005247#if (DBVER >= 40)
5248 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5249#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005250 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005251 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5252 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5253#if (DBVER >= 32)
5254 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5255#endif
5256 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5257 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5258 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005259#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005260 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005263#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005265#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266#if (DBVER >= 32)
5267 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5268 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5269 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5270#endif
5271 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5272 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5273 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5274 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5275 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5276 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005277 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005278 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5279 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5280 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5281 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5282 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5283 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005284#if (DBVER >= 40)
5285 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5286#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005287#if (DBVER >= 44)
5288 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5289#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005290 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5291 {NULL, NULL} /* sentinel */
5292};
5293
5294
5295static PyMethodDef DBTxn_methods[] = {
5296 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5297 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5298 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5299 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5300 {NULL, NULL} /* sentinel */
5301};
5302
5303
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005304#if (DBVER >= 43)
5305static PyMethodDef DBSequence_methods[] = {
5306 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5307 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5308 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5309 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005310 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5311 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5312 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5313 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5314 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5315 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5316 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5317 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5318 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5319 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5320 {NULL, NULL} /* sentinel */
5321};
5322#endif
5323
5324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005325static PyObject*
5326DB_getattr(DBObject* self, char *name)
5327{
5328 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5329}
5330
5331
5332static PyObject*
5333DBEnv_getattr(DBEnvObject* self, char *name)
5334{
5335 if (!strcmp(name, "db_home")) {
5336 CHECK_ENV_NOT_CLOSED(self);
5337 if (self->db_env->db_home == NULL) {
5338 RETURN_NONE();
5339 }
5340 return PyString_FromString(self->db_env->db_home);
5341 }
5342
5343 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5344}
5345
5346
5347static PyObject*
5348DBCursor_getattr(DBCursorObject* self, char *name)
5349{
5350 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5351}
5352
5353static PyObject*
5354DBTxn_getattr(DBTxnObject* self, char *name)
5355{
5356 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5357}
5358
5359static PyObject*
5360DBLock_getattr(DBLockObject* self, char *name)
5361{
5362 return NULL;
5363}
5364
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005365#if (DBVER >= 43)
5366static PyObject*
5367DBSequence_getattr(DBSequenceObject* self, char *name)
5368{
5369 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5370}
5371#endif
5372
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005373statichere PyTypeObject DB_Type = {
5374 PyObject_HEAD_INIT(NULL)
5375 0, /*ob_size*/
5376 "DB", /*tp_name*/
5377 sizeof(DBObject), /*tp_basicsize*/
5378 0, /*tp_itemsize*/
5379 /* methods */
5380 (destructor)DB_dealloc, /*tp_dealloc*/
5381 0, /*tp_print*/
5382 (getattrfunc)DB_getattr, /*tp_getattr*/
5383 0, /*tp_setattr*/
5384 0, /*tp_compare*/
5385 0, /*tp_repr*/
5386 0, /*tp_as_number*/
5387 0, /*tp_as_sequence*/
5388 &DB_mapping,/*tp_as_mapping*/
5389 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005390#ifdef HAVE_WEAKREF
5391 0, /* tp_call */
5392 0, /* tp_str */
5393 0, /* tp_getattro */
5394 0, /* tp_setattro */
5395 0, /* tp_as_buffer */
5396 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5397 0, /* tp_doc */
5398 0, /* tp_traverse */
5399 0, /* tp_clear */
5400 0, /* tp_richcompare */
5401 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5402#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005403};
5404
5405
5406statichere PyTypeObject DBCursor_Type = {
5407 PyObject_HEAD_INIT(NULL)
5408 0, /*ob_size*/
5409 "DBCursor", /*tp_name*/
5410 sizeof(DBCursorObject), /*tp_basicsize*/
5411 0, /*tp_itemsize*/
5412 /* methods */
5413 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5414 0, /*tp_print*/
5415 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5416 0, /*tp_setattr*/
5417 0, /*tp_compare*/
5418 0, /*tp_repr*/
5419 0, /*tp_as_number*/
5420 0, /*tp_as_sequence*/
5421 0, /*tp_as_mapping*/
5422 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005423#ifdef HAVE_WEAKREF
5424 0, /* tp_call */
5425 0, /* tp_str */
5426 0, /* tp_getattro */
5427 0, /* tp_setattro */
5428 0, /* tp_as_buffer */
5429 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5430 0, /* tp_doc */
5431 0, /* tp_traverse */
5432 0, /* tp_clear */
5433 0, /* tp_richcompare */
5434 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005436};
5437
5438
5439statichere PyTypeObject DBEnv_Type = {
5440 PyObject_HEAD_INIT(NULL)
5441 0, /*ob_size*/
5442 "DBEnv", /*tp_name*/
5443 sizeof(DBEnvObject), /*tp_basicsize*/
5444 0, /*tp_itemsize*/
5445 /* methods */
5446 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5447 0, /*tp_print*/
5448 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5449 0, /*tp_setattr*/
5450 0, /*tp_compare*/
5451 0, /*tp_repr*/
5452 0, /*tp_as_number*/
5453 0, /*tp_as_sequence*/
5454 0, /*tp_as_mapping*/
5455 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005456#ifdef HAVE_WEAKREF
5457 0, /* tp_call */
5458 0, /* tp_str */
5459 0, /* tp_getattro */
5460 0, /* tp_setattro */
5461 0, /* tp_as_buffer */
5462 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5463 0, /* tp_doc */
5464 0, /* tp_traverse */
5465 0, /* tp_clear */
5466 0, /* tp_richcompare */
5467 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5468#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005469};
5470
5471statichere PyTypeObject DBTxn_Type = {
5472 PyObject_HEAD_INIT(NULL)
5473 0, /*ob_size*/
5474 "DBTxn", /*tp_name*/
5475 sizeof(DBTxnObject), /*tp_basicsize*/
5476 0, /*tp_itemsize*/
5477 /* methods */
5478 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5479 0, /*tp_print*/
5480 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5481 0, /*tp_setattr*/
5482 0, /*tp_compare*/
5483 0, /*tp_repr*/
5484 0, /*tp_as_number*/
5485 0, /*tp_as_sequence*/
5486 0, /*tp_as_mapping*/
5487 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005488#ifdef HAVE_WEAKREF
5489 0, /* tp_call */
5490 0, /* tp_str */
5491 0, /* tp_getattro */
5492 0, /* tp_setattro */
5493 0, /* tp_as_buffer */
5494 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5495 0, /* tp_doc */
5496 0, /* tp_traverse */
5497 0, /* tp_clear */
5498 0, /* tp_richcompare */
5499 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5500#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005501};
5502
5503
5504statichere PyTypeObject DBLock_Type = {
5505 PyObject_HEAD_INIT(NULL)
5506 0, /*ob_size*/
5507 "DBLock", /*tp_name*/
5508 sizeof(DBLockObject), /*tp_basicsize*/
5509 0, /*tp_itemsize*/
5510 /* methods */
5511 (destructor)DBLock_dealloc, /*tp_dealloc*/
5512 0, /*tp_print*/
5513 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5514 0, /*tp_setattr*/
5515 0, /*tp_compare*/
5516 0, /*tp_repr*/
5517 0, /*tp_as_number*/
5518 0, /*tp_as_sequence*/
5519 0, /*tp_as_mapping*/
5520 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005521#ifdef HAVE_WEAKREF
5522 0, /* tp_call */
5523 0, /* tp_str */
5524 0, /* tp_getattro */
5525 0, /* tp_setattro */
5526 0, /* tp_as_buffer */
5527 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5528 0, /* tp_doc */
5529 0, /* tp_traverse */
5530 0, /* tp_clear */
5531 0, /* tp_richcompare */
5532 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5533#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005534};
5535
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005536#if (DBVER >= 43)
5537statichere PyTypeObject DBSequence_Type = {
5538 PyObject_HEAD_INIT(NULL)
5539 0, /*ob_size*/
5540 "DBSequence", /*tp_name*/
5541 sizeof(DBSequenceObject), /*tp_basicsize*/
5542 0, /*tp_itemsize*/
5543 /* methods */
5544 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5545 0, /*tp_print*/
5546 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5547 0, /*tp_setattr*/
5548 0, /*tp_compare*/
5549 0, /*tp_repr*/
5550 0, /*tp_as_number*/
5551 0, /*tp_as_sequence*/
5552 0, /*tp_as_mapping*/
5553 0, /*tp_hash*/
5554#ifdef HAVE_WEAKREF
5555 0, /* tp_call */
5556 0, /* tp_str */
5557 0, /* tp_getattro */
5558 0, /* tp_setattro */
5559 0, /* tp_as_buffer */
5560 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5561 0, /* tp_doc */
5562 0, /* tp_traverse */
5563 0, /* tp_clear */
5564 0, /* tp_richcompare */
5565 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5566#endif
5567};
5568#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005569
5570/* --------------------------------------------------------------------- */
5571/* Module-level functions */
5572
5573static PyObject*
5574DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5575{
5576 PyObject* dbenvobj = NULL;
5577 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005578 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005579
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005580 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5581 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005582 return NULL;
5583 if (dbenvobj == Py_None)
5584 dbenvobj = NULL;
5585 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5586 makeTypeError("DBEnv", dbenvobj);
5587 return NULL;
5588 }
5589
5590 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5591}
5592
5593
5594static PyObject*
5595DBEnv_construct(PyObject* self, PyObject* args)
5596{
5597 int flags = 0;
5598 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5599 return (PyObject* )newDBEnvObject(flags);
5600}
5601
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005602#if (DBVER >= 43)
5603static PyObject*
5604DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5605{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005606 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005607 int flags = 0;
5608 static char* kwnames[] = { "db", "flags", NULL};
5609
5610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5611 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005612 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005613 makeTypeError("DB", dbobj);
5614 return NULL;
5615 }
5616 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5617}
5618#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005619
5620static char bsddb_version_doc[] =
5621"Returns a tuple of major, minor, and patch release numbers of the\n\
5622underlying DB library.";
5623
5624static PyObject*
5625bsddb_version(PyObject* self, PyObject* args)
5626{
5627 int major, minor, patch;
5628
5629 if (!PyArg_ParseTuple(args, ":version"))
5630 return NULL;
5631 db_version(&major, &minor, &patch);
5632 return Py_BuildValue("(iii)", major, minor, patch);
5633}
5634
5635
5636/* List of functions defined in the module */
5637
5638static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005639 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5640 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5641#if (DBVER >= 43)
5642 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5643#endif
5644 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005645 {NULL, NULL} /* sentinel */
5646};
5647
5648
5649/* --------------------------------------------------------------------- */
5650/* Module initialization */
5651
5652
5653/* Convenience routine to export an integer value.
5654 * Errors are silently ignored, for better or for worse...
5655 */
5656#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5657
Gregory P. Smith41631e82003-09-21 00:08:14 +00005658#define MODULE_NAME_MAX_LEN 11
5659static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005660
5661DL_EXPORT(void) init_bsddb(void)
5662{
5663 PyObject* m;
5664 PyObject* d;
5665 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5666 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5667 PyObject* cvsid_s = PyString_FromString( rcs_id );
5668
5669 /* Initialize the type of the new type objects here; doing it here
5670 is required for portability to Windows without requiring C++. */
5671 DB_Type.ob_type = &PyType_Type;
5672 DBCursor_Type.ob_type = &PyType_Type;
5673 DBEnv_Type.ob_type = &PyType_Type;
5674 DBTxn_Type.ob_type = &PyType_Type;
5675 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005676#if (DBVER >= 43)
5677 DBSequence_Type.ob_type = &PyType_Type;
5678#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005679
5680
Mark Hammonda69d4092003-04-22 23:13:27 +00005681#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005683 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684#endif
5685
5686 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005687 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005688 if (m == NULL)
5689 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005690
5691 /* Add some symbolic constants to the module */
5692 d = PyModule_GetDict(m);
5693 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5694 PyDict_SetItemString(d, "cvsid", cvsid_s);
5695 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5696 Py_DECREF(pybsddb_version_s);
5697 pybsddb_version_s = NULL;
5698 Py_DECREF(cvsid_s);
5699 cvsid_s = NULL;
5700 Py_DECREF(db_version_s);
5701 db_version_s = NULL;
5702
5703 ADD_INT(d, DB_VERSION_MAJOR);
5704 ADD_INT(d, DB_VERSION_MINOR);
5705 ADD_INT(d, DB_VERSION_PATCH);
5706
5707 ADD_INT(d, DB_MAX_PAGES);
5708 ADD_INT(d, DB_MAX_RECORDS);
5709
Gregory P. Smith41631e82003-09-21 00:08:14 +00005710#if (DBVER >= 42)
5711 ADD_INT(d, DB_RPCCLIENT);
5712#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005713 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005714 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5715 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5716#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005717 ADD_INT(d, DB_XA_CREATE);
5718
5719 ADD_INT(d, DB_CREATE);
5720 ADD_INT(d, DB_NOMMAP);
5721 ADD_INT(d, DB_THREAD);
5722
5723 ADD_INT(d, DB_FORCE);
5724 ADD_INT(d, DB_INIT_CDB);
5725 ADD_INT(d, DB_INIT_LOCK);
5726 ADD_INT(d, DB_INIT_LOG);
5727 ADD_INT(d, DB_INIT_MPOOL);
5728 ADD_INT(d, DB_INIT_TXN);
5729#if (DBVER >= 32)
5730 ADD_INT(d, DB_JOINENV);
5731#endif
5732
5733 ADD_INT(d, DB_RECOVER);
5734 ADD_INT(d, DB_RECOVER_FATAL);
5735 ADD_INT(d, DB_TXN_NOSYNC);
5736 ADD_INT(d, DB_USE_ENVIRON);
5737 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5738
5739 ADD_INT(d, DB_LOCKDOWN);
5740 ADD_INT(d, DB_PRIVATE);
5741 ADD_INT(d, DB_SYSTEM_MEM);
5742
5743 ADD_INT(d, DB_TXN_SYNC);
5744 ADD_INT(d, DB_TXN_NOWAIT);
5745
5746 ADD_INT(d, DB_EXCL);
5747 ADD_INT(d, DB_FCNTL_LOCKING);
5748 ADD_INT(d, DB_ODDFILESIZE);
5749 ADD_INT(d, DB_RDWRMASTER);
5750 ADD_INT(d, DB_RDONLY);
5751 ADD_INT(d, DB_TRUNCATE);
5752#if (DBVER >= 32)
5753 ADD_INT(d, DB_EXTENT);
5754 ADD_INT(d, DB_CDB_ALLDB);
5755 ADD_INT(d, DB_VERIFY);
5756#endif
5757 ADD_INT(d, DB_UPGRADE);
5758
5759 ADD_INT(d, DB_AGGRESSIVE);
5760 ADD_INT(d, DB_NOORDERCHK);
5761 ADD_INT(d, DB_ORDERCHKONLY);
5762 ADD_INT(d, DB_PR_PAGE);
5763#if ! (DBVER >= 33)
5764 ADD_INT(d, DB_VRFY_FLAGMASK);
5765 ADD_INT(d, DB_PR_HEADERS);
5766#endif
5767 ADD_INT(d, DB_PR_RECOVERYTEST);
5768 ADD_INT(d, DB_SALVAGE);
5769
5770 ADD_INT(d, DB_LOCK_NORUN);
5771 ADD_INT(d, DB_LOCK_DEFAULT);
5772 ADD_INT(d, DB_LOCK_OLDEST);
5773 ADD_INT(d, DB_LOCK_RANDOM);
5774 ADD_INT(d, DB_LOCK_YOUNGEST);
5775#if (DBVER >= 33)
5776 ADD_INT(d, DB_LOCK_MAXLOCKS);
5777 ADD_INT(d, DB_LOCK_MINLOCKS);
5778 ADD_INT(d, DB_LOCK_MINWRITE);
5779#endif
5780
5781
5782#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005783 /* docs say to use zero instead */
5784 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785#else
5786 ADD_INT(d, DB_LOCK_CONFLICT);
5787#endif
5788
5789 ADD_INT(d, DB_LOCK_DUMP);
5790 ADD_INT(d, DB_LOCK_GET);
5791 ADD_INT(d, DB_LOCK_INHERIT);
5792 ADD_INT(d, DB_LOCK_PUT);
5793 ADD_INT(d, DB_LOCK_PUT_ALL);
5794 ADD_INT(d, DB_LOCK_PUT_OBJ);
5795
5796 ADD_INT(d, DB_LOCK_NG);
5797 ADD_INT(d, DB_LOCK_READ);
5798 ADD_INT(d, DB_LOCK_WRITE);
5799 ADD_INT(d, DB_LOCK_NOWAIT);
5800#if (DBVER >= 32)
5801 ADD_INT(d, DB_LOCK_WAIT);
5802#endif
5803 ADD_INT(d, DB_LOCK_IWRITE);
5804 ADD_INT(d, DB_LOCK_IREAD);
5805 ADD_INT(d, DB_LOCK_IWR);
5806#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005807#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005808 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005809#else
5810 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5811#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005812 ADD_INT(d, DB_LOCK_WWRITE);
5813#endif
5814
5815 ADD_INT(d, DB_LOCK_RECORD);
5816 ADD_INT(d, DB_LOCK_UPGRADE);
5817#if (DBVER >= 32)
5818 ADD_INT(d, DB_LOCK_SWITCH);
5819#endif
5820#if (DBVER >= 33)
5821 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5822#endif
5823
5824 ADD_INT(d, DB_LOCK_NOWAIT);
5825 ADD_INT(d, DB_LOCK_RECORD);
5826 ADD_INT(d, DB_LOCK_UPGRADE);
5827
5828#if (DBVER >= 33)
5829 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005830#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005831 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005832#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005833 ADD_INT(d, DB_LSTAT_FREE);
5834 ADD_INT(d, DB_LSTAT_HELD);
5835#if (DBVER == 33)
5836 ADD_INT(d, DB_LSTAT_NOGRANT);
5837#endif
5838 ADD_INT(d, DB_LSTAT_PENDING);
5839 ADD_INT(d, DB_LSTAT_WAITING);
5840#endif
5841
5842 ADD_INT(d, DB_ARCH_ABS);
5843 ADD_INT(d, DB_ARCH_DATA);
5844 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005845#if (DBVER >= 42)
5846 ADD_INT(d, DB_ARCH_REMOVE);
5847#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005848
5849 ADD_INT(d, DB_BTREE);
5850 ADD_INT(d, DB_HASH);
5851 ADD_INT(d, DB_RECNO);
5852 ADD_INT(d, DB_QUEUE);
5853 ADD_INT(d, DB_UNKNOWN);
5854
5855 ADD_INT(d, DB_DUP);
5856 ADD_INT(d, DB_DUPSORT);
5857 ADD_INT(d, DB_RECNUM);
5858 ADD_INT(d, DB_RENUMBER);
5859 ADD_INT(d, DB_REVSPLITOFF);
5860 ADD_INT(d, DB_SNAPSHOT);
5861
5862 ADD_INT(d, DB_JOIN_NOSORT);
5863
5864 ADD_INT(d, DB_AFTER);
5865 ADD_INT(d, DB_APPEND);
5866 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005867#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005868 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005869#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005870#if (DBVER >= 41)
5871 _addIntToDict(d, "DB_CHECKPOINT", 0);
5872#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005873 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005874 ADD_INT(d, DB_CURLSN);
5875#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005876#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877 ADD_INT(d, DB_COMMIT);
5878#endif
5879 ADD_INT(d, DB_CONSUME);
5880#if (DBVER >= 32)
5881 ADD_INT(d, DB_CONSUME_WAIT);
5882#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005883 ADD_INT(d, DB_CURRENT);
5884#if (DBVER >= 33)
5885 ADD_INT(d, DB_FAST_STAT);
5886#endif
5887 ADD_INT(d, DB_FIRST);
5888 ADD_INT(d, DB_FLUSH);
5889 ADD_INT(d, DB_GET_BOTH);
5890 ADD_INT(d, DB_GET_RECNO);
5891 ADD_INT(d, DB_JOIN_ITEM);
5892 ADD_INT(d, DB_KEYFIRST);
5893 ADD_INT(d, DB_KEYLAST);
5894 ADD_INT(d, DB_LAST);
5895 ADD_INT(d, DB_NEXT);
5896 ADD_INT(d, DB_NEXT_DUP);
5897 ADD_INT(d, DB_NEXT_NODUP);
5898 ADD_INT(d, DB_NODUPDATA);
5899 ADD_INT(d, DB_NOOVERWRITE);
5900 ADD_INT(d, DB_NOSYNC);
5901 ADD_INT(d, DB_POSITION);
5902 ADD_INT(d, DB_PREV);
5903 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005904#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005905 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005906#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005907 ADD_INT(d, DB_SET);
5908 ADD_INT(d, DB_SET_RANGE);
5909 ADD_INT(d, DB_SET_RECNO);
5910 ADD_INT(d, DB_WRITECURSOR);
5911
5912 ADD_INT(d, DB_OPFLAGS_MASK);
5913 ADD_INT(d, DB_RMW);
5914#if (DBVER >= 33)
5915 ADD_INT(d, DB_DIRTY_READ);
5916 ADD_INT(d, DB_MULTIPLE);
5917 ADD_INT(d, DB_MULTIPLE_KEY);
5918#endif
5919
Gregory P. Smith29602d22006-01-24 09:46:48 +00005920#if (DBVER >= 44)
5921 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5922 ADD_INT(d, DB_READ_COMMITTED);
5923#endif
5924
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005925#if (DBVER >= 33)
5926 ADD_INT(d, DB_DONOTINDEX);
5927#endif
5928
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005929#if (DBVER >= 41)
5930 _addIntToDict(d, "DB_INCOMPLETE", 0);
5931#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005932 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005933#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005934 ADD_INT(d, DB_KEYEMPTY);
5935 ADD_INT(d, DB_KEYEXIST);
5936 ADD_INT(d, DB_LOCK_DEADLOCK);
5937 ADD_INT(d, DB_LOCK_NOTGRANTED);
5938 ADD_INT(d, DB_NOSERVER);
5939 ADD_INT(d, DB_NOSERVER_HOME);
5940 ADD_INT(d, DB_NOSERVER_ID);
5941 ADD_INT(d, DB_NOTFOUND);
5942 ADD_INT(d, DB_OLD_VERSION);
5943 ADD_INT(d, DB_RUNRECOVERY);
5944 ADD_INT(d, DB_VERIFY_BAD);
5945#if (DBVER >= 33)
5946 ADD_INT(d, DB_PAGE_NOTFOUND);
5947 ADD_INT(d, DB_SECONDARY_BAD);
5948#endif
5949#if (DBVER >= 40)
5950 ADD_INT(d, DB_STAT_CLEAR);
5951 ADD_INT(d, DB_REGION_INIT);
5952 ADD_INT(d, DB_NOLOCKING);
5953 ADD_INT(d, DB_YIELDCPU);
5954 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5955 ADD_INT(d, DB_NOPANIC);
5956#endif
5957
Gregory P. Smith41631e82003-09-21 00:08:14 +00005958#if (DBVER >= 42)
5959 ADD_INT(d, DB_TIME_NOTGRANTED);
5960 ADD_INT(d, DB_TXN_NOT_DURABLE);
5961 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5962 ADD_INT(d, DB_LOG_AUTOREMOVE);
5963 ADD_INT(d, DB_DIRECT_LOG);
5964 ADD_INT(d, DB_DIRECT_DB);
5965 ADD_INT(d, DB_INIT_REP);
5966 ADD_INT(d, DB_ENCRYPT);
5967 ADD_INT(d, DB_CHKSUM);
5968#endif
5969
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005970#if (DBVER >= 43)
5971 ADD_INT(d, DB_LOG_INMEMORY);
5972 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005973 ADD_INT(d, DB_SEQ_DEC);
5974 ADD_INT(d, DB_SEQ_INC);
5975 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005976#endif
5977
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005978#if (DBVER >= 41)
5979 ADD_INT(d, DB_ENCRYPT_AES);
5980 ADD_INT(d, DB_AUTO_COMMIT);
5981#else
5982 /* allow berkeleydb 4.1 aware apps to run on older versions */
5983 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5984#endif
5985
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005986 ADD_INT(d, EINVAL);
5987 ADD_INT(d, EACCES);
5988 ADD_INT(d, ENOSPC);
5989 ADD_INT(d, ENOMEM);
5990 ADD_INT(d, EAGAIN);
5991 ADD_INT(d, EBUSY);
5992 ADD_INT(d, EEXIST);
5993 ADD_INT(d, ENOENT);
5994 ADD_INT(d, EPERM);
5995
Barry Warsaw1baa9822003-03-31 19:51:29 +00005996#if (DBVER >= 40)
5997 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5998 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5999#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006001 /* The exception name must be correct for pickled exception *
6002 * objects to unpickle properly. */
6003#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6004#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6005#else
6006#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6007#endif
6008
6009 /* All the rest of the exceptions derive only from DBError */
6010#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6011 PyDict_SetItemString(d, #name, name)
6012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006014 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6015 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016
Gregory P. Smithe9477062005-06-04 06:46:59 +00006017 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6018 * from both DBError and KeyError, since the API only supports
6019 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006020 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006021 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6022 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006023 Py_file_input, d, d);
6024 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006025 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006026 PyDict_DelItemString(d, "KeyError");
6027
6028
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006029#if !INCOMPLETE_IS_WARNING
6030 MAKE_EX(DBIncompleteError);
6031#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006032 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006033 MAKE_EX(DBKeyEmptyError);
6034 MAKE_EX(DBKeyExistError);
6035 MAKE_EX(DBLockDeadlockError);
6036 MAKE_EX(DBLockNotGrantedError);
6037 MAKE_EX(DBOldVersionError);
6038 MAKE_EX(DBRunRecoveryError);
6039 MAKE_EX(DBVerifyBadError);
6040 MAKE_EX(DBNoServerError);
6041 MAKE_EX(DBNoServerHomeError);
6042 MAKE_EX(DBNoServerIDError);
6043#if (DBVER >= 33)
6044 MAKE_EX(DBPageNotFoundError);
6045 MAKE_EX(DBSecondaryBadError);
6046#endif
6047
6048 MAKE_EX(DBInvalidArgError);
6049 MAKE_EX(DBAccessError);
6050 MAKE_EX(DBNoSpaceError);
6051 MAKE_EX(DBNoMemoryError);
6052 MAKE_EX(DBAgainError);
6053 MAKE_EX(DBBusyError);
6054 MAKE_EX(DBFileExistsError);
6055 MAKE_EX(DBNoSuchFileError);
6056 MAKE_EX(DBPermissionsError);
6057
6058#undef MAKE_EX
6059
6060 /* Check for errors */
6061 if (PyErr_Occurred()) {
6062 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006063 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006064 }
6065}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006066
6067/* allow this module to be named _pybsddb so that it can be installed
6068 * and imported on top of python >= 2.3 that includes its own older
6069 * copy of the library named _bsddb without importing the old version. */
6070DL_EXPORT(void) init_pybsddb(void)
6071{
6072 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6073 init_bsddb();
6074}