blob: 4cedc98d7b15c717a647fff28b804ebde9fcf5c8 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith2e49f782007-11-07 07:25:20 +0000101#define PY_BSDDB_VERSION "4.4.5.3"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000428 /*
429 * NOTE(gps): I don't like doing a data copy here, it seems
430 * wasteful. But without a clean way to tell FREE_DBT if it
431 * should free key->data or not we have to. Other places in
432 * the code check for DB_THREAD and forceably set DBT_MALLOC
433 * when we otherwise would leave flags 0 to indicate that.
434 */
Gregory P. Smith2c3e0d92007-11-01 21:22:40 +0000435 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000436 if (key->data == NULL) {
437 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
438 return 0;
439 }
Gregory P. Smith2c3e0d92007-11-01 21:22:40 +0000440 memcpy(key->data, PyString_AS_STRING(keyobj),
441 PyString_GET_SIZE(keyobj));
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000442 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000443 key->size = PyString_GET_SIZE(keyobj);
444 }
445
446 else if (PyInt_Check(keyobj)) {
447 /* verify access method type */
448 type = _DB_get_type(self);
449 if (type == -1)
450 return 0;
451 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000452 /* if BTREE then an Integer key is allowed with the
453 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 *pflags |= DB_SET_RECNO;
455 }
456 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000457 PyErr_SetString(
458 PyExc_TypeError,
459 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000460 return 0;
461 }
462
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000463 /* Make a key out of the requested recno, use allocated space so DB
464 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 recno = PyInt_AS_LONG(keyobj);
466 key->data = malloc(sizeof(db_recno_t));
467 if (key->data == NULL) {
468 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
469 return 0;
470 }
471 key->ulen = key->size = sizeof(db_recno_t);
472 memcpy(key->data, &recno, sizeof(db_recno_t));
473 key->flags = DB_DBT_REALLOC;
474 }
475 else {
476 PyErr_Format(PyExc_TypeError,
477 "String or Integer object expected for key, %s found",
478 keyobj->ob_type->tp_name);
479 return 0;
480 }
481
482 return 1;
483}
484
485
486/* Add partial record access to an existing DBT data struct.
487 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
488 and the data storage/retrieval will be done using dlen and doff. */
489static int add_partial_dbt(DBT* d, int dlen, int doff) {
490 /* if neither were set we do nothing (-1 is the default value) */
491 if ((dlen == -1) && (doff == -1)) {
492 return 1;
493 }
494
495 if ((dlen < 0) || (doff < 0)) {
496 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
497 return 0;
498 }
499
500 d->flags = d->flags | DB_DBT_PARTIAL;
501 d->dlen = (unsigned int) dlen;
502 d->doff = (unsigned int) doff;
503 return 1;
504}
505
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000506/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
507/* TODO: make this use the native libc strlcpy() when available (BSD) */
508unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
509{
510 unsigned int srclen, copylen;
511
512 srclen = strlen(src);
513 if (n <= 0)
514 return srclen;
515 copylen = (srclen > n-1) ? n-1 : srclen;
516 /* populate dest[0] thru dest[copylen-1] */
517 memcpy(dest, src, copylen);
518 /* guarantee null termination */
519 dest[copylen] = 0;
520
521 return srclen;
522}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000524/* Callback used to save away more information about errors from the DB
525 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000526static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000527#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000528static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000529#else
530static void _db_errorCallback(const DB_ENV *db_env,
531 const char* prefix, const char* msg)
532#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000534 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000535}
536
537
538/* make a nice exception object to raise for errors. */
539static int makeDBError(int err)
540{
541 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000542 PyObject *errObj = NULL;
543 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000545 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546
547 switch (err) {
548 case 0: /* successful, no error */ break;
549
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000550#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000551 case DB_INCOMPLETE:
552#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000553 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
554 /* Ensure that bytes_left never goes negative */
555 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
556 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
557 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000559 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000561 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000562#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
564#else
565 fprintf(stderr, errTxt);
566 fprintf(stderr, "\n");
567#endif
568
569#else /* do an exception instead */
570 errObj = DBIncompleteError;
571#endif
572 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000573#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000574
575 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
576 case DB_KEYEXIST: errObj = DBKeyExistError; break;
577 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
578 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
579 case DB_NOTFOUND: errObj = DBNotFoundError; break;
580 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
581 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
582 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
583 case DB_NOSERVER: errObj = DBNoServerError; break;
584 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
585 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
586#if (DBVER >= 33)
587 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
588 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
589#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000590 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000591
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000592#if (DBVER >= 43)
593 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
594 case ENOMEM: errObj = PyExc_MemoryError; break;
595#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 case EINVAL: errObj = DBInvalidArgError; break;
597 case EACCES: errObj = DBAccessError; break;
598 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000599 case EAGAIN: errObj = DBAgainError; break;
600 case EBUSY : errObj = DBBusyError; break;
601 case EEXIST: errObj = DBFileExistsError; break;
602 case ENOENT: errObj = DBNoSuchFileError; break;
603 case EPERM : errObj = DBPermissionsError; break;
604
605 default: errObj = DBError; break;
606 }
607
608 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000609 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
610 /* Ensure that bytes_left never goes negative */
611 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
612 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
613 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000615 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000616 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000617 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000618
619 errTuple = Py_BuildValue("(is)", err, errTxt);
620 PyErr_SetObject(errObj, errTuple);
621 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000622 }
623
624 return ((errObj != NULL) || exceptionRaised);
625}
626
627
628
629/* set a type exception */
630static void makeTypeError(char* expected, PyObject* found)
631{
632 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
633 expected, found->ob_type->tp_name);
634}
635
636
637/* verify that an obj is either None or a DBTxn, and set the txn pointer */
638static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
639{
640 if (txnobj == Py_None || txnobj == NULL) {
641 *txn = NULL;
642 return 1;
643 }
644 if (DBTxnObject_Check(txnobj)) {
645 *txn = ((DBTxnObject*)txnobj)->txn;
646 return 1;
647 }
648 else
649 makeTypeError("DBTxn", txnobj);
650 return 0;
651}
652
653
654/* Delete a key from a database
655 Returns 0 on success, -1 on an error. */
656static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
657{
658 int err;
659
660 MYDB_BEGIN_ALLOW_THREADS;
661 err = self->db->del(self->db, txn, key, 0);
662 MYDB_END_ALLOW_THREADS;
663 if (makeDBError(err)) {
664 return -1;
665 }
666 self->haveStat = 0;
667 return 0;
668}
669
670
671/* Store a key into a database
672 Returns 0 on success, -1 on an error. */
673static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
674{
675 int err;
676
677 MYDB_BEGIN_ALLOW_THREADS;
678 err = self->db->put(self->db, txn, key, data, flags);
679 MYDB_END_ALLOW_THREADS;
680 if (makeDBError(err)) {
681 return -1;
682 }
683 self->haveStat = 0;
684 return 0;
685}
686
687/* Get a key/data pair from a cursor */
688static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
689 PyObject *args, PyObject *kwargs, char *format)
690{
691 int err;
692 PyObject* retval = NULL;
693 DBT key, data;
694 int dlen = -1;
695 int doff = -1;
696 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000697 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000698
699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
700 &flags, &dlen, &doff))
701 return NULL;
702
703 CHECK_CURSOR_NOT_CLOSED(self);
704
705 flags |= extra_flags;
706 CLEAR_DBT(key);
707 CLEAR_DBT(data);
708 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
709 /* Tell BerkeleyDB to malloc the return value (thread safe) */
710 data.flags = DB_DBT_MALLOC;
711 key.flags = DB_DBT_MALLOC;
712 }
713 if (!add_partial_dbt(&data, dlen, doff))
714 return NULL;
715
716 MYDB_BEGIN_ALLOW_THREADS;
717 err = self->dbc->c_get(self->dbc, &key, &data, flags);
718 MYDB_END_ALLOW_THREADS;
719
Gregory P. Smithe9477062005-06-04 06:46:59 +0000720 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
721 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000722 Py_INCREF(Py_None);
723 retval = Py_None;
724 }
725 else if (makeDBError(err)) {
726 retval = NULL;
727 }
728 else { /* otherwise, success! */
729
730 /* if Recno or Queue, return the key as an Int */
731 switch (_DB_get_type(self->mydb)) {
732 case -1:
733 retval = NULL;
734 break;
735
736 case DB_RECNO:
737 case DB_QUEUE:
738 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
739 data.data, data.size);
740 break;
741 case DB_HASH:
742 case DB_BTREE:
743 default:
744 retval = Py_BuildValue("s#s#", key.data, key.size,
745 data.data, data.size);
746 break;
747 }
748 }
749 if (!err) {
750 FREE_DBT(key);
751 FREE_DBT(data);
752 }
753 return retval;
754}
755
756
757/* add an integer to a dictionary using the given name as a key */
758static void _addIntToDict(PyObject* dict, char *name, int value)
759{
760 PyObject* v = PyInt_FromLong((long) value);
761 if (!v || PyDict_SetItemString(dict, name, v))
762 PyErr_Clear();
763
764 Py_XDECREF(v);
765}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000766#if (DBVER >= 43)
767/* add an db_seq_t to a dictionary using the given name as a key */
768static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
769{
770 PyObject* v = PyLong_FromLongLong(value);
771 if (!v || PyDict_SetItemString(dict, name, v))
772 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000774 Py_XDECREF(v);
775}
776#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777
778
779
780/* --------------------------------------------------------------------- */
781/* Allocators and deallocators */
782
783static DBObject*
784newDBObject(DBEnvObject* arg, int flags)
785{
786 DBObject* self;
787 DB_ENV* db_env = NULL;
788 int err;
789
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000791 if (self == NULL)
792 return NULL;
793
794 self->haveStat = 0;
795 self->flags = 0;
796 self->setflags = 0;
797 self->myenvobj = NULL;
798#if (DBVER >= 33)
799 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000800 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000801 self->primaryDBType = 0;
802#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000803#ifdef HAVE_WEAKREF
804 self->in_weakreflist = NULL;
805#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806
807 /* keep a reference to our python DBEnv object */
808 if (arg) {
809 Py_INCREF(arg);
810 self->myenvobj = arg;
811 db_env = arg->db_env;
812 }
813
814 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000815 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000817 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
818 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000819
820 MYDB_BEGIN_ALLOW_THREADS;
821 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000822 if (self->db != NULL) {
823 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000825 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000827 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000829 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
830 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000831 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 if (makeDBError(err)) {
833 if (self->myenvobj) {
834 Py_DECREF(self->myenvobj);
835 self->myenvobj = NULL;
836 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000837 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 self = NULL;
839 }
840 return self;
841}
842
843
844static void
845DB_dealloc(DBObject* self)
846{
847 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000848 /* avoid closing a DB when its DBEnv has been closed out from under
849 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000851 (self->myenvobj && self->myenvobj->db_env))
852 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853 MYDB_BEGIN_ALLOW_THREADS;
854 self->db->close(self->db, 0);
855 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000856#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 } else {
858 PyErr_Warn(PyExc_RuntimeWarning,
859 "DB could not be closed in destructor: DBEnv already closed");
860#endif
861 }
862 self->db = NULL;
863 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000864#ifdef HAVE_WEAKREF
865 if (self->in_weakreflist != NULL) {
866 PyObject_ClearWeakRefs((PyObject *) self);
867 }
868#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 if (self->myenvobj) {
870 Py_DECREF(self->myenvobj);
871 self->myenvobj = NULL;
872 }
873#if (DBVER >= 33)
874 if (self->associateCallback != NULL) {
875 Py_DECREF(self->associateCallback);
876 self->associateCallback = NULL;
877 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000878 if (self->btCompareCallback != NULL) {
879 Py_DECREF(self->btCompareCallback);
880 self->btCompareCallback = NULL;
881 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000883 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000884}
885
886
887static DBCursorObject*
888newDBCursorObject(DBC* dbc, DBObject* db)
889{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000890 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000891 if (self == NULL)
892 return NULL;
893
894 self->dbc = dbc;
895 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000896#ifdef HAVE_WEAKREF
897 self->in_weakreflist = NULL;
898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899 Py_INCREF(self->mydb);
900 return self;
901}
902
903
904static void
905DBCursor_dealloc(DBCursorObject* self)
906{
907 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000908
909#ifdef HAVE_WEAKREF
910 if (self->in_weakreflist != NULL) {
911 PyObject_ClearWeakRefs((PyObject *) self);
912 }
913#endif
914
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000916 /* If the underlying database has been closed, we don't
917 need to do anything. If the environment has been closed
918 we need to leak, as BerkeleyDB will crash trying to access
919 the environment. There was an exception when the
920 user closed the environment even though there still was
921 a database open. */
922 if (self->mydb->db && self->mydb->myenvobj &&
923 !self->mydb->myenvobj->closed)
Gregory P. Smith946de922008-02-03 07:26:23 +0000924 /* test for: open db + no environment or non-closed environment */
925 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
926 !self->mydb->myenvobj->closed))) {
927 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000928 err = self->dbc->c_close(self->dbc);
Gregory P. Smith946de922008-02-03 07:26:23 +0000929 MYDB_END_ALLOW_THREADS;
930 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 }
933 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935}
936
937
938static DBEnvObject*
939newDBEnvObject(int flags)
940{
941 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000942 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943 if (self == NULL)
944 return NULL;
945
946 self->closed = 1;
947 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000948 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
949 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000950#ifdef HAVE_WEAKREF
951 self->in_weakreflist = NULL;
952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953
954 MYDB_BEGIN_ALLOW_THREADS;
955 err = db_env_create(&self->db_env, flags);
956 MYDB_END_ALLOW_THREADS;
957 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000958 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000959 self = NULL;
960 }
961 else {
962 self->db_env->set_errcall(self->db_env, _db_errorCallback);
963 }
964 return self;
965}
966
967
968static void
969DBEnv_dealloc(DBEnvObject* self)
970{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000971#ifdef HAVE_WEAKREF
972 if (self->in_weakreflist != NULL) {
973 PyObject_ClearWeakRefs((PyObject *) self);
974 }
975#endif
976
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000977 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 MYDB_BEGIN_ALLOW_THREADS;
979 self->db_env->close(self->db_env, 0);
980 MYDB_END_ALLOW_THREADS;
981 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983}
984
985
986static DBTxnObject*
987newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
988{
989 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000990 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 if (self == NULL)
992 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000993 Py_INCREF(myenv);
994 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000995#ifdef HAVE_WEAKREF
996 self->in_weakreflist = NULL;
997#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000998
999 MYDB_BEGIN_ALLOW_THREADS;
1000#if (DBVER >= 40)
1001 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1002#else
1003 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1004#endif
1005 MYDB_END_ALLOW_THREADS;
1006 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001007 Py_DECREF(self->env);
1008 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 self = NULL;
1010 }
1011 return self;
1012}
1013
1014
1015static void
1016DBTxn_dealloc(DBTxnObject* self)
1017{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001018#ifdef HAVE_WEAKREF
1019 if (self->in_weakreflist != NULL) {
1020 PyObject_ClearWeakRefs((PyObject *) self);
1021 }
1022#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023
Gregory P. Smith31c50652004-06-28 01:20:40 +00001024#ifdef HAVE_WARNINGS
1025 if (self->txn) {
1026 /* it hasn't been finalized, abort it! */
1027 MYDB_BEGIN_ALLOW_THREADS;
1028#if (DBVER >= 40)
1029 self->txn->abort(self->txn);
1030#else
1031 txn_abort(self->txn);
1032#endif
1033 MYDB_END_ALLOW_THREADS;
1034 PyErr_Warn(PyExc_RuntimeWarning,
1035 "DBTxn aborted in destructor. No prior commit() or abort().");
1036 }
1037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001038
Neal Norwitz62a21122006-01-25 05:21:55 +00001039 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001041}
1042
1043
1044static DBLockObject*
1045newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1046 db_lockmode_t lock_mode, int flags)
1047{
1048 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001049 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001050 if (self == NULL)
1051 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001052#ifdef HAVE_WEAKREF
1053 self->in_weakreflist = NULL;
1054#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055
1056 MYDB_BEGIN_ALLOW_THREADS;
1057#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001058 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1059 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060#else
1061 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1062#endif
1063 MYDB_END_ALLOW_THREADS;
1064 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001065 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001066 self = NULL;
1067 }
1068
1069 return self;
1070}
1071
1072
1073static void
1074DBLock_dealloc(DBLockObject* self)
1075{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001076#ifdef HAVE_WEAKREF
1077 if (self->in_weakreflist != NULL) {
1078 PyObject_ClearWeakRefs((PyObject *) self);
1079 }
1080#endif
1081 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001082
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001083 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001084}
1085
1086
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001087#if (DBVER >= 43)
1088static DBSequenceObject*
1089newDBSequenceObject(DBObject* mydb, int flags)
1090{
1091 int err;
1092 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1093 if (self == NULL)
1094 return NULL;
1095 Py_INCREF(mydb);
1096 self->mydb = mydb;
1097#ifdef HAVE_WEAKREF
1098 self->in_weakreflist = NULL;
1099#endif
1100
1101
1102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108 self = NULL;
1109 }
1110
1111 return self;
1112}
1113
1114
1115static void
1116DBSequence_dealloc(DBSequenceObject* self)
1117{
1118#ifdef HAVE_WEAKREF
1119 if (self->in_weakreflist != NULL) {
1120 PyObject_ClearWeakRefs((PyObject *) self);
1121 }
1122#endif
1123
1124 Py_DECREF(self->mydb);
1125 PyObject_Del(self);
1126}
1127#endif
1128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001129/* --------------------------------------------------------------------- */
1130/* DB methods */
1131
1132static PyObject*
1133DB_append(DBObject* self, PyObject* args)
1134{
1135 PyObject* txnobj = NULL;
1136 PyObject* dataobj;
1137 db_recno_t recno;
1138 DBT key, data;
1139 DB_TXN *txn = NULL;
1140
Georg Brandl96a8c392006-05-29 21:04:52 +00001141 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001142 return NULL;
1143
1144 CHECK_DB_NOT_CLOSED(self);
1145
1146 /* make a dummy key out of a recno */
1147 recno = 0;
1148 CLEAR_DBT(key);
1149 key.data = &recno;
1150 key.size = sizeof(recno);
1151 key.ulen = key.size;
1152 key.flags = DB_DBT_USERMEM;
1153
1154 if (!make_dbt(dataobj, &data)) return NULL;
1155 if (!checkTxnObj(txnobj, &txn)) return NULL;
1156
1157 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1158 return NULL;
1159
1160 return PyInt_FromLong(recno);
1161}
1162
1163
1164#if (DBVER >= 33)
1165
1166static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001167_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1168 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169{
1170 int retval = DB_DONOTINDEX;
1171 DBObject* secondaryDB = (DBObject*)db->app_private;
1172 PyObject* callback = secondaryDB->associateCallback;
1173 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001175 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176
1177
1178 if (callback != NULL) {
1179 MYDB_BEGIN_BLOCK_THREADS;
1180
Thomas Woutersb3153832006-03-08 01:47:19 +00001181 if (type == DB_RECNO || type == DB_QUEUE)
1182 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1183 priData->data, priData->size);
1184 else
1185 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1186 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001187 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001188 result = PyEval_CallObject(callback, args);
1189 }
1190 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001191 PyErr_Print();
1192 }
1193 else if (result == Py_None) {
1194 retval = DB_DONOTINDEX;
1195 }
1196 else if (PyInt_Check(result)) {
1197 retval = PyInt_AsLong(result);
1198 }
1199 else if (PyString_Check(result)) {
1200 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001201 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001202
1203 CLEAR_DBT(*secKey);
1204#if PYTHON_API_VERSION <= 1007
1205 /* 1.5 compatibility */
1206 size = PyString_Size(result);
1207 data = PyString_AsString(result);
1208#else
1209 PyString_AsStringAndSize(result, &data, &size);
1210#endif
1211 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1212 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001213 if (secKey->data) {
1214 memcpy(secKey->data, data, size);
1215 secKey->size = size;
1216 retval = 0;
1217 }
1218 else {
1219 PyErr_SetString(PyExc_MemoryError,
1220 "malloc failed in _db_associateCallback");
1221 PyErr_Print();
1222 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001223 }
1224 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225 PyErr_SetString(
1226 PyExc_TypeError,
1227 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228 PyErr_Print();
1229 }
1230
Thomas Woutersb3153832006-03-08 01:47:19 +00001231 Py_XDECREF(args);
1232 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233
1234 MYDB_END_BLOCK_THREADS;
1235 }
1236 return retval;
1237}
1238
1239
1240static PyObject*
1241DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1242{
1243 int err, flags=0;
1244 DBObject* secondaryDB;
1245 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246#if (DBVER >= 41)
1247 PyObject *txnobj = NULL;
1248 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001249 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001250 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001251#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001252 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001253#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001254
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001255#if (DBVER >= 41)
1256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1257 &secondaryDB, &callback, &flags,
1258 &txnobj)) {
1259#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001261 &secondaryDB, &callback, &flags)) {
1262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001263 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001264 }
1265
1266#if (DBVER >= 41)
1267 if (!checkTxnObj(txnobj, &txn)) return NULL;
1268#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001269
1270 CHECK_DB_NOT_CLOSED(self);
1271 if (!DBObject_Check(secondaryDB)) {
1272 makeTypeError("DB", (PyObject*)secondaryDB);
1273 return NULL;
1274 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001275 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 if (callback == Py_None) {
1277 callback = NULL;
1278 }
1279 else if (!PyCallable_Check(callback)) {
1280 makeTypeError("Callable", callback);
1281 return NULL;
1282 }
1283
1284 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001285 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001286 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001287 secondaryDB->associateCallback = callback;
1288 secondaryDB->primaryDBType = _DB_get_type(self);
1289
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001290 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1291 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1292 * The global interepreter lock is not initialized until the first
1293 * thread is created using thread.start_new_thread() or fork() is
1294 * called. that would cause the ALLOW_THREADS here to segfault due
1295 * to a null pointer reference if no threads or child processes
1296 * have been created. This works around that and is a no-op if
1297 * threads have already been initialized.
1298 * (see pybsddb-users mailing list post on 2002-08-07)
1299 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001300#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001301 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001302#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001304#if (DBVER >= 41)
1305 err = self->db->associate(self->db,
1306 txn,
1307 secondaryDB->db,
1308 _db_associateCallback,
1309 flags);
1310#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 err = self->db->associate(self->db,
1312 secondaryDB->db,
1313 _db_associateCallback,
1314 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001315#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 MYDB_END_ALLOW_THREADS;
1317
1318 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001319 Py_XDECREF(secondaryDB->associateCallback);
1320 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001321 secondaryDB->primaryDBType = 0;
1322 }
1323
1324 RETURN_IF_ERR();
1325 RETURN_NONE();
1326}
1327
1328
1329#endif
1330
1331
1332static PyObject*
1333DB_close(DBObject* self, PyObject* args)
1334{
1335 int err, flags=0;
1336 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1337 return NULL;
1338 if (self->db != NULL) {
1339 if (self->myenvobj)
1340 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342 self->db = NULL;
1343 RETURN_IF_ERR();
1344 }
1345 RETURN_NONE();
1346}
1347
1348
1349#if (DBVER >= 32)
1350static PyObject*
1351_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1352{
1353 int err, flags=0, type;
1354 PyObject* txnobj = NULL;
1355 PyObject* retval = NULL;
1356 DBT key, data;
1357 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001358 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001359
1360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1361 &txnobj, &flags))
1362 return NULL;
1363
1364 CHECK_DB_NOT_CLOSED(self);
1365 type = _DB_get_type(self);
1366 if (type == -1)
1367 return NULL;
1368 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 PyErr_SetString(PyExc_TypeError,
1370 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 return NULL;
1372 }
1373 if (!checkTxnObj(txnobj, &txn))
1374 return NULL;
1375
1376 CLEAR_DBT(key);
1377 CLEAR_DBT(data);
1378 if (CHECK_DBFLAG(self, DB_THREAD)) {
1379 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1380 data.flags = DB_DBT_MALLOC;
1381 key.flags = DB_DBT_MALLOC;
1382 }
1383
1384 MYDB_BEGIN_ALLOW_THREADS;
1385 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1386 MYDB_END_ALLOW_THREADS;
1387
Gregory P. Smithe9477062005-06-04 06:46:59 +00001388 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1389 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001390 err = 0;
1391 Py_INCREF(Py_None);
1392 retval = Py_None;
1393 }
1394 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001395 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1396 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001397 FREE_DBT(key);
1398 FREE_DBT(data);
1399 }
1400
1401 RETURN_IF_ERR();
1402 return retval;
1403}
1404
1405static PyObject*
1406DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1407{
1408 return _DB_consume(self, args, kwargs, DB_CONSUME);
1409}
1410
1411static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001412DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1413 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414{
1415 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1416}
1417#endif
1418
1419
1420
1421static PyObject*
1422DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1423{
1424 int err, flags=0;
1425 DBC* dbc;
1426 PyObject* txnobj = NULL;
1427 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001428 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1431 &txnobj, &flags))
1432 return NULL;
1433 CHECK_DB_NOT_CLOSED(self);
1434 if (!checkTxnObj(txnobj, &txn))
1435 return NULL;
1436
1437 MYDB_BEGIN_ALLOW_THREADS;
1438 err = self->db->cursor(self->db, txn, &dbc, flags);
1439 MYDB_END_ALLOW_THREADS;
1440 RETURN_IF_ERR();
1441 return (PyObject*) newDBCursorObject(dbc, self);
1442}
1443
1444
1445static PyObject*
1446DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1447{
1448 PyObject* txnobj = NULL;
1449 int flags = 0;
1450 PyObject* keyobj;
1451 DBT key;
1452 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001453 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454
1455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1456 &keyobj, &txnobj, &flags))
1457 return NULL;
1458 CHECK_DB_NOT_CLOSED(self);
1459 if (!make_key_dbt(self, keyobj, &key, NULL))
1460 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001461 if (!checkTxnObj(txnobj, &txn)) {
1462 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001463 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001464 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001466 if (-1 == _DB_delete(self, txn, &key, 0)) {
1467 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001468 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001469 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470
1471 FREE_DBT(key);
1472 RETURN_NONE();
1473}
1474
1475
1476static PyObject*
1477DB_fd(DBObject* self, PyObject* args)
1478{
1479 int err, the_fd;
1480
1481 if (!PyArg_ParseTuple(args,":fd"))
1482 return NULL;
1483 CHECK_DB_NOT_CLOSED(self);
1484
1485 MYDB_BEGIN_ALLOW_THREADS;
1486 err = self->db->fd(self->db, &the_fd);
1487 MYDB_END_ALLOW_THREADS;
1488 RETURN_IF_ERR();
1489 return PyInt_FromLong(the_fd);
1490}
1491
1492
1493static PyObject*
1494DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1495{
1496 int err, flags=0;
1497 PyObject* txnobj = NULL;
1498 PyObject* keyobj;
1499 PyObject* dfltobj = NULL;
1500 PyObject* retval = NULL;
1501 int dlen = -1;
1502 int doff = -1;
1503 DBT key, data;
1504 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001505 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001506 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001507
1508 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001509 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1510 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 return NULL;
1512
1513 CHECK_DB_NOT_CLOSED(self);
1514 if (!make_key_dbt(self, keyobj, &key, &flags))
1515 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001516 if (!checkTxnObj(txnobj, &txn)) {
1517 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001519 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001520
1521 CLEAR_DBT(data);
1522 if (CHECK_DBFLAG(self, DB_THREAD)) {
1523 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1524 data.flags = DB_DBT_MALLOC;
1525 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001526 if (!add_partial_dbt(&data, dlen, doff)) {
1527 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001529 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001530
1531 MYDB_BEGIN_ALLOW_THREADS;
1532 err = self->db->get(self->db, txn, &key, &data, flags);
1533 MYDB_END_ALLOW_THREADS;
1534
Gregory P. Smithe9477062005-06-04 06:46:59 +00001535 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536 err = 0;
1537 Py_INCREF(dfltobj);
1538 retval = dfltobj;
1539 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001540 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1541 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542 err = 0;
1543 Py_INCREF(Py_None);
1544 retval = Py_None;
1545 }
1546 else if (!err) {
1547 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001548 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1549 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550 else /* return just the data */
1551 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001552 FREE_DBT(data);
1553 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001554 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555
1556 RETURN_IF_ERR();
1557 return retval;
1558}
1559
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001560#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001561static PyObject*
1562DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1563{
1564 int err, flags=0;
1565 PyObject* txnobj = NULL;
1566 PyObject* keyobj;
1567 PyObject* dfltobj = NULL;
1568 PyObject* retval = NULL;
1569 int dlen = -1;
1570 int doff = -1;
1571 DBT key, pkey, data;
1572 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001573 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001574 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001575
1576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1577 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1578 &doff))
1579 return NULL;
1580
1581 CHECK_DB_NOT_CLOSED(self);
1582 if (!make_key_dbt(self, keyobj, &key, &flags))
1583 return NULL;
1584 if (!checkTxnObj(txnobj, &txn)) {
1585 FREE_DBT(key);
1586 return NULL;
1587 }
1588
1589 CLEAR_DBT(data);
1590 if (CHECK_DBFLAG(self, DB_THREAD)) {
1591 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1592 data.flags = DB_DBT_MALLOC;
1593 }
1594 if (!add_partial_dbt(&data, dlen, doff)) {
1595 FREE_DBT(key);
1596 return NULL;
1597 }
1598
1599 CLEAR_DBT(pkey);
1600 pkey.flags = DB_DBT_MALLOC;
1601
1602 MYDB_BEGIN_ALLOW_THREADS;
1603 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1604 MYDB_END_ALLOW_THREADS;
1605
Gregory P. Smithe9477062005-06-04 06:46:59 +00001606 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 err = 0;
1608 Py_INCREF(dfltobj);
1609 retval = dfltobj;
1610 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001611 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1612 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001613 err = 0;
1614 Py_INCREF(Py_None);
1615 retval = Py_None;
1616 }
1617 else if (!err) {
1618 PyObject *pkeyObj;
1619 PyObject *dataObj;
1620 dataObj = PyString_FromStringAndSize(data.data, data.size);
1621
1622 if (self->primaryDBType == DB_RECNO ||
1623 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001624 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001625 else
1626 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1627
1628 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1629 {
1630 PyObject *keyObj;
1631 int type = _DB_get_type(self);
1632 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001633 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001634 else
1635 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001636#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001637 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001638#else
1639 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1640#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001641 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001642 }
1643 else /* return just the pkey and data */
1644 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001645#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001646 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001647#else
1648 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1649#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001650 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001651 Py_DECREF(dataObj);
1652 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001653 FREE_DBT(pkey);
1654 FREE_DBT(data);
1655 }
1656 FREE_DBT(key);
1657
1658 RETURN_IF_ERR();
1659 return retval;
1660}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001661#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001662
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663
1664/* Return size of entry */
1665static PyObject*
1666DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1667{
1668 int err, flags=0;
1669 PyObject* txnobj = NULL;
1670 PyObject* keyobj;
1671 PyObject* retval = NULL;
1672 DBT key, data;
1673 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001674 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001675
1676 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1677 &keyobj, &txnobj))
1678 return NULL;
1679 CHECK_DB_NOT_CLOSED(self);
1680 if (!make_key_dbt(self, keyobj, &key, &flags))
1681 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001682 if (!checkTxnObj(txnobj, &txn)) {
1683 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001684 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001685 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 CLEAR_DBT(data);
1687
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001688 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1689 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 data.flags = DB_DBT_USERMEM;
1691 data.ulen = 0;
1692 MYDB_BEGIN_ALLOW_THREADS;
1693 err = self->db->get(self->db, txn, &key, &data, flags);
1694 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001695 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 retval = PyInt_FromLong((long)data.size);
1697 err = 0;
1698 }
1699
1700 FREE_DBT(key);
1701 FREE_DBT(data);
1702 RETURN_IF_ERR();
1703 return retval;
1704}
1705
1706
1707static PyObject*
1708DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1709{
1710 int err, flags=0;
1711 PyObject* txnobj = NULL;
1712 PyObject* keyobj;
1713 PyObject* dataobj;
1714 PyObject* retval = NULL;
1715 DBT key, data;
Neal Norwitzdf738022007-05-20 02:14:48 +00001716 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001718 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719
1720
1721 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1722 &keyobj, &dataobj, &txnobj, &flags))
1723 return NULL;
1724
1725 CHECK_DB_NOT_CLOSED(self);
1726 if (!make_key_dbt(self, keyobj, &key, NULL))
1727 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001728 if ( !make_dbt(dataobj, &data) ||
1729 !checkTxnObj(txnobj, &txn) )
1730 {
1731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001734
1735 flags |= DB_GET_BOTH;
Neal Norwitzdf738022007-05-20 02:14:48 +00001736 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001737
1738 if (CHECK_DBFLAG(self, DB_THREAD)) {
1739 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitzdf738022007-05-20 02:14:48 +00001740 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001741 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 }
1743
1744 MYDB_BEGIN_ALLOW_THREADS;
1745 err = self->db->get(self->db, txn, &key, &data, flags);
1746 MYDB_END_ALLOW_THREADS;
1747
Gregory P. Smithe9477062005-06-04 06:46:59 +00001748 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1749 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750 err = 0;
1751 Py_INCREF(Py_None);
1752 retval = Py_None;
1753 }
1754 else if (!err) {
Neal Norwitzdf738022007-05-20 02:14:48 +00001755 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitzdf738022007-05-20 02:14:48 +00001757
1758 /* Even though the flags require DB_DBT_MALLOC, data is not always
1759 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1760 if (data.data != orig_data)
1761 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001762 }
1763
1764 FREE_DBT(key);
1765 RETURN_IF_ERR();
1766 return retval;
1767}
1768
1769
1770static PyObject*
1771DB_get_byteswapped(DBObject* self, PyObject* args)
1772{
1773#if (DBVER >= 33)
1774 int err = 0;
1775#endif
1776 int retval = -1;
1777
1778 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
1782#if (DBVER >= 33)
1783 MYDB_BEGIN_ALLOW_THREADS;
1784 err = self->db->get_byteswapped(self->db, &retval);
1785 MYDB_END_ALLOW_THREADS;
1786 RETURN_IF_ERR();
1787#else
1788 MYDB_BEGIN_ALLOW_THREADS;
1789 retval = self->db->get_byteswapped(self->db);
1790 MYDB_END_ALLOW_THREADS;
1791#endif
1792 return PyInt_FromLong(retval);
1793}
1794
1795
1796static PyObject*
1797DB_get_type(DBObject* self, PyObject* args)
1798{
1799 int type;
1800
1801 if (!PyArg_ParseTuple(args,":get_type"))
1802 return NULL;
1803 CHECK_DB_NOT_CLOSED(self);
1804
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001806 if (type == -1)
1807 return NULL;
1808 return PyInt_FromLong(type);
1809}
1810
1811
1812static PyObject*
1813DB_join(DBObject* self, PyObject* args)
1814{
1815 int err, flags=0;
1816 int length, x;
1817 PyObject* cursorsObj;
1818 DBC** cursors;
1819 DBC* dbc;
1820
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1822 return NULL;
1823
1824 CHECK_DB_NOT_CLOSED(self);
1825
1826 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827 PyErr_SetString(PyExc_TypeError,
1828 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 return NULL;
1830 }
1831
1832 length = PyObject_Length(cursorsObj);
1833 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001834 if (!cursors) {
1835 PyErr_NoMemory();
1836 return NULL;
1837 }
1838
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001839 cursors[length] = NULL;
1840 for (x=0; x<length; x++) {
1841 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001842 if (item == NULL) {
1843 free(cursors);
1844 return NULL;
1845 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001847 PyErr_SetString(PyExc_TypeError,
1848 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849 free(cursors);
1850 return NULL;
1851 }
1852 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001853 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 }
1855
1856 MYDB_BEGIN_ALLOW_THREADS;
1857 err = self->db->join(self->db, cursors, &dbc, flags);
1858 MYDB_END_ALLOW_THREADS;
1859 free(cursors);
1860 RETURN_IF_ERR();
1861
Gregory P. Smith7441e652003-11-03 21:35:31 +00001862 /* FIXME: this is a buggy interface. The returned cursor
1863 contains internal references to the passed in cursors
1864 but does not hold python references to them or prevent
1865 them from being closed prematurely. This can cause
1866 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001867 return (PyObject*) newDBCursorObject(dbc, self);
1868}
1869
1870
1871static PyObject*
1872DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1873{
1874 int err, flags=0;
1875 PyObject* txnobj = NULL;
1876 PyObject* keyobj;
1877 DBT key;
1878 DB_TXN *txn = NULL;
1879 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001880 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001881
1882 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1883 &keyobj, &txnobj, &flags))
1884 return NULL;
1885 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001886 if (!make_dbt(keyobj, &key))
1887 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001888 return NULL;
1889 if (!checkTxnObj(txnobj, &txn))
1890 return NULL;
1891
1892 MYDB_BEGIN_ALLOW_THREADS;
1893 err = self->db->key_range(self->db, txn, &key, &range, flags);
1894 MYDB_END_ALLOW_THREADS;
1895
1896 RETURN_IF_ERR();
1897 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1898}
1899
1900
1901static PyObject*
1902DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1903{
1904 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1905 char* filename = NULL;
1906 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001907#if (DBVER >= 41)
1908 PyObject *txnobj = NULL;
1909 DB_TXN *txn = NULL;
1910 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001911 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001912 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1913 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001914 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001915 "filename", "dbtype", "flags", "mode", "txn", NULL};
1916#else
1917 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001918 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001919 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1920 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001921 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001922 "filename", "dbtype", "flags", "mode", NULL};
1923#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001925#if (DBVER >= 41)
1926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1927 &filename, &dbname, &type, &flags, &mode,
1928 &txnobj))
1929#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001931 &filename, &dbname, &type, &flags,
1932 &mode))
1933#endif
1934 {
1935 PyErr_Clear();
1936 type = DB_UNKNOWN; flags = 0; mode = 0660;
1937 filename = NULL; dbname = NULL;
1938#if (DBVER >= 41)
1939 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1940 kwnames_basic,
1941 &filename, &type, &flags, &mode,
1942 &txnobj))
1943 return NULL;
1944#else
1945 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1946 kwnames_basic,
1947 &filename, &type, &flags, &mode))
1948 return NULL;
1949#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 }
1951
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001952#if (DBVER >= 41)
1953 if (!checkTxnObj(txnobj, &txn)) return NULL;
1954#endif
1955
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001957 PyObject *t = Py_BuildValue("(is)", 0,
1958 "Cannot call open() twice for DB object");
1959 PyErr_SetObject(DBError, t);
1960 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 return NULL;
1962 }
1963
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001964#if 0 && (DBVER >= 41)
1965 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1966 && (self->myenvobj->flags & DB_INIT_TXN))
1967 {
1968 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1969 * explicitly passed) but we are in a transaction ready environment:
1970 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1971 * to work on BerkeleyDB 4.1 without needing to modify their
1972 * DBEnv or DB open calls.
1973 * TODO make this behaviour of the library configurable.
1974 */
1975 flags |= DB_AUTO_COMMIT;
1976 }
1977#endif
1978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001980#if (DBVER >= 41)
1981 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1982#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001984#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001985 MYDB_END_ALLOW_THREADS;
1986 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001987 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001988 self->db = NULL;
1989 return NULL;
1990 }
1991
1992 self->flags = flags;
1993 RETURN_NONE();
1994}
1995
1996
1997static PyObject*
1998DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1999{
2000 int flags=0;
2001 PyObject* txnobj = NULL;
2002 int dlen = -1;
2003 int doff = -1;
2004 PyObject* keyobj, *dataobj, *retval;
2005 DBT key, data;
2006 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002007 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002008 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002009
2010 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2011 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2012 return NULL;
2013
2014 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002015 if (!make_key_dbt(self, keyobj, &key, NULL))
2016 return NULL;
2017 if ( !make_dbt(dataobj, &data) ||
2018 !add_partial_dbt(&data, dlen, doff) ||
2019 !checkTxnObj(txnobj, &txn) )
2020 {
2021 FREE_DBT(key);
2022 return NULL;
2023 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002024
2025 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2026 FREE_DBT(key);
2027 return NULL;
2028 }
2029
2030 if (flags & DB_APPEND)
2031 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2032 else {
2033 retval = Py_None;
2034 Py_INCREF(retval);
2035 }
2036 FREE_DBT(key);
2037 return retval;
2038}
2039
2040
2041
2042static PyObject*
2043DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2044{
2045 char* filename;
2046 char* database = NULL;
2047 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002048 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002049
2050 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2051 &filename, &database, &flags))
2052 return NULL;
2053 CHECK_DB_NOT_CLOSED(self);
2054
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002055 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002056 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002057 RETURN_IF_ERR();
2058 RETURN_NONE();
2059}
2060
2061
2062
2063static PyObject*
2064DB_rename(DBObject* self, PyObject* args)
2065{
2066 char* filename;
2067 char* database;
2068 char* newname;
2069 int err, flags=0;
2070
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002071 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2072 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002073 return NULL;
2074 CHECK_DB_NOT_CLOSED(self);
2075
2076 MYDB_BEGIN_ALLOW_THREADS;
2077 err = self->db->rename(self->db, filename, database, newname, flags);
2078 MYDB_END_ALLOW_THREADS;
2079 RETURN_IF_ERR();
2080 RETURN_NONE();
2081}
2082
2083
2084static PyObject*
2085DB_set_bt_minkey(DBObject* self, PyObject* args)
2086{
2087 int err, minkey;
2088
2089 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2090 return NULL;
2091 CHECK_DB_NOT_CLOSED(self);
2092
2093 MYDB_BEGIN_ALLOW_THREADS;
2094 err = self->db->set_bt_minkey(self->db, minkey);
2095 MYDB_END_ALLOW_THREADS;
2096 RETURN_IF_ERR();
2097 RETURN_NONE();
2098}
2099
Neal Norwitz84562352005-10-20 04:30:15 +00002100#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002101static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002102_default_cmp(const DBT *leftKey,
2103 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104{
2105 int res;
2106 int lsize = leftKey->size, rsize = rightKey->size;
2107
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 res = memcmp(leftKey->data, rightKey->data,
2109 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002110
2111 if (res == 0) {
2112 if (lsize < rsize) {
2113 res = -1;
2114 }
2115 else if (lsize > rsize) {
2116 res = 1;
2117 }
2118 }
2119 return res;
2120}
2121
2122static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002123_db_compareCallback(DB* db,
2124 const DBT *leftKey,
2125 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126{
2127 int res = 0;
2128 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002129 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131
2132 if (self == NULL || self->btCompareCallback == NULL) {
2133 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 PyErr_SetString(PyExc_TypeError,
2135 (self == 0
2136 ? "DB_bt_compare db is NULL."
2137 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002138 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002139 PyErr_Print();
2140 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002141 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002142 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002143 MYDB_BEGIN_BLOCK_THREADS;
2144
Thomas Woutersb3153832006-03-08 01:47:19 +00002145 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2146 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002148 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002149 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002151 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002152 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002153 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002154 PyErr_Print();
2155 res = _default_cmp(leftKey, rightKey);
2156 } else if (PyInt_Check(result)) {
2157 res = PyInt_AsLong(result);
2158 } else {
2159 PyErr_SetString(PyExc_TypeError,
2160 "DB_bt_compare callback MUST return an int.");
2161 /* we're in a callback within the DB code, we can't raise */
2162 PyErr_Print();
2163 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164 }
2165
Thomas Woutersb3153832006-03-08 01:47:19 +00002166 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002167 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002168
2169 MYDB_END_BLOCK_THREADS;
2170 }
2171 return res;
2172}
2173
2174static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002175DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002176{
2177 int err;
2178 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002179 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002180
Georg Brandlef1701f2006-03-07 14:57:48 +00002181 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182 return NULL;
2183
Georg Brandlef1701f2006-03-07 14:57:48 +00002184 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002185
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 if (!PyCallable_Check(comparator)) {
2187 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188 return NULL;
2189 }
2190
2191 /*
2192 * Perform a test call of the comparator function with two empty
2193 * string objects here. verify that it returns an int (0).
2194 * err if not.
2195 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002196 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002197 result = PyEval_CallObject(comparator, tuple);
2198 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002199 if (result == NULL)
2200 return NULL;
2201 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002202 PyErr_SetString(PyExc_TypeError,
2203 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002205 } else if (PyInt_AsLong(result) != 0) {
2206 PyErr_SetString(PyExc_TypeError,
2207 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002208 return NULL;
2209 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002210 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211
2212 /* We don't accept multiple set_bt_compare operations, in order to
2213 * simplify the code. This would have no real use, as one cannot
2214 * change the function once the db is opened anyway */
2215 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002216 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002217 return NULL;
2218 }
2219
Georg Brandlef1701f2006-03-07 14:57:48 +00002220 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002221 self->btCompareCallback = comparator;
2222
2223 /* This is to workaround a problem with un-initialized threads (see
2224 comment in DB_associate) */
2225#ifdef WITH_THREAD
2226 PyEval_InitThreads();
2227#endif
2228
Thomas Woutersb3153832006-03-08 01:47:19 +00002229 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002230
2231 if (err) {
2232 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002233 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002234 self->btCompareCallback = NULL;
2235 }
2236
Georg Brandlef1701f2006-03-07 14:57:48 +00002237 RETURN_IF_ERR();
2238 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002239}
Neal Norwitz84562352005-10-20 04:30:15 +00002240#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002241
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002242
2243static PyObject*
2244DB_set_cachesize(DBObject* self, PyObject* args)
2245{
2246 int err;
2247 int gbytes = 0, bytes = 0, ncache = 0;
2248
2249 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2250 &gbytes,&bytes,&ncache))
2251 return NULL;
2252 CHECK_DB_NOT_CLOSED(self);
2253
2254 MYDB_BEGIN_ALLOW_THREADS;
2255 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2256 MYDB_END_ALLOW_THREADS;
2257 RETURN_IF_ERR();
2258 RETURN_NONE();
2259}
2260
2261
2262static PyObject*
2263DB_set_flags(DBObject* self, PyObject* args)
2264{
2265 int err, flags;
2266
2267 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2268 return NULL;
2269 CHECK_DB_NOT_CLOSED(self);
2270
2271 MYDB_BEGIN_ALLOW_THREADS;
2272 err = self->db->set_flags(self->db, flags);
2273 MYDB_END_ALLOW_THREADS;
2274 RETURN_IF_ERR();
2275
2276 self->setflags |= flags;
2277 RETURN_NONE();
2278}
2279
2280
2281static PyObject*
2282DB_set_h_ffactor(DBObject* self, PyObject* args)
2283{
2284 int err, ffactor;
2285
2286 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2287 return NULL;
2288 CHECK_DB_NOT_CLOSED(self);
2289
2290 MYDB_BEGIN_ALLOW_THREADS;
2291 err = self->db->set_h_ffactor(self->db, ffactor);
2292 MYDB_END_ALLOW_THREADS;
2293 RETURN_IF_ERR();
2294 RETURN_NONE();
2295}
2296
2297
2298static PyObject*
2299DB_set_h_nelem(DBObject* self, PyObject* args)
2300{
2301 int err, nelem;
2302
2303 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2304 return NULL;
2305 CHECK_DB_NOT_CLOSED(self);
2306
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->set_h_nelem(self->db, nelem);
2309 MYDB_END_ALLOW_THREADS;
2310 RETURN_IF_ERR();
2311 RETURN_NONE();
2312}
2313
2314
2315static PyObject*
2316DB_set_lorder(DBObject* self, PyObject* args)
2317{
2318 int err, lorder;
2319
2320 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2321 return NULL;
2322 CHECK_DB_NOT_CLOSED(self);
2323
2324 MYDB_BEGIN_ALLOW_THREADS;
2325 err = self->db->set_lorder(self->db, lorder);
2326 MYDB_END_ALLOW_THREADS;
2327 RETURN_IF_ERR();
2328 RETURN_NONE();
2329}
2330
2331
2332static PyObject*
2333DB_set_pagesize(DBObject* self, PyObject* args)
2334{
2335 int err, pagesize;
2336
2337 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2338 return NULL;
2339 CHECK_DB_NOT_CLOSED(self);
2340
2341 MYDB_BEGIN_ALLOW_THREADS;
2342 err = self->db->set_pagesize(self->db, pagesize);
2343 MYDB_END_ALLOW_THREADS;
2344 RETURN_IF_ERR();
2345 RETURN_NONE();
2346}
2347
2348
2349static PyObject*
2350DB_set_re_delim(DBObject* self, PyObject* args)
2351{
2352 int err;
2353 char delim;
2354
2355 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2356 PyErr_Clear();
2357 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2358 return NULL;
2359 }
2360
2361 CHECK_DB_NOT_CLOSED(self);
2362
2363 MYDB_BEGIN_ALLOW_THREADS;
2364 err = self->db->set_re_delim(self->db, delim);
2365 MYDB_END_ALLOW_THREADS;
2366 RETURN_IF_ERR();
2367 RETURN_NONE();
2368}
2369
2370static PyObject*
2371DB_set_re_len(DBObject* self, PyObject* args)
2372{
2373 int err, len;
2374
2375 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2376 return NULL;
2377 CHECK_DB_NOT_CLOSED(self);
2378
2379 MYDB_BEGIN_ALLOW_THREADS;
2380 err = self->db->set_re_len(self->db, len);
2381 MYDB_END_ALLOW_THREADS;
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2384}
2385
2386
2387static PyObject*
2388DB_set_re_pad(DBObject* self, PyObject* args)
2389{
2390 int err;
2391 char pad;
2392
2393 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2394 PyErr_Clear();
2395 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2396 return NULL;
2397 }
2398 CHECK_DB_NOT_CLOSED(self);
2399
2400 MYDB_BEGIN_ALLOW_THREADS;
2401 err = self->db->set_re_pad(self->db, pad);
2402 MYDB_END_ALLOW_THREADS;
2403 RETURN_IF_ERR();
2404 RETURN_NONE();
2405}
2406
2407
2408static PyObject*
2409DB_set_re_source(DBObject* self, PyObject* args)
2410{
2411 int err;
2412 char *re_source;
2413
2414 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2415 return NULL;
2416 CHECK_DB_NOT_CLOSED(self);
2417
2418 MYDB_BEGIN_ALLOW_THREADS;
2419 err = self->db->set_re_source(self->db, re_source);
2420 MYDB_END_ALLOW_THREADS;
2421 RETURN_IF_ERR();
2422 RETURN_NONE();
2423}
2424
2425
2426#if (DBVER >= 32)
2427static PyObject*
2428DB_set_q_extentsize(DBObject* self, PyObject* args)
2429{
2430 int err;
2431 int extentsize;
2432
2433 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2434 return NULL;
2435 CHECK_DB_NOT_CLOSED(self);
2436
2437 MYDB_BEGIN_ALLOW_THREADS;
2438 err = self->db->set_q_extentsize(self->db, extentsize);
2439 MYDB_END_ALLOW_THREADS;
2440 RETURN_IF_ERR();
2441 RETURN_NONE();
2442}
2443#endif
2444
2445static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002446DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002447{
2448 int err, flags = 0, type;
2449 void* sp;
2450 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#if (DBVER >= 43)
2452 PyObject* txnobj = NULL;
2453 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002454 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002455#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002456 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002457#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002458
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002459#if (DBVER >= 43)
2460 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2461 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002462 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002463 if (!checkTxnObj(txnobj, &txn))
2464 return NULL;
2465#else
2466 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2467 return NULL;
2468#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002469 CHECK_DB_NOT_CLOSED(self);
2470
2471 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002472#if (DBVER >= 43)
2473 err = self->db->stat(self->db, txn, &sp, flags);
2474#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002475 err = self->db->stat(self->db, &sp, flags);
2476#else
2477 err = self->db->stat(self->db, &sp, NULL, flags);
2478#endif
2479 MYDB_END_ALLOW_THREADS;
2480 RETURN_IF_ERR();
2481
2482 self->haveStat = 1;
2483
2484 /* Turn the stat structure into a dictionary */
2485 type = _DB_get_type(self);
2486 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2487 free(sp);
2488 return NULL;
2489 }
2490
2491#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2492#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2493#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2494
2495 switch (type) {
2496 case DB_HASH:
2497 MAKE_HASH_ENTRY(magic);
2498 MAKE_HASH_ENTRY(version);
2499 MAKE_HASH_ENTRY(nkeys);
2500 MAKE_HASH_ENTRY(ndata);
2501 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002502#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002503 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002504#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002505 MAKE_HASH_ENTRY(ffactor);
2506 MAKE_HASH_ENTRY(buckets);
2507 MAKE_HASH_ENTRY(free);
2508 MAKE_HASH_ENTRY(bfree);
2509 MAKE_HASH_ENTRY(bigpages);
2510 MAKE_HASH_ENTRY(big_bfree);
2511 MAKE_HASH_ENTRY(overflows);
2512 MAKE_HASH_ENTRY(ovfl_free);
2513 MAKE_HASH_ENTRY(dup);
2514 MAKE_HASH_ENTRY(dup_free);
2515 break;
2516
2517 case DB_BTREE:
2518 case DB_RECNO:
2519 MAKE_BT_ENTRY(magic);
2520 MAKE_BT_ENTRY(version);
2521 MAKE_BT_ENTRY(nkeys);
2522 MAKE_BT_ENTRY(ndata);
2523 MAKE_BT_ENTRY(pagesize);
2524 MAKE_BT_ENTRY(minkey);
2525 MAKE_BT_ENTRY(re_len);
2526 MAKE_BT_ENTRY(re_pad);
2527 MAKE_BT_ENTRY(levels);
2528 MAKE_BT_ENTRY(int_pg);
2529 MAKE_BT_ENTRY(leaf_pg);
2530 MAKE_BT_ENTRY(dup_pg);
2531 MAKE_BT_ENTRY(over_pg);
2532 MAKE_BT_ENTRY(free);
2533 MAKE_BT_ENTRY(int_pgfree);
2534 MAKE_BT_ENTRY(leaf_pgfree);
2535 MAKE_BT_ENTRY(dup_pgfree);
2536 MAKE_BT_ENTRY(over_pgfree);
2537 break;
2538
2539 case DB_QUEUE:
2540 MAKE_QUEUE_ENTRY(magic);
2541 MAKE_QUEUE_ENTRY(version);
2542 MAKE_QUEUE_ENTRY(nkeys);
2543 MAKE_QUEUE_ENTRY(ndata);
2544 MAKE_QUEUE_ENTRY(pagesize);
2545 MAKE_QUEUE_ENTRY(pages);
2546 MAKE_QUEUE_ENTRY(re_len);
2547 MAKE_QUEUE_ENTRY(re_pad);
2548 MAKE_QUEUE_ENTRY(pgfree);
2549#if (DBVER == 31)
2550 MAKE_QUEUE_ENTRY(start);
2551#endif
2552 MAKE_QUEUE_ENTRY(first_recno);
2553 MAKE_QUEUE_ENTRY(cur_recno);
2554 break;
2555
2556 default:
2557 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2558 Py_DECREF(d);
2559 d = NULL;
2560 }
2561
2562#undef MAKE_HASH_ENTRY
2563#undef MAKE_BT_ENTRY
2564#undef MAKE_QUEUE_ENTRY
2565
2566 free(sp);
2567 return d;
2568}
2569
2570static PyObject*
2571DB_sync(DBObject* self, PyObject* args)
2572{
2573 int err;
2574 int flags = 0;
2575
2576 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2577 return NULL;
2578 CHECK_DB_NOT_CLOSED(self);
2579
2580 MYDB_BEGIN_ALLOW_THREADS;
2581 err = self->db->sync(self->db, flags);
2582 MYDB_END_ALLOW_THREADS;
2583 RETURN_IF_ERR();
2584 RETURN_NONE();
2585}
2586
2587
2588#if (DBVER >= 33)
2589static PyObject*
2590DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2591{
2592 int err, flags=0;
2593 u_int32_t count=0;
2594 PyObject* txnobj = NULL;
2595 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002596 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002597
2598 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2599 &txnobj, &flags))
2600 return NULL;
2601 CHECK_DB_NOT_CLOSED(self);
2602 if (!checkTxnObj(txnobj, &txn))
2603 return NULL;
2604
2605 MYDB_BEGIN_ALLOW_THREADS;
2606 err = self->db->truncate(self->db, txn, &count, flags);
2607 MYDB_END_ALLOW_THREADS;
2608 RETURN_IF_ERR();
2609 return PyInt_FromLong(count);
2610}
2611#endif
2612
2613
2614static PyObject*
2615DB_upgrade(DBObject* self, PyObject* args)
2616{
2617 int err, flags=0;
2618 char *filename;
2619
2620 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2621 return NULL;
2622 CHECK_DB_NOT_CLOSED(self);
2623
2624 MYDB_BEGIN_ALLOW_THREADS;
2625 err = self->db->upgrade(self->db, filename, flags);
2626 MYDB_END_ALLOW_THREADS;
2627 RETURN_IF_ERR();
2628 RETURN_NONE();
2629}
2630
2631
2632static PyObject*
2633DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2634{
2635 int err, flags=0;
2636 char* fileName;
2637 char* dbName=NULL;
2638 char* outFileName=NULL;
2639 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002640 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002641 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002642
2643 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2644 &fileName, &dbName, &outFileName, &flags))
2645 return NULL;
2646
2647 CHECK_DB_NOT_CLOSED(self);
2648 if (outFileName)
2649 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002650 /* XXX(nnorwitz): it should probably be an exception if outFile
2651 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002652
2653 MYDB_BEGIN_ALLOW_THREADS;
2654 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2655 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002656 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002657 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002658
2659 /* DB.verify acts as a DB handle destructor (like close); this was
2660 * documented in BerkeleyDB 4.2 but had the undocumented effect
2661 * of not being safe in prior versions while still requiring an explicit
2662 * DB.close call afterwards. Lets call close for the user to emulate
2663 * the safe 4.2 behaviour. */
2664#if (DBVER <= 41)
2665 self->db->close(self->db, 0);
2666#endif
2667 self->db = NULL;
2668
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002669 RETURN_IF_ERR();
2670 RETURN_NONE();
2671}
2672
2673
2674static PyObject*
2675DB_set_get_returns_none(DBObject* self, PyObject* args)
2676{
2677 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002678 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002679
2680 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2681 return NULL;
2682 CHECK_DB_NOT_CLOSED(self);
2683
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002684 if (self->moduleFlags.getReturnsNone)
2685 ++oldValue;
2686 if (self->moduleFlags.cursorSetReturnsNone)
2687 ++oldValue;
2688 self->moduleFlags.getReturnsNone = (flags >= 1);
2689 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002690 return PyInt_FromLong(oldValue);
2691}
2692
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002693#if (DBVER >= 41)
2694static PyObject*
2695DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2696{
2697 int err;
2698 u_int32_t flags=0;
2699 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002700 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002701
2702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2703 &passwd, &flags)) {
2704 return NULL;
2705 }
2706
2707 MYDB_BEGIN_ALLOW_THREADS;
2708 err = self->db->set_encrypt(self->db, passwd, flags);
2709 MYDB_END_ALLOW_THREADS;
2710
2711 RETURN_IF_ERR();
2712 RETURN_NONE();
2713}
2714#endif /* DBVER >= 41 */
2715
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716
2717/*-------------------------------------------------------------- */
2718/* Mapping and Dictionary-like access routines */
2719
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002720Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721{
2722 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002723 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002724 int flags = 0;
2725 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002726 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727
2728 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002729 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2730 PyErr_SetObject(DBError, t);
2731 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732 return -1;
2733 }
2734
2735 if (self->haveStat) { /* Has the stat function been called recently? If
2736 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002737 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002738 }
2739
2740 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002741redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002742#if (DBVER >= 43)
2743 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2744#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002745 err = self->db->stat(self->db, &sp, flags);
2746#else
2747 err = self->db->stat(self->db, &sp, NULL, flags);
2748#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002749
2750 /* All the stat structures have matching fields upto the ndata field,
2751 so we can use any of them for the type cast */
2752 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2753
2754 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2755 * redo a full stat to make sure.
2756 * Fixes SF python bug 1493322, pybsddb bug 1184012
2757 */
2758 if (size == 0 && (flags & DB_FAST_STAT)) {
2759 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002760 if (!err)
2761 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002762 goto redo_stat_for_length;
2763 }
2764
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002765 MYDB_END_ALLOW_THREADS;
2766
2767 if (err)
2768 return -1;
2769
2770 self->haveStat = 1;
2771
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002772 free(sp);
2773 return size;
2774}
2775
2776
2777PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2778{
2779 int err;
2780 PyObject* retval;
2781 DBT key;
2782 DBT data;
2783
2784 CHECK_DB_NOT_CLOSED(self);
2785 if (!make_key_dbt(self, keyobj, &key, NULL))
2786 return NULL;
2787
2788 CLEAR_DBT(data);
2789 if (CHECK_DBFLAG(self, DB_THREAD)) {
2790 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2791 data.flags = DB_DBT_MALLOC;
2792 }
2793 MYDB_BEGIN_ALLOW_THREADS;
2794 err = self->db->get(self->db, NULL, &key, &data, 0);
2795 MYDB_END_ALLOW_THREADS;
2796 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2797 PyErr_SetObject(PyExc_KeyError, keyobj);
2798 retval = NULL;
2799 }
2800 else if (makeDBError(err)) {
2801 retval = NULL;
2802 }
2803 else {
2804 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2805 FREE_DBT(data);
2806 }
2807
2808 FREE_DBT(key);
2809 return retval;
2810}
2811
2812
2813static int
2814DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2815{
2816 DBT key, data;
2817 int retval;
2818 int flags = 0;
2819
2820 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002821 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2822 PyErr_SetObject(DBError, t);
2823 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824 return -1;
2825 }
2826
2827 if (!make_key_dbt(self, keyobj, &key, NULL))
2828 return -1;
2829
2830 if (dataobj != NULL) {
2831 if (!make_dbt(dataobj, &data))
2832 retval = -1;
2833 else {
2834 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002835 /* dictionaries shouldn't have duplicate keys */
2836 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002837 retval = _DB_put(self, NULL, &key, &data, flags);
2838
2839 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002840 /* try deleting any old record that matches and then PUT it
2841 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002842 _DB_delete(self, NULL, &key, 0);
2843 PyErr_Clear();
2844 retval = _DB_put(self, NULL, &key, &data, flags);
2845 }
2846 }
2847 }
2848 else {
2849 /* dataobj == NULL, so delete the key */
2850 retval = _DB_delete(self, NULL, &key, 0);
2851 }
2852 FREE_DBT(key);
2853 return retval;
2854}
2855
2856
2857static PyObject*
2858DB_has_key(DBObject* self, PyObject* args)
2859{
2860 int err;
2861 PyObject* keyobj;
2862 DBT key, data;
2863 PyObject* txnobj = NULL;
2864 DB_TXN *txn = NULL;
2865
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002866 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002867 return NULL;
2868 CHECK_DB_NOT_CLOSED(self);
2869 if (!make_key_dbt(self, keyobj, &key, NULL))
2870 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002871 if (!checkTxnObj(txnobj, &txn)) {
2872 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002874 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002876 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002877 it has a record but can't allocate a buffer for the data. This saves
2878 having to deal with data we won't be using.
2879 */
2880 CLEAR_DBT(data);
2881 data.flags = DB_DBT_USERMEM;
2882
2883 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002884 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002885 MYDB_END_ALLOW_THREADS;
2886 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002887
2888 if (err == DB_BUFFER_SMALL || err == 0) {
2889 return PyInt_FromLong(1);
2890 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2891 return PyInt_FromLong(0);
2892 }
2893
2894 makeDBError(err);
2895 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002896}
2897
2898
2899#define _KEYS_LIST 1
2900#define _VALUES_LIST 2
2901#define _ITEMS_LIST 3
2902
2903static PyObject*
2904_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2905{
2906 int err, dbtype;
2907 DBT key;
2908 DBT data;
2909 DBC *cursor;
2910 PyObject* list;
2911 PyObject* item = NULL;
2912
2913 CHECK_DB_NOT_CLOSED(self);
2914 CLEAR_DBT(key);
2915 CLEAR_DBT(data);
2916
2917 dbtype = _DB_get_type(self);
2918 if (dbtype == -1)
2919 return NULL;
2920
2921 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002922 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924
2925 /* get a cursor */
2926 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002927 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002928 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002929 if (makeDBError(err)) {
2930 Py_DECREF(list);
2931 return NULL;
2932 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002933
2934 if (CHECK_DBFLAG(self, DB_THREAD)) {
2935 key.flags = DB_DBT_REALLOC;
2936 data.flags = DB_DBT_REALLOC;
2937 }
2938
2939 while (1) { /* use the cursor to traverse the DB, collecting items */
2940 MYDB_BEGIN_ALLOW_THREADS;
2941 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2942 MYDB_END_ALLOW_THREADS;
2943
2944 if (err) {
2945 /* for any error, break out of the loop */
2946 break;
2947 }
2948
2949 switch (type) {
2950 case _KEYS_LIST:
2951 switch(dbtype) {
2952 case DB_BTREE:
2953 case DB_HASH:
2954 default:
2955 item = PyString_FromStringAndSize((char*)key.data, key.size);
2956 break;
2957 case DB_RECNO:
2958 case DB_QUEUE:
2959 item = PyInt_FromLong(*((db_recno_t*)key.data));
2960 break;
2961 }
2962 break;
2963
2964 case _VALUES_LIST:
2965 item = PyString_FromStringAndSize((char*)data.data, data.size);
2966 break;
2967
2968 case _ITEMS_LIST:
2969 switch(dbtype) {
2970 case DB_BTREE:
2971 case DB_HASH:
2972 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002973 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2974 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975 break;
2976 case DB_RECNO:
2977 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002978 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2979 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 break;
2981 }
2982 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002983 default:
2984 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2985 item = NULL;
2986 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002987 }
2988 if (item == NULL) {
2989 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990 list = NULL;
2991 goto done;
2992 }
2993 PyList_Append(list, item);
2994 Py_DECREF(item);
2995 }
2996
Gregory P. Smithe9477062005-06-04 06:46:59 +00002997 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2998 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002999 Py_DECREF(list);
3000 list = NULL;
3001 }
3002
3003 done:
3004 FREE_DBT(key);
3005 FREE_DBT(data);
3006 MYDB_BEGIN_ALLOW_THREADS;
3007 cursor->c_close(cursor);
3008 MYDB_END_ALLOW_THREADS;
3009 return list;
3010}
3011
3012
3013static PyObject*
3014DB_keys(DBObject* self, PyObject* args)
3015{
3016 PyObject* txnobj = NULL;
3017 DB_TXN *txn = NULL;
3018
Georg Brandl96a8c392006-05-29 21:04:52 +00003019 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003020 return NULL;
3021 if (!checkTxnObj(txnobj, &txn))
3022 return NULL;
3023 return _DB_make_list(self, txn, _KEYS_LIST);
3024}
3025
3026
3027static PyObject*
3028DB_items(DBObject* self, PyObject* args)
3029{
3030 PyObject* txnobj = NULL;
3031 DB_TXN *txn = NULL;
3032
Georg Brandl96a8c392006-05-29 21:04:52 +00003033 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034 return NULL;
3035 if (!checkTxnObj(txnobj, &txn))
3036 return NULL;
3037 return _DB_make_list(self, txn, _ITEMS_LIST);
3038}
3039
3040
3041static PyObject*
3042DB_values(DBObject* self, PyObject* args)
3043{
3044 PyObject* txnobj = NULL;
3045 DB_TXN *txn = NULL;
3046
Georg Brandl96a8c392006-05-29 21:04:52 +00003047 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003048 return NULL;
3049 if (!checkTxnObj(txnobj, &txn))
3050 return NULL;
3051 return _DB_make_list(self, txn, _VALUES_LIST);
3052}
3053
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003054/* --------------------------------------------------------------------- */
3055/* DBCursor methods */
3056
3057
3058static PyObject*
3059DBC_close(DBCursorObject* self, PyObject* args)
3060{
3061 int err = 0;
3062
3063 if (!PyArg_ParseTuple(args, ":close"))
3064 return NULL;
3065
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003066 if (self->dbc != NULL) {
3067 MYDB_BEGIN_ALLOW_THREADS;
3068 err = self->dbc->c_close(self->dbc);
3069 self->dbc = NULL;
3070 MYDB_END_ALLOW_THREADS;
3071 }
3072 RETURN_IF_ERR();
3073 RETURN_NONE();
3074}
3075
3076
3077static PyObject*
3078DBC_count(DBCursorObject* self, PyObject* args)
3079{
3080 int err = 0;
3081 db_recno_t count;
3082 int flags = 0;
3083
3084 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3085 return NULL;
3086
3087 CHECK_CURSOR_NOT_CLOSED(self);
3088
3089 MYDB_BEGIN_ALLOW_THREADS;
3090 err = self->dbc->c_count(self->dbc, &count, flags);
3091 MYDB_END_ALLOW_THREADS;
3092 RETURN_IF_ERR();
3093
3094 return PyInt_FromLong(count);
3095}
3096
3097
3098static PyObject*
3099DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3100{
3101 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3102}
3103
3104
3105static PyObject*
3106DBC_delete(DBCursorObject* self, PyObject* args)
3107{
3108 int err, flags=0;
3109
3110 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3111 return NULL;
3112
3113 CHECK_CURSOR_NOT_CLOSED(self);
3114
3115 MYDB_BEGIN_ALLOW_THREADS;
3116 err = self->dbc->c_del(self->dbc, flags);
3117 MYDB_END_ALLOW_THREADS;
3118 RETURN_IF_ERR();
3119
3120 self->mydb->haveStat = 0;
3121 RETURN_NONE();
3122}
3123
3124
3125static PyObject*
3126DBC_dup(DBCursorObject* self, PyObject* args)
3127{
3128 int err, flags =0;
3129 DBC* dbc = NULL;
3130
3131 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3132 return NULL;
3133
3134 CHECK_CURSOR_NOT_CLOSED(self);
3135
3136 MYDB_BEGIN_ALLOW_THREADS;
3137 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3138 MYDB_END_ALLOW_THREADS;
3139 RETURN_IF_ERR();
3140
3141 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3142}
3143
3144static PyObject*
3145DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3146{
3147 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3148}
3149
3150
3151static PyObject*
3152DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3153{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003154 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003155 PyObject* keyobj = NULL;
3156 PyObject* dataobj = NULL;
3157 PyObject* retval = NULL;
3158 int dlen = -1;
3159 int doff = -1;
3160 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003161 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003162 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163
3164 CLEAR_DBT(key);
3165 CLEAR_DBT(data);
3166 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003167 &flags, &dlen, &doff))
3168 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003170 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3171 &kwnames[1],
3172 &keyobj, &flags, &dlen, &doff))
3173 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003175 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3176 kwnames, &keyobj, &dataobj,
3177 &flags, &dlen, &doff))
3178 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 return NULL;
3180 }
3181 }
3182 }
3183
3184 CHECK_CURSOR_NOT_CLOSED(self);
3185
3186 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3187 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003188 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3189 (!add_partial_dbt(&data, dlen, doff)) )
3190 {
3191 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003192 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003193 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194
3195 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3196 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003197 if (!(key.flags & DB_DBT_REALLOC)) {
3198 key.flags |= DB_DBT_MALLOC;
3199 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003200 }
3201
3202 MYDB_BEGIN_ALLOW_THREADS;
3203 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3204 MYDB_END_ALLOW_THREADS;
3205
Gregory P. Smithe9477062005-06-04 06:46:59 +00003206 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3207 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 Py_INCREF(Py_None);
3209 retval = Py_None;
3210 }
3211 else if (makeDBError(err)) {
3212 retval = NULL;
3213 }
3214 else {
3215 switch (_DB_get_type(self->mydb)) {
3216 case -1:
3217 retval = NULL;
3218 break;
3219 case DB_BTREE:
3220 case DB_HASH:
3221 default:
3222 retval = Py_BuildValue("s#s#", key.data, key.size,
3223 data.data, data.size);
3224 break;
3225 case DB_RECNO:
3226 case DB_QUEUE:
3227 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3228 data.data, data.size);
3229 break;
3230 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003231 FREE_DBT(data);
3232 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003233 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003234 return retval;
3235}
3236
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003237#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003238static PyObject*
3239DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3240{
3241 int err, flags=0;
3242 PyObject* keyobj = NULL;
3243 PyObject* dataobj = NULL;
3244 PyObject* retval = NULL;
3245 int dlen = -1;
3246 int doff = -1;
3247 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003248 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3249 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003250
3251 CLEAR_DBT(key);
3252 CLEAR_DBT(data);
3253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3254 &flags, &dlen, &doff))
3255 {
3256 PyErr_Clear();
3257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003258 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003259 &keyobj, &flags, &dlen, &doff))
3260 {
3261 PyErr_Clear();
3262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3263 kwnames, &keyobj, &dataobj,
3264 &flags, &dlen, &doff))
3265 {
3266 return NULL;
3267 }
3268 }
3269 }
3270
3271 CHECK_CURSOR_NOT_CLOSED(self);
3272
3273 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3274 return NULL;
3275 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3276 (!add_partial_dbt(&data, dlen, doff)) ) {
3277 FREE_DBT(key);
3278 return NULL;
3279 }
3280
3281 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3282 data.flags = DB_DBT_MALLOC;
3283 if (!(key.flags & DB_DBT_REALLOC)) {
3284 key.flags |= DB_DBT_MALLOC;
3285 }
3286 }
3287
3288 CLEAR_DBT(pkey);
3289 pkey.flags = DB_DBT_MALLOC;
3290
3291 MYDB_BEGIN_ALLOW_THREADS;
3292 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3293 MYDB_END_ALLOW_THREADS;
3294
Gregory P. Smithe9477062005-06-04 06:46:59 +00003295 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3296 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003297 Py_INCREF(Py_None);
3298 retval = Py_None;
3299 }
3300 else if (makeDBError(err)) {
3301 retval = NULL;
3302 }
3303 else {
3304 PyObject *pkeyObj;
3305 PyObject *dataObj;
3306 dataObj = PyString_FromStringAndSize(data.data, data.size);
3307
3308 if (self->mydb->primaryDBType == DB_RECNO ||
3309 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003310 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 else
3312 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3313
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003314 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315 {
3316 PyObject *keyObj;
3317 int type = _DB_get_type(self->mydb);
3318 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003319 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003320 else
3321 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003322#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003323 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003324#else
3325 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3326#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003327 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003328 FREE_DBT(key);
3329 }
3330 else /* return just the pkey and data */
3331 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003332#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003333 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003334#else
3335 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3336#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003337 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003338 Py_DECREF(dataObj);
3339 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003340 FREE_DBT(pkey);
3341 FREE_DBT(data);
3342 }
3343 /* the only time REALLOC should be set is if we used an integer
3344 * key that make_key_dbt malloc'd for us. always free these. */
3345 if (key.flags & DB_DBT_REALLOC) {
3346 FREE_DBT(key);
3347 }
3348 return retval;
3349}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003350#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003351
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003352
3353static PyObject*
3354DBC_get_recno(DBCursorObject* self, PyObject* args)
3355{
3356 int err;
3357 db_recno_t recno;
3358 DBT key;
3359 DBT data;
3360
3361 if (!PyArg_ParseTuple(args, ":get_recno"))
3362 return NULL;
3363
3364 CHECK_CURSOR_NOT_CLOSED(self);
3365
3366 CLEAR_DBT(key);
3367 CLEAR_DBT(data);
3368 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3369 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3370 data.flags = DB_DBT_MALLOC;
3371 key.flags = DB_DBT_MALLOC;
3372 }
3373
3374 MYDB_BEGIN_ALLOW_THREADS;
3375 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3376 MYDB_END_ALLOW_THREADS;
3377 RETURN_IF_ERR();
3378
3379 recno = *((db_recno_t*)data.data);
3380 FREE_DBT(key);
3381 FREE_DBT(data);
3382 return PyInt_FromLong(recno);
3383}
3384
3385
3386static PyObject*
3387DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3388{
3389 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3390}
3391
3392
3393static PyObject*
3394DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3395{
3396 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3397}
3398
3399
3400static PyObject*
3401DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3402{
3403 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3404}
3405
3406
3407static PyObject*
3408DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3409{
3410 int err, flags = 0;
3411 PyObject* keyobj, *dataobj;
3412 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003413 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003414 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415 int dlen = -1;
3416 int doff = -1;
3417
3418 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3419 &keyobj, &dataobj, &flags, &dlen, &doff))
3420 return NULL;
3421
3422 CHECK_CURSOR_NOT_CLOSED(self);
3423
3424 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3425 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003426 if (!make_dbt(dataobj, &data) ||
3427 !add_partial_dbt(&data, dlen, doff) )
3428 {
3429 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003430 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003431 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432
3433 MYDB_BEGIN_ALLOW_THREADS;
3434 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3435 MYDB_END_ALLOW_THREADS;
3436 FREE_DBT(key);
3437 RETURN_IF_ERR();
3438 self->mydb->haveStat = 0;
3439 RETURN_NONE();
3440}
3441
3442
3443static PyObject*
3444DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3445{
3446 int err, flags = 0;
3447 DBT key, data;
3448 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003449 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003450 int dlen = -1;
3451 int doff = -1;
3452
3453 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3454 &keyobj, &flags, &dlen, &doff))
3455 return NULL;
3456
3457 CHECK_CURSOR_NOT_CLOSED(self);
3458
3459 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3460 return NULL;
3461
3462 CLEAR_DBT(data);
3463 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3464 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3465 data.flags = DB_DBT_MALLOC;
3466 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003467 if (!add_partial_dbt(&data, dlen, doff)) {
3468 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003470 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471
3472 MYDB_BEGIN_ALLOW_THREADS;
3473 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3474 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003475 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3476 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003477 Py_INCREF(Py_None);
3478 retval = Py_None;
3479 }
3480 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 retval = NULL;
3482 }
3483 else {
3484 switch (_DB_get_type(self->mydb)) {
3485 case -1:
3486 retval = NULL;
3487 break;
3488 case DB_BTREE:
3489 case DB_HASH:
3490 default:
3491 retval = Py_BuildValue("s#s#", key.data, key.size,
3492 data.data, data.size);
3493 break;
3494 case DB_RECNO:
3495 case DB_QUEUE:
3496 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3497 data.data, data.size);
3498 break;
3499 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003500 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003501 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003502 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003503 /* the only time REALLOC should be set is if we used an integer
3504 * key that make_key_dbt malloc'd for us. always free these. */
3505 if (key.flags & DB_DBT_REALLOC) {
3506 FREE_DBT(key);
3507 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003508
3509 return retval;
3510}
3511
3512
3513static PyObject*
3514DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3515{
3516 int err, flags = 0;
3517 DBT key, data;
3518 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003519 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003520 int dlen = -1;
3521 int doff = -1;
3522
3523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3524 &keyobj, &flags, &dlen, &doff))
3525 return NULL;
3526
3527 CHECK_CURSOR_NOT_CLOSED(self);
3528
3529 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3530 return NULL;
3531
3532 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003533 if (!add_partial_dbt(&data, dlen, doff)) {
3534 FREE_DBT(key);
3535 return NULL;
3536 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003537 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3538 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003539 data.flags |= DB_DBT_MALLOC;
3540 /* only BTREE databases will return anything in the key */
3541 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3542 key.flags |= DB_DBT_MALLOC;
3543 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545 MYDB_BEGIN_ALLOW_THREADS;
3546 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3547 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003548 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3549 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003550 Py_INCREF(Py_None);
3551 retval = Py_None;
3552 }
3553 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554 retval = NULL;
3555 }
3556 else {
3557 switch (_DB_get_type(self->mydb)) {
3558 case -1:
3559 retval = NULL;
3560 break;
3561 case DB_BTREE:
3562 case DB_HASH:
3563 default:
3564 retval = Py_BuildValue("s#s#", key.data, key.size,
3565 data.data, data.size);
3566 break;
3567 case DB_RECNO:
3568 case DB_QUEUE:
3569 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3570 data.data, data.size);
3571 break;
3572 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003573 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003574 FREE_DBT(data);
3575 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003576 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003577 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003578 if (key.flags & DB_DBT_REALLOC) {
3579 FREE_DBT(key);
3580 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581
3582 return retval;
3583}
3584
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003586_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3587 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003589 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003591 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592
Gregory P. Smith7441e652003-11-03 21:35:31 +00003593 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3595 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003596 if (!make_dbt(dataobj, &data)) {
3597 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003598 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003599 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600
3601 MYDB_BEGIN_ALLOW_THREADS;
3602 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3603 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003604 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003605 Py_INCREF(Py_None);
3606 retval = Py_None;
3607 }
3608 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003609 retval = NULL;
3610 }
3611 else {
3612 switch (_DB_get_type(self->mydb)) {
3613 case -1:
3614 retval = NULL;
3615 break;
3616 case DB_BTREE:
3617 case DB_HASH:
3618 default:
3619 retval = Py_BuildValue("s#s#", key.data, key.size,
3620 data.data, data.size);
3621 break;
3622 case DB_RECNO:
3623 case DB_QUEUE:
3624 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3625 data.data, data.size);
3626 break;
3627 }
3628 }
3629
3630 FREE_DBT(key);
3631 return retval;
3632}
3633
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003634static PyObject*
3635DBC_get_both(DBCursorObject* self, PyObject* args)
3636{
3637 int flags=0;
3638 PyObject *keyobj, *dataobj;
3639
3640 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3641 return NULL;
3642
Gregory P. Smith7441e652003-11-03 21:35:31 +00003643 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003644 CHECK_CURSOR_NOT_CLOSED(self);
3645
3646 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3647 self->mydb->moduleFlags.getReturnsNone);
3648}
3649
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003650/* Return size of entry */
3651static PyObject*
3652DBC_get_current_size(DBCursorObject* self, PyObject* args)
3653{
3654 int err, flags=DB_CURRENT;
3655 PyObject* retval = NULL;
3656 DBT key, data;
3657
3658 if (!PyArg_ParseTuple(args, ":get_current_size"))
3659 return NULL;
3660 CHECK_CURSOR_NOT_CLOSED(self);
3661 CLEAR_DBT(key);
3662 CLEAR_DBT(data);
3663
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003664 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003665 getting the record size. */
3666 data.flags = DB_DBT_USERMEM;
3667 data.ulen = 0;
3668 MYDB_BEGIN_ALLOW_THREADS;
3669 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3670 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003671 if (err == DB_BUFFER_SMALL || !err) {
3672 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003673 retval = PyInt_FromLong((long)data.size);
3674 err = 0;
3675 }
3676
3677 FREE_DBT(key);
3678 FREE_DBT(data);
3679 RETURN_IF_ERR();
3680 return retval;
3681}
3682
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003683static PyObject*
3684DBC_set_both(DBCursorObject* self, PyObject* args)
3685{
3686 int flags=0;
3687 PyObject *keyobj, *dataobj;
3688
3689 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3690 return NULL;
3691
Gregory P. Smith7441e652003-11-03 21:35:31 +00003692 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003693 CHECK_CURSOR_NOT_CLOSED(self);
3694
3695 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3696 self->mydb->moduleFlags.cursorSetReturnsNone);
3697}
3698
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699
3700static PyObject*
3701DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3702{
3703 int err, irecno, flags=0;
3704 db_recno_t recno;
3705 DBT key, data;
3706 PyObject* retval;
3707 int dlen = -1;
3708 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003709 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003710
3711 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3712 &irecno, &flags, &dlen, &doff))
3713 return NULL;
3714
3715 CHECK_CURSOR_NOT_CLOSED(self);
3716
3717 CLEAR_DBT(key);
3718 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003719 /* use allocated space so DB will be able to realloc room for the real
3720 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003721 key.data = malloc(sizeof(db_recno_t));
3722 if (key.data == NULL) {
3723 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3724 return NULL;
3725 }
3726 key.size = sizeof(db_recno_t);
3727 key.ulen = key.size;
3728 memcpy(key.data, &recno, sizeof(db_recno_t));
3729 key.flags = DB_DBT_REALLOC;
3730
3731 CLEAR_DBT(data);
3732 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3733 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3734 data.flags = DB_DBT_MALLOC;
3735 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003736 if (!add_partial_dbt(&data, dlen, doff)) {
3737 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003739 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003740
3741 MYDB_BEGIN_ALLOW_THREADS;
3742 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3743 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003744 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3745 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003746 Py_INCREF(Py_None);
3747 retval = Py_None;
3748 }
3749 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 retval = NULL;
3751 }
3752 else { /* Can only be used for BTrees, so no need to return int key */
3753 retval = Py_BuildValue("s#s#", key.data, key.size,
3754 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003755 FREE_DBT(data);
3756 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003757 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003758
3759 return retval;
3760}
3761
3762
3763static PyObject*
3764DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3765{
3766 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3767}
3768
3769
3770static PyObject*
3771DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3772{
3773 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3774}
3775
3776
3777static PyObject*
3778DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3779{
3780 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3781}
3782
3783
3784static PyObject*
3785DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3786{
3787 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3788}
3789
3790
3791static PyObject*
3792DBC_join_item(DBCursorObject* self, PyObject* args)
3793{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003794 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003795 DBT key, data;
3796 PyObject* retval;
3797
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003798 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003799 return NULL;
3800
3801 CHECK_CURSOR_NOT_CLOSED(self);
3802
3803 CLEAR_DBT(key);
3804 CLEAR_DBT(data);
3805 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3806 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3807 key.flags = DB_DBT_MALLOC;
3808 }
3809
3810 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003811 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003812 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003813 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3814 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003815 Py_INCREF(Py_None);
3816 retval = Py_None;
3817 }
3818 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003819 retval = NULL;
3820 }
3821 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003822 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003823 FREE_DBT(key);
3824 }
3825
3826 return retval;
3827}
3828
3829
3830
3831/* --------------------------------------------------------------------- */
3832/* DBEnv methods */
3833
3834
3835static PyObject*
3836DBEnv_close(DBEnvObject* self, PyObject* args)
3837{
3838 int err, flags = 0;
3839
3840 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3841 return NULL;
3842 if (!self->closed) { /* Don't close more than once */
3843 MYDB_BEGIN_ALLOW_THREADS;
3844 err = self->db_env->close(self->db_env, flags);
3845 MYDB_END_ALLOW_THREADS;
3846 /* after calling DBEnv->close, regardless of error, this DBEnv
3847 * may not be accessed again (BerkeleyDB docs). */
3848 self->closed = 1;
3849 self->db_env = NULL;
3850 RETURN_IF_ERR();
3851 }
3852 RETURN_NONE();
3853}
3854
3855
3856static PyObject*
3857DBEnv_open(DBEnvObject* self, PyObject* args)
3858{
3859 int err, flags=0, mode=0660;
3860 char *db_home;
3861
3862 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3863 return NULL;
3864
3865 CHECK_ENV_NOT_CLOSED(self);
3866
3867 MYDB_BEGIN_ALLOW_THREADS;
3868 err = self->db_env->open(self->db_env, db_home, flags, mode);
3869 MYDB_END_ALLOW_THREADS;
3870 RETURN_IF_ERR();
3871 self->closed = 0;
3872 self->flags = flags;
3873 RETURN_NONE();
3874}
3875
3876
3877static PyObject*
3878DBEnv_remove(DBEnvObject* self, PyObject* args)
3879{
3880 int err, flags=0;
3881 char *db_home;
3882
3883 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3884 return NULL;
3885 CHECK_ENV_NOT_CLOSED(self);
3886 MYDB_BEGIN_ALLOW_THREADS;
3887 err = self->db_env->remove(self->db_env, db_home, flags);
3888 MYDB_END_ALLOW_THREADS;
3889 RETURN_IF_ERR();
3890 RETURN_NONE();
3891}
3892
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003893#if (DBVER >= 41)
3894static PyObject*
3895DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3896{
3897 int err;
3898 u_int32_t flags=0;
3899 char *file = NULL;
3900 char *database = NULL;
3901 PyObject *txnobj = NULL;
3902 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003903 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003904 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003905
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003906 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003907 &file, &database, &txnobj, &flags)) {
3908 return NULL;
3909 }
3910 if (!checkTxnObj(txnobj, &txn)) {
3911 return NULL;
3912 }
3913 CHECK_ENV_NOT_CLOSED(self);
3914 MYDB_BEGIN_ALLOW_THREADS;
3915 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3916 MYDB_END_ALLOW_THREADS;
3917 RETURN_IF_ERR();
3918 RETURN_NONE();
3919}
3920
3921static PyObject*
3922DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3923{
3924 int err;
3925 u_int32_t flags=0;
3926 char *file = NULL;
3927 char *database = NULL;
3928 char *newname = NULL;
3929 PyObject *txnobj = NULL;
3930 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003931 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003932 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003933
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003934 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003935 &file, &database, &newname, &txnobj, &flags)) {
3936 return NULL;
3937 }
3938 if (!checkTxnObj(txnobj, &txn)) {
3939 return NULL;
3940 }
3941 CHECK_ENV_NOT_CLOSED(self);
3942 MYDB_BEGIN_ALLOW_THREADS;
3943 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3944 flags);
3945 MYDB_END_ALLOW_THREADS;
3946 RETURN_IF_ERR();
3947 RETURN_NONE();
3948}
3949
3950static PyObject*
3951DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3952{
3953 int err;
3954 u_int32_t flags=0;
3955 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003956 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003957
3958 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3959 &passwd, &flags)) {
3960 return NULL;
3961 }
3962
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3965 MYDB_END_ALLOW_THREADS;
3966
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3969}
3970#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003971
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003972#if (DBVER >= 40)
3973static PyObject*
3974DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3975{
3976 int err;
3977 u_int32_t flags=0;
3978 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003979 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003980
3981 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3982 &timeout, &flags)) {
3983 return NULL;
3984 }
3985
3986 MYDB_BEGIN_ALLOW_THREADS;
3987 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3988 MYDB_END_ALLOW_THREADS;
3989
3990 RETURN_IF_ERR();
3991 RETURN_NONE();
3992}
3993#endif /* DBVER >= 40 */
3994
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003995static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003996DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3997{
3998 int err;
3999 long shm_key = 0;
4000
4001 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4002 return NULL;
4003 CHECK_ENV_NOT_CLOSED(self);
4004
4005 err = self->db_env->set_shm_key(self->db_env, shm_key);
4006 RETURN_IF_ERR();
4007 RETURN_NONE();
4008}
4009
4010static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004011DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4012{
4013 int err, gbytes=0, bytes=0, ncache=0;
4014
4015 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4016 &gbytes, &bytes, &ncache))
4017 return NULL;
4018 CHECK_ENV_NOT_CLOSED(self);
4019
4020 MYDB_BEGIN_ALLOW_THREADS;
4021 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
4026
4027
4028#if (DBVER >= 32)
4029static PyObject*
4030DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4031{
4032 int err, flags=0, onoff=0;
4033
4034 if (!PyArg_ParseTuple(args, "ii:set_flags",
4035 &flags, &onoff))
4036 return NULL;
4037 CHECK_ENV_NOT_CLOSED(self);
4038
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->set_flags(self->db_env, flags, onoff);
4041 MYDB_END_ALLOW_THREADS;
4042 RETURN_IF_ERR();
4043 RETURN_NONE();
4044}
4045#endif
4046
4047
4048static PyObject*
4049DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4050{
4051 int err;
4052 char *dir;
4053
4054 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4055 return NULL;
4056 CHECK_ENV_NOT_CLOSED(self);
4057
4058 MYDB_BEGIN_ALLOW_THREADS;
4059 err = self->db_env->set_data_dir(self->db_env, dir);
4060 MYDB_END_ALLOW_THREADS;
4061 RETURN_IF_ERR();
4062 RETURN_NONE();
4063}
4064
4065
4066static PyObject*
4067DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4068{
4069 int err, lg_bsize;
4070
4071 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4072 return NULL;
4073 CHECK_ENV_NOT_CLOSED(self);
4074
4075 MYDB_BEGIN_ALLOW_THREADS;
4076 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4077 MYDB_END_ALLOW_THREADS;
4078 RETURN_IF_ERR();
4079 RETURN_NONE();
4080}
4081
4082
4083static PyObject*
4084DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4085{
4086 int err;
4087 char *dir;
4088
4089 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4090 return NULL;
4091 CHECK_ENV_NOT_CLOSED(self);
4092
4093 MYDB_BEGIN_ALLOW_THREADS;
4094 err = self->db_env->set_lg_dir(self->db_env, dir);
4095 MYDB_END_ALLOW_THREADS;
4096 RETURN_IF_ERR();
4097 RETURN_NONE();
4098}
4099
4100static PyObject*
4101DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4102{
4103 int err, lg_max;
4104
4105 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_lg_max(self->db_env, lg_max);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
4115
4116
Neal Norwitz84562352005-10-20 04:30:15 +00004117#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004118static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004119DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4120{
4121 int err, lg_max;
4122
4123 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4124 return NULL;
4125 CHECK_ENV_NOT_CLOSED(self);
4126
4127 MYDB_BEGIN_ALLOW_THREADS;
4128 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4129 MYDB_END_ALLOW_THREADS;
4130 RETURN_IF_ERR();
4131 RETURN_NONE();
4132}
Neal Norwitz84562352005-10-20 04:30:15 +00004133#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004134
4135
4136static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004137DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4138{
4139 int err, lk_detect;
4140
4141 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4144
4145 MYDB_BEGIN_ALLOW_THREADS;
4146 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4147 MYDB_END_ALLOW_THREADS;
4148 RETURN_IF_ERR();
4149 RETURN_NONE();
4150}
4151
4152
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004153#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004154static PyObject*
4155DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4156{
4157 int err, max;
4158
4159 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4160 return NULL;
4161 CHECK_ENV_NOT_CLOSED(self);
4162
4163 MYDB_BEGIN_ALLOW_THREADS;
4164 err = self->db_env->set_lk_max(self->db_env, max);
4165 MYDB_END_ALLOW_THREADS;
4166 RETURN_IF_ERR();
4167 RETURN_NONE();
4168}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004170
4171
4172#if (DBVER >= 32)
4173
4174static PyObject*
4175DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4176{
4177 int err, max;
4178
4179 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4180 return NULL;
4181 CHECK_ENV_NOT_CLOSED(self);
4182
4183 MYDB_BEGIN_ALLOW_THREADS;
4184 err = self->db_env->set_lk_max_locks(self->db_env, max);
4185 MYDB_END_ALLOW_THREADS;
4186 RETURN_IF_ERR();
4187 RETURN_NONE();
4188}
4189
4190
4191static PyObject*
4192DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4193{
4194 int err, max;
4195
4196 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4197 return NULL;
4198 CHECK_ENV_NOT_CLOSED(self);
4199
4200 MYDB_BEGIN_ALLOW_THREADS;
4201 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4202 MYDB_END_ALLOW_THREADS;
4203 RETURN_IF_ERR();
4204 RETURN_NONE();
4205}
4206
4207
4208static PyObject*
4209DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4210{
4211 int err, max;
4212
4213 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4214 return NULL;
4215 CHECK_ENV_NOT_CLOSED(self);
4216
4217 MYDB_BEGIN_ALLOW_THREADS;
4218 err = self->db_env->set_lk_max_objects(self->db_env, max);
4219 MYDB_END_ALLOW_THREADS;
4220 RETURN_IF_ERR();
4221 RETURN_NONE();
4222}
4223
4224#endif
4225
4226
4227static PyObject*
4228DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4229{
4230 int err, mp_mmapsize;
4231
4232 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4233 return NULL;
4234 CHECK_ENV_NOT_CLOSED(self);
4235
4236 MYDB_BEGIN_ALLOW_THREADS;
4237 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4238 MYDB_END_ALLOW_THREADS;
4239 RETURN_IF_ERR();
4240 RETURN_NONE();
4241}
4242
4243
4244static PyObject*
4245DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4246{
4247 int err;
4248 char *dir;
4249
4250 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4251 return NULL;
4252 CHECK_ENV_NOT_CLOSED(self);
4253
4254 MYDB_BEGIN_ALLOW_THREADS;
4255 err = self->db_env->set_tmp_dir(self->db_env, dir);
4256 MYDB_END_ALLOW_THREADS;
4257 RETURN_IF_ERR();
4258 RETURN_NONE();
4259}
4260
4261
4262static PyObject*
4263DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4264{
4265 int flags = 0;
4266 PyObject* txnobj = NULL;
4267 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004268 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004269
4270 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4271 &txnobj, &flags))
4272 return NULL;
4273
4274 if (!checkTxnObj(txnobj, &txn))
4275 return NULL;
4276 CHECK_ENV_NOT_CLOSED(self);
4277
4278 return (PyObject*)newDBTxnObject(self, txn, flags);
4279}
4280
4281
4282static PyObject*
4283DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4284{
4285 int err, kbyte=0, min=0, flags=0;
4286
4287 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4288 return NULL;
4289 CHECK_ENV_NOT_CLOSED(self);
4290
4291 MYDB_BEGIN_ALLOW_THREADS;
4292#if (DBVER >= 40)
4293 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4294#else
4295 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4296#endif
4297 MYDB_END_ALLOW_THREADS;
4298 RETURN_IF_ERR();
4299 RETURN_NONE();
4300}
4301
4302
4303static PyObject*
4304DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4305{
4306 int err, max;
4307
4308 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4309 return NULL;
4310 CHECK_ENV_NOT_CLOSED(self);
4311
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004312 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004313 RETURN_IF_ERR();
4314 RETURN_NONE();
4315}
4316
4317
4318static PyObject*
4319DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4320{
4321 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004322 long stamp;
4323 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004324
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004325 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004326 return NULL;
4327 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004328 timestamp = (time_t)stamp;
4329 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004330 RETURN_IF_ERR();
4331 RETURN_NONE();
4332}
4333
4334
4335static PyObject*
4336DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4337{
4338 int err, atype, flags=0;
4339 int aborted = 0;
4340
4341 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4342 return NULL;
4343 CHECK_ENV_NOT_CLOSED(self);
4344
4345 MYDB_BEGIN_ALLOW_THREADS;
4346#if (DBVER >= 40)
4347 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4348#else
4349 err = lock_detect(self->db_env, flags, atype, &aborted);
4350#endif
4351 MYDB_END_ALLOW_THREADS;
4352 RETURN_IF_ERR();
4353 return PyInt_FromLong(aborted);
4354}
4355
4356
4357static PyObject*
4358DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4359{
4360 int flags=0;
4361 int locker, lock_mode;
4362 DBT obj;
4363 PyObject* objobj;
4364
4365 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4366 return NULL;
4367
4368
4369 if (!make_dbt(objobj, &obj))
4370 return NULL;
4371
4372 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4373}
4374
4375
4376static PyObject*
4377DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4378{
4379 int err;
4380 u_int32_t theID;
4381
4382 if (!PyArg_ParseTuple(args, ":lock_id"))
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_id(self->db_env, &theID);
4389#else
4390 err = lock_id(self->db_env, &theID);
4391#endif
4392 MYDB_END_ALLOW_THREADS;
4393 RETURN_IF_ERR();
4394
4395 return PyInt_FromLong((long)theID);
4396}
4397
4398
4399static PyObject*
4400DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4401{
4402 int err;
4403 DBLockObject* dblockobj;
4404
4405 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4406 return NULL;
4407
4408 CHECK_ENV_NOT_CLOSED(self);
4409 MYDB_BEGIN_ALLOW_THREADS;
4410#if (DBVER >= 40)
4411 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4412#else
4413 err = lock_put(self->db_env, &dblockobj->lock);
4414#endif
4415 MYDB_END_ALLOW_THREADS;
4416 RETURN_IF_ERR();
4417 RETURN_NONE();
4418}
4419
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004420#if (DBVER >= 44)
4421static PyObject*
4422DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4423{
4424 int err;
4425 char *file;
4426 u_int32_t flags = 0;
4427 static char* kwnames[] = { "file", "flags", NULL};
4428
4429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4430 &file, &flags))
4431 return NULL;
4432 CHECK_ENV_NOT_CLOSED(self);
4433
4434 MYDB_BEGIN_ALLOW_THREADS;
4435 err = self->db_env->lsn_reset(self->db_env, file, flags);
4436 MYDB_END_ALLOW_THREADS;
4437 RETURN_IF_ERR();
4438 RETURN_NONE();
4439}
4440#endif /* DBVER >= 4.4 */
4441
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004442#if (DBVER >= 40)
4443static PyObject*
4444DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4445{
4446 int err;
4447 DB_LOG_STAT* statp = NULL;
4448 PyObject* d = NULL;
4449 u_int32_t flags = 0;
4450
4451 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4452 return NULL;
4453 CHECK_ENV_NOT_CLOSED(self);
4454
4455 MYDB_BEGIN_ALLOW_THREADS;
4456 err = self->db_env->log_stat(self->db_env, &statp, flags);
4457 MYDB_END_ALLOW_THREADS;
4458 RETURN_IF_ERR();
4459
4460 /* Turn the stat structure into a dictionary */
4461 d = PyDict_New();
4462 if (d == NULL) {
4463 if (statp)
4464 free(statp);
4465 return NULL;
4466 }
4467
4468#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4469
4470 MAKE_ENTRY(magic);
4471 MAKE_ENTRY(version);
4472 MAKE_ENTRY(mode);
4473 MAKE_ENTRY(lg_bsize);
4474#if (DBVER >= 44)
4475 MAKE_ENTRY(lg_size);
4476 MAKE_ENTRY(record);
4477#endif
4478#if (DBVER <= 40)
4479 MAKE_ENTRY(lg_max);
4480#endif
4481 MAKE_ENTRY(w_mbytes);
4482 MAKE_ENTRY(w_bytes);
4483 MAKE_ENTRY(wc_mbytes);
4484 MAKE_ENTRY(wc_bytes);
4485 MAKE_ENTRY(wcount);
4486 MAKE_ENTRY(wcount_fill);
4487#if (DBVER >= 44)
4488 MAKE_ENTRY(rcount);
4489#endif
4490 MAKE_ENTRY(scount);
4491 MAKE_ENTRY(cur_file);
4492 MAKE_ENTRY(cur_offset);
4493 MAKE_ENTRY(disk_file);
4494 MAKE_ENTRY(disk_offset);
4495 MAKE_ENTRY(maxcommitperflush);
4496 MAKE_ENTRY(mincommitperflush);
4497 MAKE_ENTRY(regsize);
4498 MAKE_ENTRY(region_wait);
4499 MAKE_ENTRY(region_nowait);
4500
4501#undef MAKE_ENTRY
4502 free(statp);
4503 return d;
4504} /* DBEnv_log_stat */
4505#endif /* DBVER >= 4.0 for log_stat method */
4506
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004507
4508static PyObject*
4509DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4510{
4511 int err;
4512 DB_LOCK_STAT* sp;
4513 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004514 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004515
4516 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4517 return NULL;
4518 CHECK_ENV_NOT_CLOSED(self);
4519
4520 MYDB_BEGIN_ALLOW_THREADS;
4521#if (DBVER >= 40)
4522 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4523#else
4524#if (DBVER >= 33)
4525 err = lock_stat(self->db_env, &sp);
4526#else
4527 err = lock_stat(self->db_env, &sp, NULL);
4528#endif
4529#endif
4530 MYDB_END_ALLOW_THREADS;
4531 RETURN_IF_ERR();
4532
4533 /* Turn the stat structure into a dictionary */
4534 d = PyDict_New();
4535 if (d == NULL) {
4536 free(sp);
4537 return NULL;
4538 }
4539
4540#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4541
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004542#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004543 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004544#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(nmodes);
4546#if (DBVER >= 32)
4547 MAKE_ENTRY(maxlocks);
4548 MAKE_ENTRY(maxlockers);
4549 MAKE_ENTRY(maxobjects);
4550 MAKE_ENTRY(nlocks);
4551 MAKE_ENTRY(maxnlocks);
4552#endif
4553 MAKE_ENTRY(nlockers);
4554 MAKE_ENTRY(maxnlockers);
4555#if (DBVER >= 32)
4556 MAKE_ENTRY(nobjects);
4557 MAKE_ENTRY(maxnobjects);
4558#endif
4559 MAKE_ENTRY(nrequests);
4560 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004561#if (DBVER < 44)
4562 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004564#else
4565 MAKE_ENTRY(lock_nowait);
4566 MAKE_ENTRY(lock_wait);
4567#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004568 MAKE_ENTRY(ndeadlocks);
4569 MAKE_ENTRY(regsize);
4570 MAKE_ENTRY(region_wait);
4571 MAKE_ENTRY(region_nowait);
4572
4573#undef MAKE_ENTRY
4574 free(sp);
4575 return d;
4576}
4577
4578
4579static PyObject*
4580DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4581{
4582 int flags=0;
4583 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004584 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004585 PyObject* list;
4586 PyObject* item = NULL;
4587
4588 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4589 return NULL;
4590
4591 CHECK_ENV_NOT_CLOSED(self);
4592 MYDB_BEGIN_ALLOW_THREADS;
4593#if (DBVER >= 40)
4594 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4595#elif (DBVER == 33)
4596 err = log_archive(self->db_env, &log_list, flags);
4597#else
4598 err = log_archive(self->db_env, &log_list, flags, NULL);
4599#endif
4600 MYDB_END_ALLOW_THREADS;
4601 RETURN_IF_ERR();
4602
Gregory P. Smithbad47452006-06-05 00:33:35 +00004603 list = PyList_New(0);
4604 if (list == NULL) {
4605 if (log_list)
4606 free(log_list);
4607 return NULL;
4608 }
4609
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004611 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4613 item = PyString_FromString (*log_list);
4614 if (item == NULL) {
4615 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004616 list = NULL;
4617 break;
4618 }
4619 PyList_Append(list, item);
4620 Py_DECREF(item);
4621 }
4622 free(log_list_start);
4623 }
4624 return list;
4625}
4626
4627
4628static PyObject*
4629DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4630{
4631 int err;
4632 DB_TXN_STAT* sp;
4633 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004634 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004635
4636 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4637 return NULL;
4638 CHECK_ENV_NOT_CLOSED(self);
4639
4640 MYDB_BEGIN_ALLOW_THREADS;
4641#if (DBVER >= 40)
4642 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4643#elif (DBVER == 33)
4644 err = txn_stat(self->db_env, &sp);
4645#else
4646 err = txn_stat(self->db_env, &sp, NULL);
4647#endif
4648 MYDB_END_ALLOW_THREADS;
4649 RETURN_IF_ERR();
4650
4651 /* Turn the stat structure into a dictionary */
4652 d = PyDict_New();
4653 if (d == NULL) {
4654 free(sp);
4655 return NULL;
4656 }
4657
4658#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4659
4660 MAKE_ENTRY(time_ckp);
4661 MAKE_ENTRY(last_txnid);
4662 MAKE_ENTRY(maxtxns);
4663 MAKE_ENTRY(nactive);
4664 MAKE_ENTRY(maxnactive);
4665 MAKE_ENTRY(nbegins);
4666 MAKE_ENTRY(naborts);
4667 MAKE_ENTRY(ncommits);
4668 MAKE_ENTRY(regsize);
4669 MAKE_ENTRY(region_wait);
4670 MAKE_ENTRY(region_nowait);
4671
4672#undef MAKE_ENTRY
4673 free(sp);
4674 return d;
4675}
4676
4677
4678static PyObject*
4679DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4680{
4681 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004682 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683
4684 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4685 return NULL;
4686 CHECK_ENV_NOT_CLOSED(self);
4687
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004688 if (self->moduleFlags.getReturnsNone)
4689 ++oldValue;
4690 if (self->moduleFlags.cursorSetReturnsNone)
4691 ++oldValue;
4692 self->moduleFlags.getReturnsNone = (flags >= 1);
4693 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004694 return PyInt_FromLong(oldValue);
4695}
4696
4697
4698/* --------------------------------------------------------------------- */
4699/* DBTxn methods */
4700
4701
4702static PyObject*
4703DBTxn_commit(DBTxnObject* self, PyObject* args)
4704{
4705 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004706 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004707
4708 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4709 return NULL;
4710
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004711 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004712 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4713 "after txn_commit or txn_abort");
4714 PyErr_SetObject(DBError, t);
4715 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004716 return NULL;
4717 }
4718 txn = self->txn;
4719 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004720 MYDB_BEGIN_ALLOW_THREADS;
4721#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004722 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004723#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004724 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004725#endif
4726 MYDB_END_ALLOW_THREADS;
4727 RETURN_IF_ERR();
4728 RETURN_NONE();
4729}
4730
4731static PyObject*
4732DBTxn_prepare(DBTxnObject* self, PyObject* args)
4733{
4734#if (DBVER >= 33)
4735 int err;
4736 char* gid=NULL;
4737 int gid_size=0;
4738
4739 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4740 return NULL;
4741
4742 if (gid_size != DB_XIDDATASIZE) {
4743 PyErr_SetString(PyExc_TypeError,
4744 "gid must be DB_XIDDATASIZE bytes long");
4745 return NULL;
4746 }
4747
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004748 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004749 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4750 "after txn_commit or txn_abort");
4751 PyErr_SetObject(DBError, t);
4752 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004753 return NULL;
4754 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004755 MYDB_BEGIN_ALLOW_THREADS;
4756#if (DBVER >= 40)
4757 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4758#else
4759 err = txn_prepare(self->txn, (u_int8_t*)gid);
4760#endif
4761 MYDB_END_ALLOW_THREADS;
4762 RETURN_IF_ERR();
4763 RETURN_NONE();
4764#else
4765 int err;
4766
4767 if (!PyArg_ParseTuple(args, ":prepare"))
4768 return NULL;
4769
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004770 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004771 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4772 "after txn_commit or txn_abort");
4773 PyErr_SetObject(DBError, t);
4774 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004775 return NULL;
4776 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004777 MYDB_BEGIN_ALLOW_THREADS;
4778 err = txn_prepare(self->txn);
4779 MYDB_END_ALLOW_THREADS;
4780 RETURN_IF_ERR();
4781 RETURN_NONE();
4782#endif
4783}
4784
4785
4786static PyObject*
4787DBTxn_abort(DBTxnObject* self, PyObject* args)
4788{
4789 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004790 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791
4792 if (!PyArg_ParseTuple(args, ":abort"))
4793 return NULL;
4794
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004795 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004796 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4797 "after txn_commit or txn_abort");
4798 PyErr_SetObject(DBError, t);
4799 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004800 return NULL;
4801 }
4802 txn = self->txn;
4803 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004804 MYDB_BEGIN_ALLOW_THREADS;
4805#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004808 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809#endif
4810 MYDB_END_ALLOW_THREADS;
4811 RETURN_IF_ERR();
4812 RETURN_NONE();
4813}
4814
4815
4816static PyObject*
4817DBTxn_id(DBTxnObject* self, PyObject* args)
4818{
4819 int id;
4820
4821 if (!PyArg_ParseTuple(args, ":id"))
4822 return NULL;
4823
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004824 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004825 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4826 "after txn_commit or txn_abort");
4827 PyErr_SetObject(DBError, t);
4828 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004829 return NULL;
4830 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004831 MYDB_BEGIN_ALLOW_THREADS;
4832#if (DBVER >= 40)
4833 id = self->txn->id(self->txn);
4834#else
4835 id = txn_id(self->txn);
4836#endif
4837 MYDB_END_ALLOW_THREADS;
4838 return PyInt_FromLong(id);
4839}
4840
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004841#if (DBVER >= 43)
4842/* --------------------------------------------------------------------- */
4843/* DBSequence methods */
4844
4845
4846static PyObject*
4847DBSequence_close(DBSequenceObject* self, PyObject* args)
4848{
4849 int err, flags=0;
4850 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4851 return NULL;
4852 CHECK_SEQUENCE_NOT_CLOSED(self)
4853
4854 MYDB_BEGIN_ALLOW_THREADS
4855 err = self->sequence->close(self->sequence, flags);
4856 self->sequence = NULL;
4857 MYDB_END_ALLOW_THREADS
4858
4859 RETURN_IF_ERR();
4860
4861 RETURN_NONE();
4862}
4863
4864static PyObject*
4865DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4866{
4867 int err, flags = 0;
4868 int delta = 1;
4869 db_seq_t value;
4870 PyObject *txnobj = NULL;
4871 DB_TXN *txn = NULL;
4872 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4873 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4874 return NULL;
4875 CHECK_SEQUENCE_NOT_CLOSED(self)
4876
4877 if (!checkTxnObj(txnobj, &txn))
4878 return NULL;
4879
4880 MYDB_BEGIN_ALLOW_THREADS
4881 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4882 MYDB_END_ALLOW_THREADS
4883
4884 RETURN_IF_ERR();
4885 return PyLong_FromLongLong(value);
4886
4887}
4888
4889static PyObject*
4890DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4891{
4892 if (!PyArg_ParseTuple(args,":get_dbp"))
4893 return NULL;
4894 CHECK_SEQUENCE_NOT_CLOSED(self)
4895 Py_INCREF(self->mydb);
4896 return (PyObject* )self->mydb;
4897}
4898
4899static PyObject*
4900DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4901{
4902 int err;
4903 DBT key;
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004904 PyObject *retval;
4905 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004906 CHECK_SEQUENCE_NOT_CLOSED(self)
4907 MYDB_BEGIN_ALLOW_THREADS
4908 err = self->sequence->get_key(self->sequence, &key);
4909 MYDB_END_ALLOW_THREADS
4910
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004911 if (!err)
4912 retval = PyString_FromStringAndSize(key.data, key.size);
4913
4914 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004915 RETURN_IF_ERR();
4916
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004917 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004918}
4919
4920static PyObject*
4921DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4922{
4923 int err;
4924 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004925 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004926 return NULL;
4927 CHECK_SEQUENCE_NOT_CLOSED(self)
4928
4929 MYDB_BEGIN_ALLOW_THREADS
4930 err = self->sequence->initial_value(self->sequence, value);
4931 MYDB_END_ALLOW_THREADS
4932
4933 RETURN_IF_ERR();
4934
4935 RETURN_NONE();
4936}
4937
4938static PyObject*
4939DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4940{
4941 int err, flags = 0;
4942 PyObject* keyobj;
4943 PyObject *txnobj = NULL;
4944 DB_TXN *txn = NULL;
4945 DBT key;
4946
4947 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004948 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004949 return NULL;
4950
4951 if (!checkTxnObj(txnobj, &txn))
4952 return NULL;
4953
4954 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4955 return NULL;
4956
4957 MYDB_BEGIN_ALLOW_THREADS
4958 err = self->sequence->open(self->sequence, txn, &key, flags);
4959 MYDB_END_ALLOW_THREADS
4960
4961 CLEAR_DBT(key);
4962 RETURN_IF_ERR();
4963
4964 RETURN_NONE();
4965}
4966
4967static PyObject*
4968DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4969{
4970 int err, flags = 0;
4971 PyObject *txnobj = NULL;
4972 DB_TXN *txn = NULL;
4973
4974 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004975 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004976 return NULL;
4977
4978 if (!checkTxnObj(txnobj, &txn))
4979 return NULL;
4980
4981 CHECK_SEQUENCE_NOT_CLOSED(self)
4982
4983 MYDB_BEGIN_ALLOW_THREADS
4984 err = self->sequence->remove(self->sequence, txn, flags);
4985 MYDB_END_ALLOW_THREADS
4986
4987 RETURN_IF_ERR();
4988 RETURN_NONE();
4989}
4990
4991static PyObject*
4992DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4993{
4994 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004995 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004996 return NULL;
4997 CHECK_SEQUENCE_NOT_CLOSED(self)
4998
4999 MYDB_BEGIN_ALLOW_THREADS
5000 err = self->sequence->set_cachesize(self->sequence, size);
5001 MYDB_END_ALLOW_THREADS
5002
5003 RETURN_IF_ERR();
5004 RETURN_NONE();
5005}
5006
5007static PyObject*
5008DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5009{
5010 int err, size;
5011 if (!PyArg_ParseTuple(args,":get_cachesize"))
5012 return NULL;
5013 CHECK_SEQUENCE_NOT_CLOSED(self)
5014
5015 MYDB_BEGIN_ALLOW_THREADS
5016 err = self->sequence->get_cachesize(self->sequence, &size);
5017 MYDB_END_ALLOW_THREADS
5018
5019 RETURN_IF_ERR();
5020 return PyInt_FromLong(size);
5021}
5022
5023static PyObject*
5024DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5025{
5026 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005027 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005028 return NULL;
5029 CHECK_SEQUENCE_NOT_CLOSED(self)
5030
5031 MYDB_BEGIN_ALLOW_THREADS
5032 err = self->sequence->set_flags(self->sequence, flags);
5033 MYDB_END_ALLOW_THREADS
5034
5035 RETURN_IF_ERR();
5036 RETURN_NONE();
5037
5038}
5039
5040static PyObject*
5041DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5042{
5043 unsigned int flags;
5044 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005045 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005046 return NULL;
5047 CHECK_SEQUENCE_NOT_CLOSED(self)
5048
5049 MYDB_BEGIN_ALLOW_THREADS
5050 err = self->sequence->get_flags(self->sequence, &flags);
5051 MYDB_END_ALLOW_THREADS
5052
5053 RETURN_IF_ERR();
5054 return PyInt_FromLong((int)flags);
5055}
5056
5057static PyObject*
5058DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5059{
5060 int err;
5061 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005062 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005063 return NULL;
5064 CHECK_SEQUENCE_NOT_CLOSED(self)
5065
5066 MYDB_BEGIN_ALLOW_THREADS
5067 err = self->sequence->set_range(self->sequence, min, max);
5068 MYDB_END_ALLOW_THREADS
5069
5070 RETURN_IF_ERR();
5071 RETURN_NONE();
5072}
5073
5074static PyObject*
5075DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5076{
5077 int err;
5078 db_seq_t min, max;
5079 if (!PyArg_ParseTuple(args,":get_range"))
5080 return NULL;
5081 CHECK_SEQUENCE_NOT_CLOSED(self)
5082
5083 MYDB_BEGIN_ALLOW_THREADS
5084 err = self->sequence->get_range(self->sequence, &min, &max);
5085 MYDB_END_ALLOW_THREADS
5086
5087 RETURN_IF_ERR();
5088 return Py_BuildValue("(LL)", min, max);
5089}
5090
5091static PyObject*
5092DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5093{
5094 int err, flags = 0;
5095 DB_SEQUENCE_STAT* sp = NULL;
5096 PyObject* dict_stat;
5097 static char* kwnames[] = {"flags", NULL };
5098 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5099 return NULL;
5100 CHECK_SEQUENCE_NOT_CLOSED(self);
5101
5102 MYDB_BEGIN_ALLOW_THREADS;
5103 err = self->sequence->stat(self->sequence, &sp, flags);
5104 MYDB_END_ALLOW_THREADS;
5105 RETURN_IF_ERR();
5106
5107 if ((dict_stat = PyDict_New()) == NULL) {
5108 free(sp);
5109 return NULL;
5110 }
5111
5112
5113#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5114#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5115
5116 MAKE_INT_ENTRY(wait);
5117 MAKE_INT_ENTRY(nowait);
5118 MAKE_LONG_LONG_ENTRY(current);
5119 MAKE_LONG_LONG_ENTRY(value);
5120 MAKE_LONG_LONG_ENTRY(last_value);
5121 MAKE_LONG_LONG_ENTRY(min);
5122 MAKE_LONG_LONG_ENTRY(max);
5123 MAKE_INT_ENTRY(cache_size);
5124 MAKE_INT_ENTRY(flags);
5125
5126#undef MAKE_INT_ENTRY
5127#undef MAKE_LONG_LONG_ENTRY
5128
5129 free(sp);
5130 return dict_stat;
5131}
5132#endif
5133
5134
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005135/* --------------------------------------------------------------------- */
5136/* Method definition tables and type objects */
5137
5138static PyMethodDef DB_methods[] = {
5139 {"append", (PyCFunction)DB_append, METH_VARARGS},
5140#if (DBVER >= 33)
5141 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5142#endif
5143 {"close", (PyCFunction)DB_close, METH_VARARGS},
5144#if (DBVER >= 32)
5145 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5146 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5147#endif
5148 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5149 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5150 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5151 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005152#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005153 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005154#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005155 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5156 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5157 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5158 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5159 {"join", (PyCFunction)DB_join, METH_VARARGS},
5160 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5161 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5162 {"items", (PyCFunction)DB_items, METH_VARARGS},
5163 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5164 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5165 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5166 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5167 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5168 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005169#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005170 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005171#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005172 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005173#if (DBVER >= 41)
5174 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5175#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5177 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5178 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5179 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5180 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5181 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5182 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5183 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5184 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5185#if (DBVER >= 32)
5186 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5187#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005188 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005189 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5190#if (DBVER >= 33)
5191 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5192#endif
5193 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5194 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5195 {"values", (PyCFunction)DB_values, METH_VARARGS},
5196 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5197 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5198 {NULL, NULL} /* sentinel */
5199};
5200
5201
5202static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005203 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005204 (binaryfunc)DB_subscript, /*mp_subscript*/
5205 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5206};
5207
5208
5209static PyMethodDef DBCursor_methods[] = {
5210 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5211 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5212 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5213 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5214 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5215 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5216 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005217#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005218 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005219#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005220 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5221 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5222 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5223 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5224 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5225 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5226 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5227 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005228 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005229 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005230 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5231 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5232 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5233 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5234 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5235 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5236 {NULL, NULL} /* sentinel */
5237};
5238
5239
5240static PyMethodDef DBEnv_methods[] = {
5241 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5242 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5243 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005244#if (DBVER >= 41)
5245 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5246 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5247 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5248#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005249#if (DBVER >= 40)
5250 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5251#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005252 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005253 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5254 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5255#if (DBVER >= 32)
5256 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5257#endif
5258 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5259 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5260 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005261#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005262 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005265#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005268#if (DBVER >= 32)
5269 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5270 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5271 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5272#endif
5273 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5274 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5275 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5276 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5277 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5278 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005279 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005280 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5281 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5282 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5283 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5284 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5285 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005286#if (DBVER >= 40)
5287 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5288#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005289#if (DBVER >= 44)
5290 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5291#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005292 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5293 {NULL, NULL} /* sentinel */
5294};
5295
5296
5297static PyMethodDef DBTxn_methods[] = {
5298 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5299 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5300 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5301 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5302 {NULL, NULL} /* sentinel */
5303};
5304
5305
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005306#if (DBVER >= 43)
5307static PyMethodDef DBSequence_methods[] = {
5308 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5309 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5310 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5311 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005312 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5313 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5314 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5315 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5316 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5317 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5318 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5319 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5320 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5321 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5322 {NULL, NULL} /* sentinel */
5323};
5324#endif
5325
5326
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005327static PyObject*
5328DB_getattr(DBObject* self, char *name)
5329{
5330 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5331}
5332
5333
5334static PyObject*
5335DBEnv_getattr(DBEnvObject* self, char *name)
5336{
5337 if (!strcmp(name, "db_home")) {
5338 CHECK_ENV_NOT_CLOSED(self);
5339 if (self->db_env->db_home == NULL) {
5340 RETURN_NONE();
5341 }
5342 return PyString_FromString(self->db_env->db_home);
5343 }
5344
5345 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5346}
5347
5348
5349static PyObject*
5350DBCursor_getattr(DBCursorObject* self, char *name)
5351{
5352 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5353}
5354
5355static PyObject*
5356DBTxn_getattr(DBTxnObject* self, char *name)
5357{
5358 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5359}
5360
5361static PyObject*
5362DBLock_getattr(DBLockObject* self, char *name)
5363{
5364 return NULL;
5365}
5366
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005367#if (DBVER >= 43)
5368static PyObject*
5369DBSequence_getattr(DBSequenceObject* self, char *name)
5370{
5371 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5372}
5373#endif
5374
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005375statichere PyTypeObject DB_Type = {
5376 PyObject_HEAD_INIT(NULL)
5377 0, /*ob_size*/
5378 "DB", /*tp_name*/
5379 sizeof(DBObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DB_dealloc, /*tp_dealloc*/
5383 0, /*tp_print*/
5384 (getattrfunc)DB_getattr, /*tp_getattr*/
5385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 &DB_mapping,/*tp_as_mapping*/
5391 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005392#ifdef HAVE_WEAKREF
5393 0, /* tp_call */
5394 0, /* tp_str */
5395 0, /* tp_getattro */
5396 0, /* tp_setattro */
5397 0, /* tp_as_buffer */
5398 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5399 0, /* tp_doc */
5400 0, /* tp_traverse */
5401 0, /* tp_clear */
5402 0, /* tp_richcompare */
5403 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5404#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005405};
5406
5407
5408statichere PyTypeObject DBCursor_Type = {
5409 PyObject_HEAD_INIT(NULL)
5410 0, /*ob_size*/
5411 "DBCursor", /*tp_name*/
5412 sizeof(DBCursorObject), /*tp_basicsize*/
5413 0, /*tp_itemsize*/
5414 /* methods */
5415 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5416 0, /*tp_print*/
5417 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5418 0, /*tp_setattr*/
5419 0, /*tp_compare*/
5420 0, /*tp_repr*/
5421 0, /*tp_as_number*/
5422 0, /*tp_as_sequence*/
5423 0, /*tp_as_mapping*/
5424 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005425#ifdef HAVE_WEAKREF
5426 0, /* tp_call */
5427 0, /* tp_str */
5428 0, /* tp_getattro */
5429 0, /* tp_setattro */
5430 0, /* tp_as_buffer */
5431 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5432 0, /* tp_doc */
5433 0, /* tp_traverse */
5434 0, /* tp_clear */
5435 0, /* tp_richcompare */
5436 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5437#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005438};
5439
5440
5441statichere PyTypeObject DBEnv_Type = {
5442 PyObject_HEAD_INIT(NULL)
5443 0, /*ob_size*/
5444 "DBEnv", /*tp_name*/
5445 sizeof(DBEnvObject), /*tp_basicsize*/
5446 0, /*tp_itemsize*/
5447 /* methods */
5448 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5449 0, /*tp_print*/
5450 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5451 0, /*tp_setattr*/
5452 0, /*tp_compare*/
5453 0, /*tp_repr*/
5454 0, /*tp_as_number*/
5455 0, /*tp_as_sequence*/
5456 0, /*tp_as_mapping*/
5457 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005458#ifdef HAVE_WEAKREF
5459 0, /* tp_call */
5460 0, /* tp_str */
5461 0, /* tp_getattro */
5462 0, /* tp_setattro */
5463 0, /* tp_as_buffer */
5464 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5465 0, /* tp_doc */
5466 0, /* tp_traverse */
5467 0, /* tp_clear */
5468 0, /* tp_richcompare */
5469 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5470#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005471};
5472
5473statichere PyTypeObject DBTxn_Type = {
5474 PyObject_HEAD_INIT(NULL)
5475 0, /*ob_size*/
5476 "DBTxn", /*tp_name*/
5477 sizeof(DBTxnObject), /*tp_basicsize*/
5478 0, /*tp_itemsize*/
5479 /* methods */
5480 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5481 0, /*tp_print*/
5482 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5483 0, /*tp_setattr*/
5484 0, /*tp_compare*/
5485 0, /*tp_repr*/
5486 0, /*tp_as_number*/
5487 0, /*tp_as_sequence*/
5488 0, /*tp_as_mapping*/
5489 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005490#ifdef HAVE_WEAKREF
5491 0, /* tp_call */
5492 0, /* tp_str */
5493 0, /* tp_getattro */
5494 0, /* tp_setattro */
5495 0, /* tp_as_buffer */
5496 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5497 0, /* tp_doc */
5498 0, /* tp_traverse */
5499 0, /* tp_clear */
5500 0, /* tp_richcompare */
5501 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5502#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005503};
5504
5505
5506statichere PyTypeObject DBLock_Type = {
5507 PyObject_HEAD_INIT(NULL)
5508 0, /*ob_size*/
5509 "DBLock", /*tp_name*/
5510 sizeof(DBLockObject), /*tp_basicsize*/
5511 0, /*tp_itemsize*/
5512 /* methods */
5513 (destructor)DBLock_dealloc, /*tp_dealloc*/
5514 0, /*tp_print*/
5515 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5516 0, /*tp_setattr*/
5517 0, /*tp_compare*/
5518 0, /*tp_repr*/
5519 0, /*tp_as_number*/
5520 0, /*tp_as_sequence*/
5521 0, /*tp_as_mapping*/
5522 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005523#ifdef HAVE_WEAKREF
5524 0, /* tp_call */
5525 0, /* tp_str */
5526 0, /* tp_getattro */
5527 0, /* tp_setattro */
5528 0, /* tp_as_buffer */
5529 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5530 0, /* tp_doc */
5531 0, /* tp_traverse */
5532 0, /* tp_clear */
5533 0, /* tp_richcompare */
5534 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5535#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536};
5537
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005538#if (DBVER >= 43)
5539statichere PyTypeObject DBSequence_Type = {
5540 PyObject_HEAD_INIT(NULL)
5541 0, /*ob_size*/
5542 "DBSequence", /*tp_name*/
5543 sizeof(DBSequenceObject), /*tp_basicsize*/
5544 0, /*tp_itemsize*/
5545 /* methods */
5546 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5547 0, /*tp_print*/
5548 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5549 0, /*tp_setattr*/
5550 0, /*tp_compare*/
5551 0, /*tp_repr*/
5552 0, /*tp_as_number*/
5553 0, /*tp_as_sequence*/
5554 0, /*tp_as_mapping*/
5555 0, /*tp_hash*/
5556#ifdef HAVE_WEAKREF
5557 0, /* tp_call */
5558 0, /* tp_str */
5559 0, /* tp_getattro */
5560 0, /* tp_setattro */
5561 0, /* tp_as_buffer */
5562 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5563 0, /* tp_doc */
5564 0, /* tp_traverse */
5565 0, /* tp_clear */
5566 0, /* tp_richcompare */
5567 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5568#endif
5569};
5570#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005571
5572/* --------------------------------------------------------------------- */
5573/* Module-level functions */
5574
5575static PyObject*
5576DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5577{
5578 PyObject* dbenvobj = NULL;
5579 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005580 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005581
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005582 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5583 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005584 return NULL;
5585 if (dbenvobj == Py_None)
5586 dbenvobj = NULL;
5587 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5588 makeTypeError("DBEnv", dbenvobj);
5589 return NULL;
5590 }
5591
5592 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5593}
5594
5595
5596static PyObject*
5597DBEnv_construct(PyObject* self, PyObject* args)
5598{
5599 int flags = 0;
5600 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5601 return (PyObject* )newDBEnvObject(flags);
5602}
5603
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005604#if (DBVER >= 43)
5605static PyObject*
5606DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5607{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005608 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005609 int flags = 0;
5610 static char* kwnames[] = { "db", "flags", NULL};
5611
5612 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5613 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005614 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005615 makeTypeError("DB", dbobj);
5616 return NULL;
5617 }
5618 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5619}
5620#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005621
5622static char bsddb_version_doc[] =
5623"Returns a tuple of major, minor, and patch release numbers of the\n\
5624underlying DB library.";
5625
5626static PyObject*
5627bsddb_version(PyObject* self, PyObject* args)
5628{
5629 int major, minor, patch;
5630
5631 if (!PyArg_ParseTuple(args, ":version"))
5632 return NULL;
5633 db_version(&major, &minor, &patch);
5634 return Py_BuildValue("(iii)", major, minor, patch);
5635}
5636
5637
5638/* List of functions defined in the module */
5639
5640static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005641 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5642 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5643#if (DBVER >= 43)
5644 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5645#endif
5646 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647 {NULL, NULL} /* sentinel */
5648};
5649
5650
5651/* --------------------------------------------------------------------- */
5652/* Module initialization */
5653
5654
5655/* Convenience routine to export an integer value.
5656 * Errors are silently ignored, for better or for worse...
5657 */
5658#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5659
Gregory P. Smith41631e82003-09-21 00:08:14 +00005660#define MODULE_NAME_MAX_LEN 11
5661static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005662
5663DL_EXPORT(void) init_bsddb(void)
5664{
5665 PyObject* m;
5666 PyObject* d;
5667 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5668 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5669 PyObject* cvsid_s = PyString_FromString( rcs_id );
5670
5671 /* Initialize the type of the new type objects here; doing it here
5672 is required for portability to Windows without requiring C++. */
5673 DB_Type.ob_type = &PyType_Type;
5674 DBCursor_Type.ob_type = &PyType_Type;
5675 DBEnv_Type.ob_type = &PyType_Type;
5676 DBTxn_Type.ob_type = &PyType_Type;
5677 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005678#if (DBVER >= 43)
5679 DBSequence_Type.ob_type = &PyType_Type;
5680#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005681
5682
Mark Hammonda69d4092003-04-22 23:13:27 +00005683#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005685 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005686#endif
5687
5688 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005689 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005690 if (m == NULL)
5691 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005692
5693 /* Add some symbolic constants to the module */
5694 d = PyModule_GetDict(m);
5695 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5696 PyDict_SetItemString(d, "cvsid", cvsid_s);
5697 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5698 Py_DECREF(pybsddb_version_s);
5699 pybsddb_version_s = NULL;
5700 Py_DECREF(cvsid_s);
5701 cvsid_s = NULL;
5702 Py_DECREF(db_version_s);
5703 db_version_s = NULL;
5704
5705 ADD_INT(d, DB_VERSION_MAJOR);
5706 ADD_INT(d, DB_VERSION_MINOR);
5707 ADD_INT(d, DB_VERSION_PATCH);
5708
5709 ADD_INT(d, DB_MAX_PAGES);
5710 ADD_INT(d, DB_MAX_RECORDS);
5711
Gregory P. Smith41631e82003-09-21 00:08:14 +00005712#if (DBVER >= 42)
5713 ADD_INT(d, DB_RPCCLIENT);
5714#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005715 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005716 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5717 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5718#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005719 ADD_INT(d, DB_XA_CREATE);
5720
5721 ADD_INT(d, DB_CREATE);
5722 ADD_INT(d, DB_NOMMAP);
5723 ADD_INT(d, DB_THREAD);
5724
5725 ADD_INT(d, DB_FORCE);
5726 ADD_INT(d, DB_INIT_CDB);
5727 ADD_INT(d, DB_INIT_LOCK);
5728 ADD_INT(d, DB_INIT_LOG);
5729 ADD_INT(d, DB_INIT_MPOOL);
5730 ADD_INT(d, DB_INIT_TXN);
5731#if (DBVER >= 32)
5732 ADD_INT(d, DB_JOINENV);
5733#endif
5734
5735 ADD_INT(d, DB_RECOVER);
5736 ADD_INT(d, DB_RECOVER_FATAL);
5737 ADD_INT(d, DB_TXN_NOSYNC);
5738 ADD_INT(d, DB_USE_ENVIRON);
5739 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5740
5741 ADD_INT(d, DB_LOCKDOWN);
5742 ADD_INT(d, DB_PRIVATE);
5743 ADD_INT(d, DB_SYSTEM_MEM);
5744
5745 ADD_INT(d, DB_TXN_SYNC);
5746 ADD_INT(d, DB_TXN_NOWAIT);
5747
5748 ADD_INT(d, DB_EXCL);
5749 ADD_INT(d, DB_FCNTL_LOCKING);
5750 ADD_INT(d, DB_ODDFILESIZE);
5751 ADD_INT(d, DB_RDWRMASTER);
5752 ADD_INT(d, DB_RDONLY);
5753 ADD_INT(d, DB_TRUNCATE);
5754#if (DBVER >= 32)
5755 ADD_INT(d, DB_EXTENT);
5756 ADD_INT(d, DB_CDB_ALLDB);
5757 ADD_INT(d, DB_VERIFY);
5758#endif
5759 ADD_INT(d, DB_UPGRADE);
5760
5761 ADD_INT(d, DB_AGGRESSIVE);
5762 ADD_INT(d, DB_NOORDERCHK);
5763 ADD_INT(d, DB_ORDERCHKONLY);
5764 ADD_INT(d, DB_PR_PAGE);
5765#if ! (DBVER >= 33)
5766 ADD_INT(d, DB_VRFY_FLAGMASK);
5767 ADD_INT(d, DB_PR_HEADERS);
5768#endif
5769 ADD_INT(d, DB_PR_RECOVERYTEST);
5770 ADD_INT(d, DB_SALVAGE);
5771
5772 ADD_INT(d, DB_LOCK_NORUN);
5773 ADD_INT(d, DB_LOCK_DEFAULT);
5774 ADD_INT(d, DB_LOCK_OLDEST);
5775 ADD_INT(d, DB_LOCK_RANDOM);
5776 ADD_INT(d, DB_LOCK_YOUNGEST);
5777#if (DBVER >= 33)
5778 ADD_INT(d, DB_LOCK_MAXLOCKS);
5779 ADD_INT(d, DB_LOCK_MINLOCKS);
5780 ADD_INT(d, DB_LOCK_MINWRITE);
5781#endif
5782
5783
5784#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005785 /* docs say to use zero instead */
5786 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787#else
5788 ADD_INT(d, DB_LOCK_CONFLICT);
5789#endif
5790
5791 ADD_INT(d, DB_LOCK_DUMP);
5792 ADD_INT(d, DB_LOCK_GET);
5793 ADD_INT(d, DB_LOCK_INHERIT);
5794 ADD_INT(d, DB_LOCK_PUT);
5795 ADD_INT(d, DB_LOCK_PUT_ALL);
5796 ADD_INT(d, DB_LOCK_PUT_OBJ);
5797
5798 ADD_INT(d, DB_LOCK_NG);
5799 ADD_INT(d, DB_LOCK_READ);
5800 ADD_INT(d, DB_LOCK_WRITE);
5801 ADD_INT(d, DB_LOCK_NOWAIT);
5802#if (DBVER >= 32)
5803 ADD_INT(d, DB_LOCK_WAIT);
5804#endif
5805 ADD_INT(d, DB_LOCK_IWRITE);
5806 ADD_INT(d, DB_LOCK_IREAD);
5807 ADD_INT(d, DB_LOCK_IWR);
5808#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005809#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005810 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005811#else
5812 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5813#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005814 ADD_INT(d, DB_LOCK_WWRITE);
5815#endif
5816
5817 ADD_INT(d, DB_LOCK_RECORD);
5818 ADD_INT(d, DB_LOCK_UPGRADE);
5819#if (DBVER >= 32)
5820 ADD_INT(d, DB_LOCK_SWITCH);
5821#endif
5822#if (DBVER >= 33)
5823 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5824#endif
5825
5826 ADD_INT(d, DB_LOCK_NOWAIT);
5827 ADD_INT(d, DB_LOCK_RECORD);
5828 ADD_INT(d, DB_LOCK_UPGRADE);
5829
5830#if (DBVER >= 33)
5831 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005832#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005833 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005835 ADD_INT(d, DB_LSTAT_FREE);
5836 ADD_INT(d, DB_LSTAT_HELD);
5837#if (DBVER == 33)
5838 ADD_INT(d, DB_LSTAT_NOGRANT);
5839#endif
5840 ADD_INT(d, DB_LSTAT_PENDING);
5841 ADD_INT(d, DB_LSTAT_WAITING);
5842#endif
5843
5844 ADD_INT(d, DB_ARCH_ABS);
5845 ADD_INT(d, DB_ARCH_DATA);
5846 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005847#if (DBVER >= 42)
5848 ADD_INT(d, DB_ARCH_REMOVE);
5849#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005850
5851 ADD_INT(d, DB_BTREE);
5852 ADD_INT(d, DB_HASH);
5853 ADD_INT(d, DB_RECNO);
5854 ADD_INT(d, DB_QUEUE);
5855 ADD_INT(d, DB_UNKNOWN);
5856
5857 ADD_INT(d, DB_DUP);
5858 ADD_INT(d, DB_DUPSORT);
5859 ADD_INT(d, DB_RECNUM);
5860 ADD_INT(d, DB_RENUMBER);
5861 ADD_INT(d, DB_REVSPLITOFF);
5862 ADD_INT(d, DB_SNAPSHOT);
5863
5864 ADD_INT(d, DB_JOIN_NOSORT);
5865
5866 ADD_INT(d, DB_AFTER);
5867 ADD_INT(d, DB_APPEND);
5868 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005869#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005870 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005871#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005872#if (DBVER >= 41)
5873 _addIntToDict(d, "DB_CHECKPOINT", 0);
5874#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005876 ADD_INT(d, DB_CURLSN);
5877#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005878#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 ADD_INT(d, DB_COMMIT);
5880#endif
5881 ADD_INT(d, DB_CONSUME);
5882#if (DBVER >= 32)
5883 ADD_INT(d, DB_CONSUME_WAIT);
5884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005885 ADD_INT(d, DB_CURRENT);
5886#if (DBVER >= 33)
5887 ADD_INT(d, DB_FAST_STAT);
5888#endif
5889 ADD_INT(d, DB_FIRST);
5890 ADD_INT(d, DB_FLUSH);
5891 ADD_INT(d, DB_GET_BOTH);
5892 ADD_INT(d, DB_GET_RECNO);
5893 ADD_INT(d, DB_JOIN_ITEM);
5894 ADD_INT(d, DB_KEYFIRST);
5895 ADD_INT(d, DB_KEYLAST);
5896 ADD_INT(d, DB_LAST);
5897 ADD_INT(d, DB_NEXT);
5898 ADD_INT(d, DB_NEXT_DUP);
5899 ADD_INT(d, DB_NEXT_NODUP);
5900 ADD_INT(d, DB_NODUPDATA);
5901 ADD_INT(d, DB_NOOVERWRITE);
5902 ADD_INT(d, DB_NOSYNC);
5903 ADD_INT(d, DB_POSITION);
5904 ADD_INT(d, DB_PREV);
5905 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005906#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005907 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005909 ADD_INT(d, DB_SET);
5910 ADD_INT(d, DB_SET_RANGE);
5911 ADD_INT(d, DB_SET_RECNO);
5912 ADD_INT(d, DB_WRITECURSOR);
5913
5914 ADD_INT(d, DB_OPFLAGS_MASK);
5915 ADD_INT(d, DB_RMW);
5916#if (DBVER >= 33)
5917 ADD_INT(d, DB_DIRTY_READ);
5918 ADD_INT(d, DB_MULTIPLE);
5919 ADD_INT(d, DB_MULTIPLE_KEY);
5920#endif
5921
Gregory P. Smith29602d22006-01-24 09:46:48 +00005922#if (DBVER >= 44)
5923 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5924 ADD_INT(d, DB_READ_COMMITTED);
5925#endif
5926
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005927#if (DBVER >= 33)
5928 ADD_INT(d, DB_DONOTINDEX);
5929#endif
5930
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005931#if (DBVER >= 41)
5932 _addIntToDict(d, "DB_INCOMPLETE", 0);
5933#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005934 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005935#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005936 ADD_INT(d, DB_KEYEMPTY);
5937 ADD_INT(d, DB_KEYEXIST);
5938 ADD_INT(d, DB_LOCK_DEADLOCK);
5939 ADD_INT(d, DB_LOCK_NOTGRANTED);
5940 ADD_INT(d, DB_NOSERVER);
5941 ADD_INT(d, DB_NOSERVER_HOME);
5942 ADD_INT(d, DB_NOSERVER_ID);
5943 ADD_INT(d, DB_NOTFOUND);
5944 ADD_INT(d, DB_OLD_VERSION);
5945 ADD_INT(d, DB_RUNRECOVERY);
5946 ADD_INT(d, DB_VERIFY_BAD);
5947#if (DBVER >= 33)
5948 ADD_INT(d, DB_PAGE_NOTFOUND);
5949 ADD_INT(d, DB_SECONDARY_BAD);
5950#endif
5951#if (DBVER >= 40)
5952 ADD_INT(d, DB_STAT_CLEAR);
5953 ADD_INT(d, DB_REGION_INIT);
5954 ADD_INT(d, DB_NOLOCKING);
5955 ADD_INT(d, DB_YIELDCPU);
5956 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5957 ADD_INT(d, DB_NOPANIC);
5958#endif
5959
Gregory P. Smith41631e82003-09-21 00:08:14 +00005960#if (DBVER >= 42)
5961 ADD_INT(d, DB_TIME_NOTGRANTED);
5962 ADD_INT(d, DB_TXN_NOT_DURABLE);
5963 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5964 ADD_INT(d, DB_LOG_AUTOREMOVE);
5965 ADD_INT(d, DB_DIRECT_LOG);
5966 ADD_INT(d, DB_DIRECT_DB);
5967 ADD_INT(d, DB_INIT_REP);
5968 ADD_INT(d, DB_ENCRYPT);
5969 ADD_INT(d, DB_CHKSUM);
5970#endif
5971
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005972#if (DBVER >= 43)
5973 ADD_INT(d, DB_LOG_INMEMORY);
5974 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005975 ADD_INT(d, DB_SEQ_DEC);
5976 ADD_INT(d, DB_SEQ_INC);
5977 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005978#endif
5979
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005980#if (DBVER >= 41)
5981 ADD_INT(d, DB_ENCRYPT_AES);
5982 ADD_INT(d, DB_AUTO_COMMIT);
5983#else
5984 /* allow berkeleydb 4.1 aware apps to run on older versions */
5985 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5986#endif
5987
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 ADD_INT(d, EINVAL);
5989 ADD_INT(d, EACCES);
5990 ADD_INT(d, ENOSPC);
5991 ADD_INT(d, ENOMEM);
5992 ADD_INT(d, EAGAIN);
5993 ADD_INT(d, EBUSY);
5994 ADD_INT(d, EEXIST);
5995 ADD_INT(d, ENOENT);
5996 ADD_INT(d, EPERM);
5997
Barry Warsaw1baa9822003-03-31 19:51:29 +00005998#if (DBVER >= 40)
5999 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
6000 ADD_INT(d, DB_SET_TXN_TIMEOUT);
6001#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006002
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006003 /* The exception name must be correct for pickled exception *
6004 * objects to unpickle properly. */
6005#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6006#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6007#else
6008#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6009#endif
6010
6011 /* All the rest of the exceptions derive only from DBError */
6012#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6013 PyDict_SetItemString(d, #name, name)
6014
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006015 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006016 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6017 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006018
Gregory P. Smithe9477062005-06-04 06:46:59 +00006019 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6020 * from both DBError and KeyError, since the API only supports
6021 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006022 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006023 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6024 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006025 Py_file_input, d, d);
6026 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006027 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006028 PyDict_DelItemString(d, "KeyError");
6029
6030
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006031#if !INCOMPLETE_IS_WARNING
6032 MAKE_EX(DBIncompleteError);
6033#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006034 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006035 MAKE_EX(DBKeyEmptyError);
6036 MAKE_EX(DBKeyExistError);
6037 MAKE_EX(DBLockDeadlockError);
6038 MAKE_EX(DBLockNotGrantedError);
6039 MAKE_EX(DBOldVersionError);
6040 MAKE_EX(DBRunRecoveryError);
6041 MAKE_EX(DBVerifyBadError);
6042 MAKE_EX(DBNoServerError);
6043 MAKE_EX(DBNoServerHomeError);
6044 MAKE_EX(DBNoServerIDError);
6045#if (DBVER >= 33)
6046 MAKE_EX(DBPageNotFoundError);
6047 MAKE_EX(DBSecondaryBadError);
6048#endif
6049
6050 MAKE_EX(DBInvalidArgError);
6051 MAKE_EX(DBAccessError);
6052 MAKE_EX(DBNoSpaceError);
6053 MAKE_EX(DBNoMemoryError);
6054 MAKE_EX(DBAgainError);
6055 MAKE_EX(DBBusyError);
6056 MAKE_EX(DBFileExistsError);
6057 MAKE_EX(DBNoSuchFileError);
6058 MAKE_EX(DBPermissionsError);
6059
6060#undef MAKE_EX
6061
6062 /* Check for errors */
6063 if (PyErr_Occurred()) {
6064 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006065 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006066 }
6067}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006068
6069/* allow this module to be named _pybsddb so that it can be installed
6070 * and imported on top of python >= 2.3 that includes its own older
6071 * copy of the library named _bsddb without importing the old version. */
6072DL_EXPORT(void) init_pybsddb(void)
6073{
6074 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6075 init_bsddb();
6076}