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