blob: 29b6cfa14290b6ba2ed21dfe506fa9354e82bcb2 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000101#define PY_BSDDB_VERSION "4.5.0"
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000102static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000103
104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000106typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298static PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
Neal Norwitz227b5332006-03-22 09:28:35 +0000301static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000302
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000303#define DBObject_Check(v) (Py_Type(v) == &DB_Type)
304#define DBCursorObject_Check(v) (Py_Type(v) == &DBCursor_Type)
305#define DBEnvObject_Check(v) (Py_Type(v) == &DBEnv_Type)
306#define DBTxnObject_Check(v) (Py_Type(v) == &DBTxn_Type)
307#define DBLockObject_Check(v) (Py_Type(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000309#define DBSequenceObject_Check(v) (Py_Type(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000416 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000417 /* 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
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000428 key->data = PyBytes_AS_STRING(keyobj);
429 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000463 "Bytes or Integer object expected for key, %s found",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000464 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000548#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000559#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000603 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000619 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
Gregory P. Smithe9477062005-06-04 06:46:59 +0000706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000724 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000730 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000752
753/* The same, when the value is a time_t */
754static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
755{
756 PyObject* v;
757 /* if the value fits in regular int, use that. */
758#ifdef HAVE_LONG_LONG
759 if (sizeof(time_t) > sizeof(long))
760 v = PyLong_FromLongLong((PY_LONG_LONG) value);
761 else
762#endif
763 v = PyInt_FromLong((long) value);
764 if (!v || PyDict_SetItemString(dict, name, v))
765 PyErr_Clear();
766
767 Py_XDECREF(v);
768}
769
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000770#if (DBVER >= 43)
771/* add an db_seq_t to a dictionary using the given name as a key */
772static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
773{
774 PyObject* v = PyLong_FromLongLong(value);
775 if (!v || PyDict_SetItemString(dict, name, v))
776 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000778 Py_XDECREF(v);
779}
780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781
782
783
784/* --------------------------------------------------------------------- */
785/* Allocators and deallocators */
786
787static DBObject*
788newDBObject(DBEnvObject* arg, int flags)
789{
790 DBObject* self;
791 DB_ENV* db_env = NULL;
792 int err;
793
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 if (self == NULL)
796 return NULL;
797
798 self->haveStat = 0;
799 self->flags = 0;
800 self->setflags = 0;
801 self->myenvobj = NULL;
802#if (DBVER >= 33)
803 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000804 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805 self->primaryDBType = 0;
806#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000807#ifdef HAVE_WEAKREF
808 self->in_weakreflist = NULL;
809#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810
811 /* keep a reference to our python DBEnv object */
812 if (arg) {
813 Py_INCREF(arg);
814 self->myenvobj = arg;
815 db_env = arg->db_env;
816 }
817
818 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000819 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000820 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000821 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
822 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823
824 MYDB_BEGIN_ALLOW_THREADS;
825 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000826 if (self->db != NULL) {
827 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000829 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000831 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000833 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
834 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000835 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (makeDBError(err)) {
837 if (self->myenvobj) {
838 Py_DECREF(self->myenvobj);
839 self->myenvobj = NULL;
840 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000841 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 self = NULL;
843 }
844 return self;
845}
846
847
848static void
849DB_dealloc(DBObject* self)
850{
851 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000852 /* avoid closing a DB when its DBEnv has been closed out from under
853 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000854 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000855 (self->myenvobj && self->myenvobj->db_env))
856 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 MYDB_BEGIN_ALLOW_THREADS;
858 self->db->close(self->db, 0);
859 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000860#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861 } else {
862 PyErr_Warn(PyExc_RuntimeWarning,
863 "DB could not be closed in destructor: DBEnv already closed");
864#endif
865 }
866 self->db = NULL;
867 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000868#ifdef HAVE_WEAKREF
869 if (self->in_weakreflist != NULL) {
870 PyObject_ClearWeakRefs((PyObject *) self);
871 }
872#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000873 if (self->myenvobj) {
874 Py_DECREF(self->myenvobj);
875 self->myenvobj = NULL;
876 }
877#if (DBVER >= 33)
878 if (self->associateCallback != NULL) {
879 Py_DECREF(self->associateCallback);
880 self->associateCallback = NULL;
881 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000882 if (self->btCompareCallback != NULL) {
883 Py_DECREF(self->btCompareCallback);
884 self->btCompareCallback = NULL;
885 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000887 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888}
889
890
891static DBCursorObject*
892newDBCursorObject(DBC* dbc, DBObject* db)
893{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000894 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000895 if (self == NULL)
896 return NULL;
897
898 self->dbc = dbc;
899 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000900#ifdef HAVE_WEAKREF
901 self->in_weakreflist = NULL;
902#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 Py_INCREF(self->mydb);
904 return self;
905}
906
907
908static void
909DBCursor_dealloc(DBCursorObject* self)
910{
911 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000912
913#ifdef HAVE_WEAKREF
914 if (self->in_weakreflist != NULL) {
915 PyObject_ClearWeakRefs((PyObject *) self);
916 }
917#endif
918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919 if (self->dbc != NULL) {
920 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000921 /* If the underlying database has been closed, we don't
922 need to do anything. If the environment has been closed
923 we need to leak, as BerkeleyDB will crash trying to access
924 the environment. There was an exception when the
925 user closed the environment even though there still was
926 a database open. */
927 if (self->mydb->db && self->mydb->myenvobj &&
928 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000929 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 self->dbc = NULL;
931 MYDB_END_ALLOW_THREADS;
932 }
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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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
Thomas Wouters4d70c3d2006-06-08 14:42:34 +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 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001199 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001200 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);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001204 size = PyBytes_Size(result);
1205 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1207 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001208 if (secKey->data) {
1209 memcpy(secKey->data, data, size);
1210 secKey->size = size;
1211 retval = 0;
1212 }
1213 else {
1214 PyErr_SetString(PyExc_MemoryError,
1215 "malloc failed in _db_associateCallback");
1216 PyErr_Print();
1217 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001218 }
1219 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001220 PyErr_SetString(
1221 PyExc_TypeError,
1222 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001223 PyErr_Print();
1224 }
1225
Thomas Woutersb3153832006-03-08 01:47:19 +00001226 Py_XDECREF(args);
1227 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228
1229 MYDB_END_BLOCK_THREADS;
1230 }
1231 return retval;
1232}
1233
1234
1235static PyObject*
1236DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1237{
1238 int err, flags=0;
1239 DBObject* secondaryDB;
1240 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001241#if (DBVER >= 41)
1242 PyObject *txnobj = NULL;
1243 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001244 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001245 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001247 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001248#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001249
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001250#if (DBVER >= 41)
1251 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1252 &secondaryDB, &callback, &flags,
1253 &txnobj)) {
1254#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001256 &secondaryDB, &callback, &flags)) {
1257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001259 }
1260
1261#if (DBVER >= 41)
1262 if (!checkTxnObj(txnobj, &txn)) return NULL;
1263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001264
1265 CHECK_DB_NOT_CLOSED(self);
1266 if (!DBObject_Check(secondaryDB)) {
1267 makeTypeError("DB", (PyObject*)secondaryDB);
1268 return NULL;
1269 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001270 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271 if (callback == Py_None) {
1272 callback = NULL;
1273 }
1274 else if (!PyCallable_Check(callback)) {
1275 makeTypeError("Callable", callback);
1276 return NULL;
1277 }
1278
1279 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001280 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001281 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001282 secondaryDB->associateCallback = callback;
1283 secondaryDB->primaryDBType = _DB_get_type(self);
1284
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001285 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1286 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1287 * The global interepreter lock is not initialized until the first
1288 * thread is created using thread.start_new_thread() or fork() is
1289 * called. that would cause the ALLOW_THREADS here to segfault due
1290 * to a null pointer reference if no threads or child processes
1291 * have been created. This works around that and is a no-op if
1292 * threads have already been initialized.
1293 * (see pybsddb-users mailing list post on 2002-08-07)
1294 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001295#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001296 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001297#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001299#if (DBVER >= 41)
1300 err = self->db->associate(self->db,
1301 txn,
1302 secondaryDB->db,
1303 _db_associateCallback,
1304 flags);
1305#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001306 err = self->db->associate(self->db,
1307 secondaryDB->db,
1308 _db_associateCallback,
1309 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 MYDB_END_ALLOW_THREADS;
1312
1313 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001314 Py_XDECREF(secondaryDB->associateCallback);
1315 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 secondaryDB->primaryDBType = 0;
1317 }
1318
1319 RETURN_IF_ERR();
1320 RETURN_NONE();
1321}
1322
1323
1324#endif
1325
1326
1327static PyObject*
1328DB_close(DBObject* self, PyObject* args)
1329{
1330 int err, flags=0;
1331 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1332 return NULL;
1333 if (self->db != NULL) {
1334 if (self->myenvobj)
1335 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001336 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001337 self->db = NULL;
1338 RETURN_IF_ERR();
1339 }
1340 RETURN_NONE();
1341}
1342
1343
1344#if (DBVER >= 32)
1345static PyObject*
1346_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1347{
1348 int err, flags=0, type;
1349 PyObject* txnobj = NULL;
1350 PyObject* retval = NULL;
1351 DBT key, data;
1352 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001353 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001354
1355 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1356 &txnobj, &flags))
1357 return NULL;
1358
1359 CHECK_DB_NOT_CLOSED(self);
1360 type = _DB_get_type(self);
1361 if (type == -1)
1362 return NULL;
1363 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001364 PyErr_SetString(PyExc_TypeError,
1365 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366 return NULL;
1367 }
1368 if (!checkTxnObj(txnobj, &txn))
1369 return NULL;
1370
1371 CLEAR_DBT(key);
1372 CLEAR_DBT(data);
1373 if (CHECK_DBFLAG(self, DB_THREAD)) {
1374 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1375 data.flags = DB_DBT_MALLOC;
1376 key.flags = DB_DBT_MALLOC;
1377 }
1378
1379 MYDB_BEGIN_ALLOW_THREADS;
1380 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1381 MYDB_END_ALLOW_THREADS;
1382
Gregory P. Smithe9477062005-06-04 06:46:59 +00001383 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1384 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001385 err = 0;
1386 Py_INCREF(Py_None);
1387 retval = Py_None;
1388 }
1389 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001390 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1391 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392 FREE_DBT(key);
1393 FREE_DBT(data);
1394 }
1395
1396 RETURN_IF_ERR();
1397 return retval;
1398}
1399
1400static PyObject*
1401DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1402{
1403 return _DB_consume(self, args, kwargs, DB_CONSUME);
1404}
1405
1406static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001407DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1408 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001409{
1410 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1411}
1412#endif
1413
1414
1415
1416static PyObject*
1417DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1418{
1419 int err, flags=0;
1420 DBC* dbc;
1421 PyObject* txnobj = NULL;
1422 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001423 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001424
1425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1426 &txnobj, &flags))
1427 return NULL;
1428 CHECK_DB_NOT_CLOSED(self);
1429 if (!checkTxnObj(txnobj, &txn))
1430 return NULL;
1431
1432 MYDB_BEGIN_ALLOW_THREADS;
1433 err = self->db->cursor(self->db, txn, &dbc, flags);
1434 MYDB_END_ALLOW_THREADS;
1435 RETURN_IF_ERR();
1436 return (PyObject*) newDBCursorObject(dbc, self);
1437}
1438
1439
1440static PyObject*
1441DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1442{
1443 PyObject* txnobj = NULL;
1444 int flags = 0;
1445 PyObject* keyobj;
1446 DBT key;
1447 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001448 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001449
1450 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1451 &keyobj, &txnobj, &flags))
1452 return NULL;
1453 CHECK_DB_NOT_CLOSED(self);
1454 if (!make_key_dbt(self, keyobj, &key, NULL))
1455 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001456 if (!checkTxnObj(txnobj, &txn)) {
1457 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001458 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001459 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001460
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001461 if (-1 == _DB_delete(self, txn, &key, 0)) {
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
1466 FREE_DBT(key);
1467 RETURN_NONE();
1468}
1469
1470
1471static PyObject*
1472DB_fd(DBObject* self, PyObject* args)
1473{
1474 int err, the_fd;
1475
1476 if (!PyArg_ParseTuple(args,":fd"))
1477 return NULL;
1478 CHECK_DB_NOT_CLOSED(self);
1479
1480 MYDB_BEGIN_ALLOW_THREADS;
1481 err = self->db->fd(self->db, &the_fd);
1482 MYDB_END_ALLOW_THREADS;
1483 RETURN_IF_ERR();
1484 return PyInt_FromLong(the_fd);
1485}
1486
1487
1488static PyObject*
1489DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1490{
1491 int err, flags=0;
1492 PyObject* txnobj = NULL;
1493 PyObject* keyobj;
1494 PyObject* dfltobj = NULL;
1495 PyObject* retval = NULL;
1496 int dlen = -1;
1497 int doff = -1;
1498 DBT key, data;
1499 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001500 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001501 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502
1503 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001504 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1505 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001506 return NULL;
1507
1508 CHECK_DB_NOT_CLOSED(self);
1509 if (!make_key_dbt(self, keyobj, &key, &flags))
1510 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001511 if (!checkTxnObj(txnobj, &txn)) {
1512 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001513 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001514 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515
1516 CLEAR_DBT(data);
1517 if (CHECK_DBFLAG(self, DB_THREAD)) {
1518 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1519 data.flags = DB_DBT_MALLOC;
1520 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001521 if (!add_partial_dbt(&data, dlen, doff)) {
1522 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001523 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001524 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525
1526 MYDB_BEGIN_ALLOW_THREADS;
1527 err = self->db->get(self->db, txn, &key, &data, flags);
1528 MYDB_END_ALLOW_THREADS;
1529
Gregory P. Smithe9477062005-06-04 06:46:59 +00001530 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001531 err = 0;
1532 Py_INCREF(dfltobj);
1533 retval = dfltobj;
1534 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001535 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1536 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001537 err = 0;
1538 Py_INCREF(Py_None);
1539 retval = Py_None;
1540 }
1541 else if (!err) {
1542 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001543 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1544 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001545 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001546 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001547 FREE_DBT(data);
1548 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001549 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550
1551 RETURN_IF_ERR();
1552 return retval;
1553}
1554
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001555#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001556static PyObject*
1557DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1558{
1559 int err, flags=0;
1560 PyObject* txnobj = NULL;
1561 PyObject* keyobj;
1562 PyObject* dfltobj = NULL;
1563 PyObject* retval = NULL;
1564 int dlen = -1;
1565 int doff = -1;
1566 DBT key, pkey, data;
1567 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001568 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001569 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001570
1571 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1572 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1573 &doff))
1574 return NULL;
1575
1576 CHECK_DB_NOT_CLOSED(self);
1577 if (!make_key_dbt(self, keyobj, &key, &flags))
1578 return NULL;
1579 if (!checkTxnObj(txnobj, &txn)) {
1580 FREE_DBT(key);
1581 return NULL;
1582 }
1583
1584 CLEAR_DBT(data);
1585 if (CHECK_DBFLAG(self, DB_THREAD)) {
1586 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1587 data.flags = DB_DBT_MALLOC;
1588 }
1589 if (!add_partial_dbt(&data, dlen, doff)) {
1590 FREE_DBT(key);
1591 return NULL;
1592 }
1593
1594 CLEAR_DBT(pkey);
1595 pkey.flags = DB_DBT_MALLOC;
1596
1597 MYDB_BEGIN_ALLOW_THREADS;
1598 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1599 MYDB_END_ALLOW_THREADS;
1600
Gregory P. Smithe9477062005-06-04 06:46:59 +00001601 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001602 err = 0;
1603 Py_INCREF(dfltobj);
1604 retval = dfltobj;
1605 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001606 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1607 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001608 err = 0;
1609 Py_INCREF(Py_None);
1610 retval = Py_None;
1611 }
1612 else if (!err) {
1613 PyObject *pkeyObj;
1614 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001615 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616
1617 if (self->primaryDBType == DB_RECNO ||
1618 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001619 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001620 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001621 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001622
1623 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1624 {
1625 PyObject *keyObj;
1626 int type = _DB_get_type(self);
1627 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001628 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001629 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001630 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001631#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001632 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001633#else
1634 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1635#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001636 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001637 }
1638 else /* return just the pkey and data */
1639 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001640#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001641 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001642#else
1643 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1644#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001645 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001646 Py_DECREF(dataObj);
1647 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001648 FREE_DBT(pkey);
1649 FREE_DBT(data);
1650 }
1651 FREE_DBT(key);
1652
1653 RETURN_IF_ERR();
1654 return retval;
1655}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001656#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001657
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658
1659/* Return size of entry */
1660static PyObject*
1661DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1662{
1663 int err, flags=0;
1664 PyObject* txnobj = NULL;
1665 PyObject* keyobj;
1666 PyObject* retval = NULL;
1667 DBT key, data;
1668 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001669 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001670
1671 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1672 &keyobj, &txnobj))
1673 return NULL;
1674 CHECK_DB_NOT_CLOSED(self);
1675 if (!make_key_dbt(self, keyobj, &key, &flags))
1676 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001677 if (!checkTxnObj(txnobj, &txn)) {
1678 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001679 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001680 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001681 CLEAR_DBT(data);
1682
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001683 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1684 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685 data.flags = DB_DBT_USERMEM;
1686 data.ulen = 0;
1687 MYDB_BEGIN_ALLOW_THREADS;
1688 err = self->db->get(self->db, txn, &key, &data, flags);
1689 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001690 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691 retval = PyInt_FromLong((long)data.size);
1692 err = 0;
1693 }
1694
1695 FREE_DBT(key);
1696 FREE_DBT(data);
1697 RETURN_IF_ERR();
1698 return retval;
1699}
1700
1701
1702static PyObject*
1703DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1704{
1705 int err, flags=0;
1706 PyObject* txnobj = NULL;
1707 PyObject* keyobj;
1708 PyObject* dataobj;
1709 PyObject* retval = NULL;
1710 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001711 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001712 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001713 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714
1715
1716 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1717 &keyobj, &dataobj, &txnobj, &flags))
1718 return NULL;
1719
1720 CHECK_DB_NOT_CLOSED(self);
1721 if (!make_key_dbt(self, keyobj, &key, NULL))
1722 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001723 if ( !make_dbt(dataobj, &data) ||
1724 !checkTxnObj(txnobj, &txn) )
1725 {
1726 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001728 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729
1730 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001731 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732
1733 if (CHECK_DBFLAG(self, DB_THREAD)) {
1734 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001735 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001736 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001737 }
1738
1739 MYDB_BEGIN_ALLOW_THREADS;
1740 err = self->db->get(self->db, txn, &key, &data, flags);
1741 MYDB_END_ALLOW_THREADS;
1742
Gregory P. Smithe9477062005-06-04 06:46:59 +00001743 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1744 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 err = 0;
1746 Py_INCREF(Py_None);
1747 retval = Py_None;
1748 }
1749 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001750 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001751 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001752
1753 /* Even though the flags require DB_DBT_MALLOC, data is not always
1754 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1755 if (data.data != orig_data)
1756 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001757 }
1758
1759 FREE_DBT(key);
1760 RETURN_IF_ERR();
1761 return retval;
1762}
1763
1764
1765static PyObject*
1766DB_get_byteswapped(DBObject* self, PyObject* args)
1767{
1768#if (DBVER >= 33)
1769 int err = 0;
1770#endif
1771 int retval = -1;
1772
1773 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1774 return NULL;
1775 CHECK_DB_NOT_CLOSED(self);
1776
1777#if (DBVER >= 33)
1778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->get_byteswapped(self->db, &retval);
1780 MYDB_END_ALLOW_THREADS;
1781 RETURN_IF_ERR();
1782#else
1783 MYDB_BEGIN_ALLOW_THREADS;
1784 retval = self->db->get_byteswapped(self->db);
1785 MYDB_END_ALLOW_THREADS;
1786#endif
1787 return PyInt_FromLong(retval);
1788}
1789
1790
1791static PyObject*
1792DB_get_type(DBObject* self, PyObject* args)
1793{
1794 int type;
1795
1796 if (!PyArg_ParseTuple(args,":get_type"))
1797 return NULL;
1798 CHECK_DB_NOT_CLOSED(self);
1799
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001800 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 if (type == -1)
1802 return NULL;
1803 return PyInt_FromLong(type);
1804}
1805
1806
1807static PyObject*
1808DB_join(DBObject* self, PyObject* args)
1809{
1810 int err, flags=0;
1811 int length, x;
1812 PyObject* cursorsObj;
1813 DBC** cursors;
1814 DBC* dbc;
1815
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1817 return NULL;
1818
1819 CHECK_DB_NOT_CLOSED(self);
1820
1821 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001822 PyErr_SetString(PyExc_TypeError,
1823 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001824 return NULL;
1825 }
1826
1827 length = PyObject_Length(cursorsObj);
1828 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001829 if (!cursors) {
1830 PyErr_NoMemory();
1831 return NULL;
1832 }
1833
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 cursors[length] = NULL;
1835 for (x=0; x<length; x++) {
1836 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001837 if (item == NULL) {
1838 free(cursors);
1839 return NULL;
1840 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001841 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001842 PyErr_SetString(PyExc_TypeError,
1843 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 free(cursors);
1845 return NULL;
1846 }
1847 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001848 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849 }
1850
1851 MYDB_BEGIN_ALLOW_THREADS;
1852 err = self->db->join(self->db, cursors, &dbc, flags);
1853 MYDB_END_ALLOW_THREADS;
1854 free(cursors);
1855 RETURN_IF_ERR();
1856
Gregory P. Smith7441e652003-11-03 21:35:31 +00001857 /* FIXME: this is a buggy interface. The returned cursor
1858 contains internal references to the passed in cursors
1859 but does not hold python references to them or prevent
1860 them from being closed prematurely. This can cause
1861 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001862 return (PyObject*) newDBCursorObject(dbc, self);
1863}
1864
1865
1866static PyObject*
1867DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1868{
1869 int err, flags=0;
1870 PyObject* txnobj = NULL;
1871 PyObject* keyobj;
1872 DBT key;
1873 DB_TXN *txn = NULL;
1874 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001875 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001876
1877 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1878 &keyobj, &txnobj, &flags))
1879 return NULL;
1880 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001881 if (!make_dbt(keyobj, &key))
1882 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001883 return NULL;
1884 if (!checkTxnObj(txnobj, &txn))
1885 return NULL;
1886
1887 MYDB_BEGIN_ALLOW_THREADS;
1888 err = self->db->key_range(self->db, txn, &key, &range, flags);
1889 MYDB_END_ALLOW_THREADS;
1890
1891 RETURN_IF_ERR();
1892 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1893}
1894
1895
1896static PyObject*
1897DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1898{
1899 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1900 char* filename = NULL;
1901 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001902#if (DBVER >= 41)
1903 PyObject *txnobj = NULL;
1904 DB_TXN *txn = NULL;
1905 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001906 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001907 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1908 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001909 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001910 "filename", "dbtype", "flags", "mode", "txn", NULL};
1911#else
1912 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001913 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001914 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1915 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001916 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001917 "filename", "dbtype", "flags", "mode", NULL};
1918#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001919
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001920#if (DBVER >= 41)
1921 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1922 &filename, &dbname, &type, &flags, &mode,
1923 &txnobj))
1924#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001926 &filename, &dbname, &type, &flags,
1927 &mode))
1928#endif
1929 {
1930 PyErr_Clear();
1931 type = DB_UNKNOWN; flags = 0; mode = 0660;
1932 filename = NULL; dbname = NULL;
1933#if (DBVER >= 41)
1934 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1935 kwnames_basic,
1936 &filename, &type, &flags, &mode,
1937 &txnobj))
1938 return NULL;
1939#else
1940 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1941 kwnames_basic,
1942 &filename, &type, &flags, &mode))
1943 return NULL;
1944#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945 }
1946
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001947#if (DBVER >= 41)
1948 if (!checkTxnObj(txnobj, &txn)) return NULL;
1949#endif
1950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001952 PyObject *t = Py_BuildValue("(is)", 0,
1953 "Cannot call open() twice for DB object");
1954 PyErr_SetObject(DBError, t);
1955 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956 return NULL;
1957 }
1958
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959#if 0 && (DBVER >= 41)
1960 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1961 && (self->myenvobj->flags & DB_INIT_TXN))
1962 {
1963 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1964 * explicitly passed) but we are in a transaction ready environment:
1965 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1966 * to work on BerkeleyDB 4.1 without needing to modify their
1967 * DBEnv or DB open calls.
1968 * TODO make this behaviour of the library configurable.
1969 */
1970 flags |= DB_AUTO_COMMIT;
1971 }
1972#endif
1973
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001974 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001975#if (DBVER >= 41)
1976 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1977#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001978 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001979#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001980 MYDB_END_ALLOW_THREADS;
1981 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001982 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 self->db = NULL;
1984 return NULL;
1985 }
1986
1987 self->flags = flags;
1988 RETURN_NONE();
1989}
1990
1991
1992static PyObject*
1993DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1994{
1995 int flags=0;
1996 PyObject* txnobj = NULL;
1997 int dlen = -1;
1998 int doff = -1;
1999 PyObject* keyobj, *dataobj, *retval;
2000 DBT key, data;
2001 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002002 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002003 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002004
2005 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2006 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2007 return NULL;
2008
2009 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002010 if (!make_key_dbt(self, keyobj, &key, NULL))
2011 return NULL;
2012 if ( !make_dbt(dataobj, &data) ||
2013 !add_partial_dbt(&data, dlen, doff) ||
2014 !checkTxnObj(txnobj, &txn) )
2015 {
2016 FREE_DBT(key);
2017 return NULL;
2018 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002019
2020 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2021 FREE_DBT(key);
2022 return NULL;
2023 }
2024
2025 if (flags & DB_APPEND)
2026 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2027 else {
2028 retval = Py_None;
2029 Py_INCREF(retval);
2030 }
2031 FREE_DBT(key);
2032 return retval;
2033}
2034
2035
2036
2037static PyObject*
2038DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2039{
2040 char* filename;
2041 char* database = NULL;
2042 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002043 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002044
2045 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2046 &filename, &database, &flags))
2047 return NULL;
2048 CHECK_DB_NOT_CLOSED(self);
2049
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002050 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002051 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002052 RETURN_IF_ERR();
2053 RETURN_NONE();
2054}
2055
2056
2057
2058static PyObject*
2059DB_rename(DBObject* self, PyObject* args)
2060{
2061 char* filename;
2062 char* database;
2063 char* newname;
2064 int err, flags=0;
2065
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002066 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2067 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002068 return NULL;
2069 CHECK_DB_NOT_CLOSED(self);
2070
2071 MYDB_BEGIN_ALLOW_THREADS;
2072 err = self->db->rename(self->db, filename, database, newname, flags);
2073 MYDB_END_ALLOW_THREADS;
2074 RETURN_IF_ERR();
2075 RETURN_NONE();
2076}
2077
2078
2079static PyObject*
2080DB_set_bt_minkey(DBObject* self, PyObject* args)
2081{
2082 int err, minkey;
2083
2084 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2085 return NULL;
2086 CHECK_DB_NOT_CLOSED(self);
2087
2088 MYDB_BEGIN_ALLOW_THREADS;
2089 err = self->db->set_bt_minkey(self->db, minkey);
2090 MYDB_END_ALLOW_THREADS;
2091 RETURN_IF_ERR();
2092 RETURN_NONE();
2093}
2094
Neal Norwitz84562352005-10-20 04:30:15 +00002095#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002097_default_cmp(const DBT *leftKey,
2098 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002099{
2100 int res;
2101 int lsize = leftKey->size, rsize = rightKey->size;
2102
Georg Brandlef1701f2006-03-07 14:57:48 +00002103 res = memcmp(leftKey->data, rightKey->data,
2104 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002105
2106 if (res == 0) {
2107 if (lsize < rsize) {
2108 res = -1;
2109 }
2110 else if (lsize > rsize) {
2111 res = 1;
2112 }
2113 }
2114 return res;
2115}
2116
2117static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002118_db_compareCallback(DB* db,
2119 const DBT *leftKey,
2120 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002121{
2122 int res = 0;
2123 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002124 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126
2127 if (self == NULL || self->btCompareCallback == NULL) {
2128 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 PyErr_SetString(PyExc_TypeError,
2130 (self == 0
2131 ? "DB_bt_compare db is NULL."
2132 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002133 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 PyErr_Print();
2135 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002136 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002137 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002138 MYDB_BEGIN_BLOCK_THREADS;
2139
Thomas Woutersb3153832006-03-08 01:47:19 +00002140 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2141 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002142 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002143 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002144 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002148 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002149 PyErr_Print();
2150 res = _default_cmp(leftKey, rightKey);
2151 } else if (PyInt_Check(result)) {
2152 res = PyInt_AsLong(result);
2153 } else {
2154 PyErr_SetString(PyExc_TypeError,
2155 "DB_bt_compare callback MUST return an int.");
2156 /* we're in a callback within the DB code, we can't raise */
2157 PyErr_Print();
2158 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002159 }
2160
Thomas Woutersb3153832006-03-08 01:47:19 +00002161 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002162 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163
2164 MYDB_END_BLOCK_THREADS;
2165 }
2166 return res;
2167}
2168
2169static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002170DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002171{
2172 int err;
2173 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002174 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002175
Georg Brandlef1701f2006-03-07 14:57:48 +00002176 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002177 return NULL;
2178
Georg Brandlef1701f2006-03-07 14:57:48 +00002179 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002180
Georg Brandlef1701f2006-03-07 14:57:48 +00002181 if (!PyCallable_Check(comparator)) {
2182 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183 return NULL;
2184 }
2185
2186 /*
2187 * Perform a test call of the comparator function with two empty
2188 * string objects here. verify that it returns an int (0).
2189 * err if not.
2190 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002191 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002192 result = PyEval_CallObject(comparator, tuple);
2193 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002194 if (result == NULL)
2195 return NULL;
2196 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002197 PyErr_SetString(PyExc_TypeError,
2198 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002199 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002200 } else if (PyInt_AsLong(result) != 0) {
2201 PyErr_SetString(PyExc_TypeError,
2202 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002203 return NULL;
2204 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002205 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002206
2207 /* We don't accept multiple set_bt_compare operations, in order to
2208 * simplify the code. This would have no real use, as one cannot
2209 * change the function once the db is opened anyway */
2210 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002211 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002212 return NULL;
2213 }
2214
Georg Brandlef1701f2006-03-07 14:57:48 +00002215 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216 self->btCompareCallback = comparator;
2217
2218 /* This is to workaround a problem with un-initialized threads (see
2219 comment in DB_associate) */
2220#ifdef WITH_THREAD
2221 PyEval_InitThreads();
2222#endif
2223
Thomas Woutersb3153832006-03-08 01:47:19 +00002224 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002225
2226 if (err) {
2227 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002228 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002229 self->btCompareCallback = NULL;
2230 }
2231
Georg Brandlef1701f2006-03-07 14:57:48 +00002232 RETURN_IF_ERR();
2233 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002234}
Neal Norwitz84562352005-10-20 04:30:15 +00002235#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002236
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002237
2238static PyObject*
2239DB_set_cachesize(DBObject* self, PyObject* args)
2240{
2241 int err;
2242 int gbytes = 0, bytes = 0, ncache = 0;
2243
2244 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2245 &gbytes,&bytes,&ncache))
2246 return NULL;
2247 CHECK_DB_NOT_CLOSED(self);
2248
2249 MYDB_BEGIN_ALLOW_THREADS;
2250 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2251 MYDB_END_ALLOW_THREADS;
2252 RETURN_IF_ERR();
2253 RETURN_NONE();
2254}
2255
2256
2257static PyObject*
2258DB_set_flags(DBObject* self, PyObject* args)
2259{
2260 int err, flags;
2261
2262 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2263 return NULL;
2264 CHECK_DB_NOT_CLOSED(self);
2265
2266 MYDB_BEGIN_ALLOW_THREADS;
2267 err = self->db->set_flags(self->db, flags);
2268 MYDB_END_ALLOW_THREADS;
2269 RETURN_IF_ERR();
2270
2271 self->setflags |= flags;
2272 RETURN_NONE();
2273}
2274
2275
2276static PyObject*
2277DB_set_h_ffactor(DBObject* self, PyObject* args)
2278{
2279 int err, ffactor;
2280
2281 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2282 return NULL;
2283 CHECK_DB_NOT_CLOSED(self);
2284
2285 MYDB_BEGIN_ALLOW_THREADS;
2286 err = self->db->set_h_ffactor(self->db, ffactor);
2287 MYDB_END_ALLOW_THREADS;
2288 RETURN_IF_ERR();
2289 RETURN_NONE();
2290}
2291
2292
2293static PyObject*
2294DB_set_h_nelem(DBObject* self, PyObject* args)
2295{
2296 int err, nelem;
2297
2298 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2299 return NULL;
2300 CHECK_DB_NOT_CLOSED(self);
2301
2302 MYDB_BEGIN_ALLOW_THREADS;
2303 err = self->db->set_h_nelem(self->db, nelem);
2304 MYDB_END_ALLOW_THREADS;
2305 RETURN_IF_ERR();
2306 RETURN_NONE();
2307}
2308
2309
2310static PyObject*
2311DB_set_lorder(DBObject* self, PyObject* args)
2312{
2313 int err, lorder;
2314
2315 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2316 return NULL;
2317 CHECK_DB_NOT_CLOSED(self);
2318
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->set_lorder(self->db, lorder);
2321 MYDB_END_ALLOW_THREADS;
2322 RETURN_IF_ERR();
2323 RETURN_NONE();
2324}
2325
2326
2327static PyObject*
2328DB_set_pagesize(DBObject* self, PyObject* args)
2329{
2330 int err, pagesize;
2331
2332 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2333 return NULL;
2334 CHECK_DB_NOT_CLOSED(self);
2335
2336 MYDB_BEGIN_ALLOW_THREADS;
2337 err = self->db->set_pagesize(self->db, pagesize);
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340 RETURN_NONE();
2341}
2342
2343
2344static PyObject*
2345DB_set_re_delim(DBObject* self, PyObject* args)
2346{
2347 int err;
2348 char delim;
2349
2350 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2351 PyErr_Clear();
2352 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2353 return NULL;
2354 }
2355
2356 CHECK_DB_NOT_CLOSED(self);
2357
2358 MYDB_BEGIN_ALLOW_THREADS;
2359 err = self->db->set_re_delim(self->db, delim);
2360 MYDB_END_ALLOW_THREADS;
2361 RETURN_IF_ERR();
2362 RETURN_NONE();
2363}
2364
2365static PyObject*
2366DB_set_re_len(DBObject* self, PyObject* args)
2367{
2368 int err, len;
2369
2370 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2371 return NULL;
2372 CHECK_DB_NOT_CLOSED(self);
2373
2374 MYDB_BEGIN_ALLOW_THREADS;
2375 err = self->db->set_re_len(self->db, len);
2376 MYDB_END_ALLOW_THREADS;
2377 RETURN_IF_ERR();
2378 RETURN_NONE();
2379}
2380
2381
2382static PyObject*
2383DB_set_re_pad(DBObject* self, PyObject* args)
2384{
2385 int err;
2386 char pad;
2387
2388 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2389 PyErr_Clear();
2390 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2391 return NULL;
2392 }
2393 CHECK_DB_NOT_CLOSED(self);
2394
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_pad(self->db, pad);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2400}
2401
2402
2403static PyObject*
2404DB_set_re_source(DBObject* self, PyObject* args)
2405{
2406 int err;
2407 char *re_source;
2408
2409 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2410 return NULL;
2411 CHECK_DB_NOT_CLOSED(self);
2412
2413 MYDB_BEGIN_ALLOW_THREADS;
2414 err = self->db->set_re_source(self->db, re_source);
2415 MYDB_END_ALLOW_THREADS;
2416 RETURN_IF_ERR();
2417 RETURN_NONE();
2418}
2419
2420
2421#if (DBVER >= 32)
2422static PyObject*
2423DB_set_q_extentsize(DBObject* self, PyObject* args)
2424{
2425 int err;
2426 int extentsize;
2427
2428 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2429 return NULL;
2430 CHECK_DB_NOT_CLOSED(self);
2431
2432 MYDB_BEGIN_ALLOW_THREADS;
2433 err = self->db->set_q_extentsize(self->db, extentsize);
2434 MYDB_END_ALLOW_THREADS;
2435 RETURN_IF_ERR();
2436 RETURN_NONE();
2437}
2438#endif
2439
2440static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002441DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002442{
2443 int err, flags = 0, type;
2444 void* sp;
2445 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002446#if (DBVER >= 43)
2447 PyObject* txnobj = NULL;
2448 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002449 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002450#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002451 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002452#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002453
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002454#if (DBVER >= 43)
2455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2456 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002457 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002458 if (!checkTxnObj(txnobj, &txn))
2459 return NULL;
2460#else
2461 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2462 return NULL;
2463#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002464 CHECK_DB_NOT_CLOSED(self);
2465
2466 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002467#if (DBVER >= 43)
2468 err = self->db->stat(self->db, txn, &sp, flags);
2469#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002470 err = self->db->stat(self->db, &sp, flags);
2471#else
2472 err = self->db->stat(self->db, &sp, NULL, flags);
2473#endif
2474 MYDB_END_ALLOW_THREADS;
2475 RETURN_IF_ERR();
2476
2477 self->haveStat = 1;
2478
2479 /* Turn the stat structure into a dictionary */
2480 type = _DB_get_type(self);
2481 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2482 free(sp);
2483 return NULL;
2484 }
2485
2486#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2487#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2488#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2489
2490 switch (type) {
2491 case DB_HASH:
2492 MAKE_HASH_ENTRY(magic);
2493 MAKE_HASH_ENTRY(version);
2494 MAKE_HASH_ENTRY(nkeys);
2495 MAKE_HASH_ENTRY(ndata);
2496 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002497#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002498 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002499#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002500 MAKE_HASH_ENTRY(ffactor);
2501 MAKE_HASH_ENTRY(buckets);
2502 MAKE_HASH_ENTRY(free);
2503 MAKE_HASH_ENTRY(bfree);
2504 MAKE_HASH_ENTRY(bigpages);
2505 MAKE_HASH_ENTRY(big_bfree);
2506 MAKE_HASH_ENTRY(overflows);
2507 MAKE_HASH_ENTRY(ovfl_free);
2508 MAKE_HASH_ENTRY(dup);
2509 MAKE_HASH_ENTRY(dup_free);
2510 break;
2511
2512 case DB_BTREE:
2513 case DB_RECNO:
2514 MAKE_BT_ENTRY(magic);
2515 MAKE_BT_ENTRY(version);
2516 MAKE_BT_ENTRY(nkeys);
2517 MAKE_BT_ENTRY(ndata);
2518 MAKE_BT_ENTRY(pagesize);
2519 MAKE_BT_ENTRY(minkey);
2520 MAKE_BT_ENTRY(re_len);
2521 MAKE_BT_ENTRY(re_pad);
2522 MAKE_BT_ENTRY(levels);
2523 MAKE_BT_ENTRY(int_pg);
2524 MAKE_BT_ENTRY(leaf_pg);
2525 MAKE_BT_ENTRY(dup_pg);
2526 MAKE_BT_ENTRY(over_pg);
2527 MAKE_BT_ENTRY(free);
2528 MAKE_BT_ENTRY(int_pgfree);
2529 MAKE_BT_ENTRY(leaf_pgfree);
2530 MAKE_BT_ENTRY(dup_pgfree);
2531 MAKE_BT_ENTRY(over_pgfree);
2532 break;
2533
2534 case DB_QUEUE:
2535 MAKE_QUEUE_ENTRY(magic);
2536 MAKE_QUEUE_ENTRY(version);
2537 MAKE_QUEUE_ENTRY(nkeys);
2538 MAKE_QUEUE_ENTRY(ndata);
2539 MAKE_QUEUE_ENTRY(pagesize);
2540 MAKE_QUEUE_ENTRY(pages);
2541 MAKE_QUEUE_ENTRY(re_len);
2542 MAKE_QUEUE_ENTRY(re_pad);
2543 MAKE_QUEUE_ENTRY(pgfree);
2544#if (DBVER == 31)
2545 MAKE_QUEUE_ENTRY(start);
2546#endif
2547 MAKE_QUEUE_ENTRY(first_recno);
2548 MAKE_QUEUE_ENTRY(cur_recno);
2549 break;
2550
2551 default:
2552 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2553 Py_DECREF(d);
2554 d = NULL;
2555 }
2556
2557#undef MAKE_HASH_ENTRY
2558#undef MAKE_BT_ENTRY
2559#undef MAKE_QUEUE_ENTRY
2560
2561 free(sp);
2562 return d;
2563}
2564
2565static PyObject*
2566DB_sync(DBObject* self, PyObject* args)
2567{
2568 int err;
2569 int flags = 0;
2570
2571 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2572 return NULL;
2573 CHECK_DB_NOT_CLOSED(self);
2574
2575 MYDB_BEGIN_ALLOW_THREADS;
2576 err = self->db->sync(self->db, flags);
2577 MYDB_END_ALLOW_THREADS;
2578 RETURN_IF_ERR();
2579 RETURN_NONE();
2580}
2581
2582
2583#if (DBVER >= 33)
2584static PyObject*
2585DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2586{
2587 int err, flags=0;
2588 u_int32_t count=0;
2589 PyObject* txnobj = NULL;
2590 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002591 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002592
2593 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2594 &txnobj, &flags))
2595 return NULL;
2596 CHECK_DB_NOT_CLOSED(self);
2597 if (!checkTxnObj(txnobj, &txn))
2598 return NULL;
2599
2600 MYDB_BEGIN_ALLOW_THREADS;
2601 err = self->db->truncate(self->db, txn, &count, flags);
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2604 return PyInt_FromLong(count);
2605}
2606#endif
2607
2608
2609static PyObject*
2610DB_upgrade(DBObject* self, PyObject* args)
2611{
2612 int err, flags=0;
2613 char *filename;
2614
2615 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2616 return NULL;
2617 CHECK_DB_NOT_CLOSED(self);
2618
2619 MYDB_BEGIN_ALLOW_THREADS;
2620 err = self->db->upgrade(self->db, filename, flags);
2621 MYDB_END_ALLOW_THREADS;
2622 RETURN_IF_ERR();
2623 RETURN_NONE();
2624}
2625
2626
2627static PyObject*
2628DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2629{
2630 int err, flags=0;
2631 char* fileName;
2632 char* dbName=NULL;
2633 char* outFileName=NULL;
2634 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002635 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002636 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002637
2638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2639 &fileName, &dbName, &outFileName, &flags))
2640 return NULL;
2641
2642 CHECK_DB_NOT_CLOSED(self);
2643 if (outFileName)
2644 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002645 /* XXX(nnorwitz): it should probably be an exception if outFile
2646 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002647
2648 MYDB_BEGIN_ALLOW_THREADS;
2649 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2650 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002651 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002652 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002653
2654 /* DB.verify acts as a DB handle destructor (like close); this was
2655 * documented in BerkeleyDB 4.2 but had the undocumented effect
2656 * of not being safe in prior versions while still requiring an explicit
2657 * DB.close call afterwards. Lets call close for the user to emulate
2658 * the safe 4.2 behaviour. */
2659#if (DBVER <= 41)
2660 self->db->close(self->db, 0);
2661#endif
2662 self->db = NULL;
2663
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002664 RETURN_IF_ERR();
2665 RETURN_NONE();
2666}
2667
2668
2669static PyObject*
2670DB_set_get_returns_none(DBObject* self, PyObject* args)
2671{
2672 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002673 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002674
2675 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2676 return NULL;
2677 CHECK_DB_NOT_CLOSED(self);
2678
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002679 if (self->moduleFlags.getReturnsNone)
2680 ++oldValue;
2681 if (self->moduleFlags.cursorSetReturnsNone)
2682 ++oldValue;
2683 self->moduleFlags.getReturnsNone = (flags >= 1);
2684 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002685 return PyInt_FromLong(oldValue);
2686}
2687
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002688#if (DBVER >= 41)
2689static PyObject*
2690DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2691{
2692 int err;
2693 u_int32_t flags=0;
2694 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002695 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002696
2697 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2698 &passwd, &flags)) {
2699 return NULL;
2700 }
2701
2702 MYDB_BEGIN_ALLOW_THREADS;
2703 err = self->db->set_encrypt(self->db, passwd, flags);
2704 MYDB_END_ALLOW_THREADS;
2705
2706 RETURN_IF_ERR();
2707 RETURN_NONE();
2708}
2709#endif /* DBVER >= 41 */
2710
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002711
2712/*-------------------------------------------------------------- */
2713/* Mapping and Dictionary-like access routines */
2714
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002715Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716{
2717 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002718 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002719 int flags = 0;
2720 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002721 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002722
2723 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002724 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2725 PyErr_SetObject(DBError, t);
2726 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 return -1;
2728 }
2729
2730 if (self->haveStat) { /* Has the stat function been called recently? If
2731 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002732 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002733 }
2734
2735 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002736redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002737#if (DBVER >= 43)
2738 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2739#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 err = self->db->stat(self->db, &sp, flags);
2741#else
2742 err = self->db->stat(self->db, &sp, NULL, flags);
2743#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002744
2745 /* All the stat structures have matching fields upto the ndata field,
2746 so we can use any of them for the type cast */
2747 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2748
2749 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2750 * redo a full stat to make sure.
2751 * Fixes SF python bug 1493322, pybsddb bug 1184012
2752 */
2753 if (size == 0 && (flags & DB_FAST_STAT)) {
2754 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002755 if (!err)
2756 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002757 goto redo_stat_for_length;
2758 }
2759
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002760 MYDB_END_ALLOW_THREADS;
2761
2762 if (err)
2763 return -1;
2764
2765 self->haveStat = 1;
2766
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002767 free(sp);
2768 return size;
2769}
2770
2771
2772PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2773{
2774 int err;
2775 PyObject* retval;
2776 DBT key;
2777 DBT data;
2778
2779 CHECK_DB_NOT_CLOSED(self);
2780 if (!make_key_dbt(self, keyobj, &key, NULL))
2781 return NULL;
2782
2783 CLEAR_DBT(data);
2784 if (CHECK_DBFLAG(self, DB_THREAD)) {
2785 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2786 data.flags = DB_DBT_MALLOC;
2787 }
2788 MYDB_BEGIN_ALLOW_THREADS;
2789 err = self->db->get(self->db, NULL, &key, &data, 0);
2790 MYDB_END_ALLOW_THREADS;
2791 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2792 PyErr_SetObject(PyExc_KeyError, keyobj);
2793 retval = NULL;
2794 }
2795 else if (makeDBError(err)) {
2796 retval = NULL;
2797 }
2798 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002799 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002800 FREE_DBT(data);
2801 }
2802
2803 FREE_DBT(key);
2804 return retval;
2805}
2806
2807
2808static int
2809DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2810{
2811 DBT key, data;
2812 int retval;
2813 int flags = 0;
2814
2815 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002816 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2817 PyErr_SetObject(DBError, t);
2818 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002819 return -1;
2820 }
2821
2822 if (!make_key_dbt(self, keyobj, &key, NULL))
2823 return -1;
2824
2825 if (dataobj != NULL) {
2826 if (!make_dbt(dataobj, &data))
2827 retval = -1;
2828 else {
2829 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002830 /* dictionaries shouldn't have duplicate keys */
2831 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002832 retval = _DB_put(self, NULL, &key, &data, flags);
2833
2834 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002835 /* try deleting any old record that matches and then PUT it
2836 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002837 _DB_delete(self, NULL, &key, 0);
2838 PyErr_Clear();
2839 retval = _DB_put(self, NULL, &key, &data, flags);
2840 }
2841 }
2842 }
2843 else {
2844 /* dataobj == NULL, so delete the key */
2845 retval = _DB_delete(self, NULL, &key, 0);
2846 }
2847 FREE_DBT(key);
2848 return retval;
2849}
2850
2851
2852static PyObject*
2853DB_has_key(DBObject* self, PyObject* args)
2854{
2855 int err;
2856 PyObject* keyobj;
2857 DBT key, data;
2858 PyObject* txnobj = NULL;
2859 DB_TXN *txn = NULL;
2860
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002861 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002862 return NULL;
2863 CHECK_DB_NOT_CLOSED(self);
2864 if (!make_key_dbt(self, keyobj, &key, NULL))
2865 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002866 if (!checkTxnObj(txnobj, &txn)) {
2867 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002869 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002870
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002871 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 it has a record but can't allocate a buffer for the data. This saves
2873 having to deal with data we won't be using.
2874 */
2875 CLEAR_DBT(data);
2876 data.flags = DB_DBT_USERMEM;
2877
2878 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002879 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880 MYDB_END_ALLOW_THREADS;
2881 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002882
2883 if (err == DB_BUFFER_SMALL || err == 0) {
2884 return PyInt_FromLong(1);
2885 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2886 return PyInt_FromLong(0);
2887 }
2888
2889 makeDBError(err);
2890 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002891}
2892
2893
2894#define _KEYS_LIST 1
2895#define _VALUES_LIST 2
2896#define _ITEMS_LIST 3
2897
2898static PyObject*
2899_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2900{
2901 int err, dbtype;
2902 DBT key;
2903 DBT data;
2904 DBC *cursor;
2905 PyObject* list;
2906 PyObject* item = NULL;
2907
2908 CHECK_DB_NOT_CLOSED(self);
2909 CLEAR_DBT(key);
2910 CLEAR_DBT(data);
2911
2912 dbtype = _DB_get_type(self);
2913 if (dbtype == -1)
2914 return NULL;
2915
2916 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002917 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002918 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919
2920 /* get a cursor */
2921 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002922 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002924 if (makeDBError(err)) {
2925 Py_DECREF(list);
2926 return NULL;
2927 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002928
2929 if (CHECK_DBFLAG(self, DB_THREAD)) {
2930 key.flags = DB_DBT_REALLOC;
2931 data.flags = DB_DBT_REALLOC;
2932 }
2933
2934 while (1) { /* use the cursor to traverse the DB, collecting items */
2935 MYDB_BEGIN_ALLOW_THREADS;
2936 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2937 MYDB_END_ALLOW_THREADS;
2938
2939 if (err) {
2940 /* for any error, break out of the loop */
2941 break;
2942 }
2943
2944 switch (type) {
2945 case _KEYS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002950 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002951 break;
2952 case DB_RECNO:
2953 case DB_QUEUE:
2954 item = PyInt_FromLong(*((db_recno_t*)key.data));
2955 break;
2956 }
2957 break;
2958
2959 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002960 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 break;
2962
2963 case _ITEMS_LIST:
2964 switch(dbtype) {
2965 case DB_BTREE:
2966 case DB_HASH:
2967 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002968 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2969 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002970 break;
2971 case DB_RECNO:
2972 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002973 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2974 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975 break;
2976 }
2977 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002978 default:
2979 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2980 item = NULL;
2981 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 }
2983 if (item == NULL) {
2984 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002985 list = NULL;
2986 goto done;
2987 }
2988 PyList_Append(list, item);
2989 Py_DECREF(item);
2990 }
2991
Gregory P. Smithe9477062005-06-04 06:46:59 +00002992 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2993 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002994 Py_DECREF(list);
2995 list = NULL;
2996 }
2997
2998 done:
2999 FREE_DBT(key);
3000 FREE_DBT(data);
3001 MYDB_BEGIN_ALLOW_THREADS;
3002 cursor->c_close(cursor);
3003 MYDB_END_ALLOW_THREADS;
3004 return list;
3005}
3006
3007
3008static PyObject*
3009DB_keys(DBObject* self, PyObject* args)
3010{
3011 PyObject* txnobj = NULL;
3012 DB_TXN *txn = NULL;
3013
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003014 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 return NULL;
3016 if (!checkTxnObj(txnobj, &txn))
3017 return NULL;
3018 return _DB_make_list(self, txn, _KEYS_LIST);
3019}
3020
3021
3022static PyObject*
3023DB_items(DBObject* self, PyObject* args)
3024{
3025 PyObject* txnobj = NULL;
3026 DB_TXN *txn = NULL;
3027
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003028 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003029 return NULL;
3030 if (!checkTxnObj(txnobj, &txn))
3031 return NULL;
3032 return _DB_make_list(self, txn, _ITEMS_LIST);
3033}
3034
3035
3036static PyObject*
3037DB_values(DBObject* self, PyObject* args)
3038{
3039 PyObject* txnobj = NULL;
3040 DB_TXN *txn = NULL;
3041
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003042 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003043 return NULL;
3044 if (!checkTxnObj(txnobj, &txn))
3045 return NULL;
3046 return _DB_make_list(self, txn, _VALUES_LIST);
3047}
3048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003049/* --------------------------------------------------------------------- */
3050/* DBCursor methods */
3051
3052
3053static PyObject*
3054DBC_close(DBCursorObject* self, PyObject* args)
3055{
3056 int err = 0;
3057
3058 if (!PyArg_ParseTuple(args, ":close"))
3059 return NULL;
3060
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003061 if (self->dbc != NULL) {
3062 MYDB_BEGIN_ALLOW_THREADS;
3063 err = self->dbc->c_close(self->dbc);
3064 self->dbc = NULL;
3065 MYDB_END_ALLOW_THREADS;
3066 }
3067 RETURN_IF_ERR();
3068 RETURN_NONE();
3069}
3070
3071
3072static PyObject*
3073DBC_count(DBCursorObject* self, PyObject* args)
3074{
3075 int err = 0;
3076 db_recno_t count;
3077 int flags = 0;
3078
3079 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3080 return NULL;
3081
3082 CHECK_CURSOR_NOT_CLOSED(self);
3083
3084 MYDB_BEGIN_ALLOW_THREADS;
3085 err = self->dbc->c_count(self->dbc, &count, flags);
3086 MYDB_END_ALLOW_THREADS;
3087 RETURN_IF_ERR();
3088
3089 return PyInt_FromLong(count);
3090}
3091
3092
3093static PyObject*
3094DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3095{
3096 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3097}
3098
3099
3100static PyObject*
3101DBC_delete(DBCursorObject* self, PyObject* args)
3102{
3103 int err, flags=0;
3104
3105 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3106 return NULL;
3107
3108 CHECK_CURSOR_NOT_CLOSED(self);
3109
3110 MYDB_BEGIN_ALLOW_THREADS;
3111 err = self->dbc->c_del(self->dbc, flags);
3112 MYDB_END_ALLOW_THREADS;
3113 RETURN_IF_ERR();
3114
3115 self->mydb->haveStat = 0;
3116 RETURN_NONE();
3117}
3118
3119
3120static PyObject*
3121DBC_dup(DBCursorObject* self, PyObject* args)
3122{
3123 int err, flags =0;
3124 DBC* dbc = NULL;
3125
3126 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3127 return NULL;
3128
3129 CHECK_CURSOR_NOT_CLOSED(self);
3130
3131 MYDB_BEGIN_ALLOW_THREADS;
3132 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3133 MYDB_END_ALLOW_THREADS;
3134 RETURN_IF_ERR();
3135
3136 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3137}
3138
3139static PyObject*
3140DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3141{
3142 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3143}
3144
3145
3146static PyObject*
3147DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3148{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003149 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003150 PyObject* keyobj = NULL;
3151 PyObject* dataobj = NULL;
3152 PyObject* retval = NULL;
3153 int dlen = -1;
3154 int doff = -1;
3155 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003156 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003157 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158
3159 CLEAR_DBT(key);
3160 CLEAR_DBT(data);
3161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003162 &flags, &dlen, &doff))
3163 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003164 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3166 &kwnames[1],
3167 &keyobj, &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, "OOi|ii:get",
3171 kwnames, &keyobj, &dataobj,
3172 &flags, &dlen, &doff))
3173 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 return NULL;
3175 }
3176 }
3177 }
3178
3179 CHECK_CURSOR_NOT_CLOSED(self);
3180
3181 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3182 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003183 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3184 (!add_partial_dbt(&data, dlen, doff)) )
3185 {
3186 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003187 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003188 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003189
3190 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3191 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003192 if (!(key.flags & DB_DBT_REALLOC)) {
3193 key.flags |= DB_DBT_MALLOC;
3194 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003195 }
3196
3197 MYDB_BEGIN_ALLOW_THREADS;
3198 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3199 MYDB_END_ALLOW_THREADS;
3200
Gregory P. Smithe9477062005-06-04 06:46:59 +00003201 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3202 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003203 Py_INCREF(Py_None);
3204 retval = Py_None;
3205 }
3206 else if (makeDBError(err)) {
3207 retval = NULL;
3208 }
3209 else {
3210 switch (_DB_get_type(self->mydb)) {
3211 case -1:
3212 retval = NULL;
3213 break;
3214 case DB_BTREE:
3215 case DB_HASH:
3216 default:
3217 retval = Py_BuildValue("s#s#", key.data, key.size,
3218 data.data, data.size);
3219 break;
3220 case DB_RECNO:
3221 case DB_QUEUE:
3222 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3223 data.data, data.size);
3224 break;
3225 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003226 FREE_DBT(data);
3227 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003228 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003229 return retval;
3230}
3231
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003232#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003233static PyObject*
3234DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3235{
3236 int err, flags=0;
3237 PyObject* keyobj = NULL;
3238 PyObject* dataobj = NULL;
3239 PyObject* retval = NULL;
3240 int dlen = -1;
3241 int doff = -1;
3242 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003243 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3244 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003245
3246 CLEAR_DBT(key);
3247 CLEAR_DBT(data);
3248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3249 &flags, &dlen, &doff))
3250 {
3251 PyErr_Clear();
3252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003253 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003254 &keyobj, &flags, &dlen, &doff))
3255 {
3256 PyErr_Clear();
3257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3258 kwnames, &keyobj, &dataobj,
3259 &flags, &dlen, &doff))
3260 {
3261 return NULL;
3262 }
3263 }
3264 }
3265
3266 CHECK_CURSOR_NOT_CLOSED(self);
3267
3268 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3269 return NULL;
3270 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3271 (!add_partial_dbt(&data, dlen, doff)) ) {
3272 FREE_DBT(key);
3273 return NULL;
3274 }
3275
3276 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3277 data.flags = DB_DBT_MALLOC;
3278 if (!(key.flags & DB_DBT_REALLOC)) {
3279 key.flags |= DB_DBT_MALLOC;
3280 }
3281 }
3282
3283 CLEAR_DBT(pkey);
3284 pkey.flags = DB_DBT_MALLOC;
3285
3286 MYDB_BEGIN_ALLOW_THREADS;
3287 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3288 MYDB_END_ALLOW_THREADS;
3289
Gregory P. Smithe9477062005-06-04 06:46:59 +00003290 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3291 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003292 Py_INCREF(Py_None);
3293 retval = Py_None;
3294 }
3295 else if (makeDBError(err)) {
3296 retval = NULL;
3297 }
3298 else {
3299 PyObject *pkeyObj;
3300 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003301 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302
3303 if (self->mydb->primaryDBType == DB_RECNO ||
3304 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003305 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003306 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003307 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003308
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003309 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003310 {
3311 PyObject *keyObj;
3312 int type = _DB_get_type(self->mydb);
3313 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003314 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003316 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003317#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003318 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003319#else
3320 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3321#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003322 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003323 FREE_DBT(key);
3324 }
3325 else /* return just the pkey and data */
3326 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003327#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003328 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003329#else
3330 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3331#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003332 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003333 Py_DECREF(dataObj);
3334 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003335 FREE_DBT(pkey);
3336 FREE_DBT(data);
3337 }
3338 /* the only time REALLOC should be set is if we used an integer
3339 * key that make_key_dbt malloc'd for us. always free these. */
3340 if (key.flags & DB_DBT_REALLOC) {
3341 FREE_DBT(key);
3342 }
3343 return retval;
3344}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003345#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003346
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003347
3348static PyObject*
3349DBC_get_recno(DBCursorObject* self, PyObject* args)
3350{
3351 int err;
3352 db_recno_t recno;
3353 DBT key;
3354 DBT data;
3355
3356 if (!PyArg_ParseTuple(args, ":get_recno"))
3357 return NULL;
3358
3359 CHECK_CURSOR_NOT_CLOSED(self);
3360
3361 CLEAR_DBT(key);
3362 CLEAR_DBT(data);
3363 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3364 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3365 data.flags = DB_DBT_MALLOC;
3366 key.flags = DB_DBT_MALLOC;
3367 }
3368
3369 MYDB_BEGIN_ALLOW_THREADS;
3370 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3371 MYDB_END_ALLOW_THREADS;
3372 RETURN_IF_ERR();
3373
3374 recno = *((db_recno_t*)data.data);
3375 FREE_DBT(key);
3376 FREE_DBT(data);
3377 return PyInt_FromLong(recno);
3378}
3379
3380
3381static PyObject*
3382DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3383{
3384 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3385}
3386
3387
3388static PyObject*
3389DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3390{
3391 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3392}
3393
3394
3395static PyObject*
3396DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3397{
3398 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3399}
3400
3401
3402static PyObject*
3403DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3404{
3405 int err, flags = 0;
3406 PyObject* keyobj, *dataobj;
3407 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003408 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003409 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410 int dlen = -1;
3411 int doff = -1;
3412
3413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3414 &keyobj, &dataobj, &flags, &dlen, &doff))
3415 return NULL;
3416
3417 CHECK_CURSOR_NOT_CLOSED(self);
3418
3419 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3420 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003421 if (!make_dbt(dataobj, &data) ||
3422 !add_partial_dbt(&data, dlen, doff) )
3423 {
3424 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003425 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003426 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427
3428 MYDB_BEGIN_ALLOW_THREADS;
3429 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3430 MYDB_END_ALLOW_THREADS;
3431 FREE_DBT(key);
3432 RETURN_IF_ERR();
3433 self->mydb->haveStat = 0;
3434 RETURN_NONE();
3435}
3436
3437
3438static PyObject*
3439DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3440{
3441 int err, flags = 0;
3442 DBT key, data;
3443 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003444 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 int dlen = -1;
3446 int doff = -1;
3447
3448 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3449 &keyobj, &flags, &dlen, &doff))
3450 return NULL;
3451
3452 CHECK_CURSOR_NOT_CLOSED(self);
3453
3454 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3455 return NULL;
3456
3457 CLEAR_DBT(data);
3458 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3459 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3460 data.flags = DB_DBT_MALLOC;
3461 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003462 if (!add_partial_dbt(&data, dlen, doff)) {
3463 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003465 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003466
3467 MYDB_BEGIN_ALLOW_THREADS;
3468 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3469 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003470 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3471 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003472 Py_INCREF(Py_None);
3473 retval = Py_None;
3474 }
3475 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003476 retval = NULL;
3477 }
3478 else {
3479 switch (_DB_get_type(self->mydb)) {
3480 case -1:
3481 retval = NULL;
3482 break;
3483 case DB_BTREE:
3484 case DB_HASH:
3485 default:
3486 retval = Py_BuildValue("s#s#", key.data, key.size,
3487 data.data, data.size);
3488 break;
3489 case DB_RECNO:
3490 case DB_QUEUE:
3491 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3492 data.data, data.size);
3493 break;
3494 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003495 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003496 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003497 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003498 /* the only time REALLOC should be set is if we used an integer
3499 * key that make_key_dbt malloc'd for us. always free these. */
3500 if (key.flags & DB_DBT_REALLOC) {
3501 FREE_DBT(key);
3502 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003503
3504 return retval;
3505}
3506
3507
3508static PyObject*
3509DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3510{
3511 int err, flags = 0;
3512 DBT key, data;
3513 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003514 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003515 int dlen = -1;
3516 int doff = -1;
3517
3518 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3519 &keyobj, &flags, &dlen, &doff))
3520 return NULL;
3521
3522 CHECK_CURSOR_NOT_CLOSED(self);
3523
3524 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3525 return NULL;
3526
3527 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003528 if (!add_partial_dbt(&data, dlen, doff)) {
3529 FREE_DBT(key);
3530 return NULL;
3531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003532 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3533 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003534 data.flags |= DB_DBT_MALLOC;
3535 /* only BTREE databases will return anything in the key */
3536 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3537 key.flags |= DB_DBT_MALLOC;
3538 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003539 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 MYDB_BEGIN_ALLOW_THREADS;
3541 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3542 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003543 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3544 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003545 Py_INCREF(Py_None);
3546 retval = Py_None;
3547 }
3548 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549 retval = NULL;
3550 }
3551 else {
3552 switch (_DB_get_type(self->mydb)) {
3553 case -1:
3554 retval = NULL;
3555 break;
3556 case DB_BTREE:
3557 case DB_HASH:
3558 default:
3559 retval = Py_BuildValue("s#s#", key.data, key.size,
3560 data.data, data.size);
3561 break;
3562 case DB_RECNO:
3563 case DB_QUEUE:
3564 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3565 data.data, data.size);
3566 break;
3567 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003568 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569 FREE_DBT(data);
3570 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003571 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003572 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003573 if (key.flags & DB_DBT_REALLOC) {
3574 FREE_DBT(key);
3575 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576
3577 return retval;
3578}
3579
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003581_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3582 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003584 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003586 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587
Gregory P. Smith7441e652003-11-03 21:35:31 +00003588 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3590 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003591 if (!make_dbt(dataobj, &data)) {
3592 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003593 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003594 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595
3596 MYDB_BEGIN_ALLOW_THREADS;
3597 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3598 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003599 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003600 Py_INCREF(Py_None);
3601 retval = Py_None;
3602 }
3603 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604 retval = NULL;
3605 }
3606 else {
3607 switch (_DB_get_type(self->mydb)) {
3608 case -1:
3609 retval = NULL;
3610 break;
3611 case DB_BTREE:
3612 case DB_HASH:
3613 default:
3614 retval = Py_BuildValue("s#s#", key.data, key.size,
3615 data.data, data.size);
3616 break;
3617 case DB_RECNO:
3618 case DB_QUEUE:
3619 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3620 data.data, data.size);
3621 break;
3622 }
3623 }
3624
3625 FREE_DBT(key);
3626 return retval;
3627}
3628
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003629static PyObject*
3630DBC_get_both(DBCursorObject* self, PyObject* args)
3631{
3632 int flags=0;
3633 PyObject *keyobj, *dataobj;
3634
3635 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3636 return NULL;
3637
Gregory P. Smith7441e652003-11-03 21:35:31 +00003638 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003639 CHECK_CURSOR_NOT_CLOSED(self);
3640
3641 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3642 self->mydb->moduleFlags.getReturnsNone);
3643}
3644
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003645/* Return size of entry */
3646static PyObject*
3647DBC_get_current_size(DBCursorObject* self, PyObject* args)
3648{
3649 int err, flags=DB_CURRENT;
3650 PyObject* retval = NULL;
3651 DBT key, data;
3652
3653 if (!PyArg_ParseTuple(args, ":get_current_size"))
3654 return NULL;
3655 CHECK_CURSOR_NOT_CLOSED(self);
3656 CLEAR_DBT(key);
3657 CLEAR_DBT(data);
3658
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003659 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003660 getting the record size. */
3661 data.flags = DB_DBT_USERMEM;
3662 data.ulen = 0;
3663 MYDB_BEGIN_ALLOW_THREADS;
3664 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3665 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003666 if (err == DB_BUFFER_SMALL || !err) {
3667 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003668 retval = PyInt_FromLong((long)data.size);
3669 err = 0;
3670 }
3671
3672 FREE_DBT(key);
3673 FREE_DBT(data);
3674 RETURN_IF_ERR();
3675 return retval;
3676}
3677
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003678static PyObject*
3679DBC_set_both(DBCursorObject* self, PyObject* args)
3680{
3681 int flags=0;
3682 PyObject *keyobj, *dataobj;
3683
3684 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3685 return NULL;
3686
Gregory P. Smith7441e652003-11-03 21:35:31 +00003687 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 CHECK_CURSOR_NOT_CLOSED(self);
3689
3690 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3691 self->mydb->moduleFlags.cursorSetReturnsNone);
3692}
3693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694
3695static PyObject*
3696DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3697{
3698 int err, irecno, flags=0;
3699 db_recno_t recno;
3700 DBT key, data;
3701 PyObject* retval;
3702 int dlen = -1;
3703 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003704 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003705
3706 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3707 &irecno, &flags, &dlen, &doff))
3708 return NULL;
3709
3710 CHECK_CURSOR_NOT_CLOSED(self);
3711
3712 CLEAR_DBT(key);
3713 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003714 /* use allocated space so DB will be able to realloc room for the real
3715 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 key.data = malloc(sizeof(db_recno_t));
3717 if (key.data == NULL) {
3718 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3719 return NULL;
3720 }
3721 key.size = sizeof(db_recno_t);
3722 key.ulen = key.size;
3723 memcpy(key.data, &recno, sizeof(db_recno_t));
3724 key.flags = DB_DBT_REALLOC;
3725
3726 CLEAR_DBT(data);
3727 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3728 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3729 data.flags = DB_DBT_MALLOC;
3730 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003731 if (!add_partial_dbt(&data, dlen, doff)) {
3732 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003733 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003734 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003735
3736 MYDB_BEGIN_ALLOW_THREADS;
3737 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3738 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003739 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3740 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003741 Py_INCREF(Py_None);
3742 retval = Py_None;
3743 }
3744 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745 retval = NULL;
3746 }
3747 else { /* Can only be used for BTrees, so no need to return int key */
3748 retval = Py_BuildValue("s#s#", key.data, key.size,
3749 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 FREE_DBT(data);
3751 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003752 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003753
3754 return retval;
3755}
3756
3757
3758static PyObject*
3759DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3760{
3761 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3762}
3763
3764
3765static PyObject*
3766DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3767{
3768 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3769}
3770
3771
3772static PyObject*
3773DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3774{
3775 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3776}
3777
3778
3779static PyObject*
3780DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3781{
3782 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3783}
3784
3785
3786static PyObject*
3787DBC_join_item(DBCursorObject* self, PyObject* args)
3788{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003789 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790 DBT key, data;
3791 PyObject* retval;
3792
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794 return NULL;
3795
3796 CHECK_CURSOR_NOT_CLOSED(self);
3797
3798 CLEAR_DBT(key);
3799 CLEAR_DBT(data);
3800 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3801 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3802 key.flags = DB_DBT_MALLOC;
3803 }
3804
3805 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003806 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003807 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003808 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3809 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003810 Py_INCREF(Py_None);
3811 retval = Py_None;
3812 }
3813 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003814 retval = NULL;
3815 }
3816 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003817 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 FREE_DBT(key);
3819 }
3820
3821 return retval;
3822}
3823
3824
3825
3826/* --------------------------------------------------------------------- */
3827/* DBEnv methods */
3828
3829
3830static PyObject*
3831DBEnv_close(DBEnvObject* self, PyObject* args)
3832{
3833 int err, flags = 0;
3834
3835 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3836 return NULL;
3837 if (!self->closed) { /* Don't close more than once */
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->close(self->db_env, flags);
3840 MYDB_END_ALLOW_THREADS;
3841 /* after calling DBEnv->close, regardless of error, this DBEnv
3842 * may not be accessed again (BerkeleyDB docs). */
3843 self->closed = 1;
3844 self->db_env = NULL;
3845 RETURN_IF_ERR();
3846 }
3847 RETURN_NONE();
3848}
3849
3850
3851static PyObject*
3852DBEnv_open(DBEnvObject* self, PyObject* args)
3853{
3854 int err, flags=0, mode=0660;
3855 char *db_home;
3856
3857 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3858 return NULL;
3859
3860 CHECK_ENV_NOT_CLOSED(self);
3861
3862 MYDB_BEGIN_ALLOW_THREADS;
3863 err = self->db_env->open(self->db_env, db_home, flags, mode);
3864 MYDB_END_ALLOW_THREADS;
3865 RETURN_IF_ERR();
3866 self->closed = 0;
3867 self->flags = flags;
3868 RETURN_NONE();
3869}
3870
3871
3872static PyObject*
3873DBEnv_remove(DBEnvObject* self, PyObject* args)
3874{
3875 int err, flags=0;
3876 char *db_home;
3877
3878 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3879 return NULL;
3880 CHECK_ENV_NOT_CLOSED(self);
3881 MYDB_BEGIN_ALLOW_THREADS;
3882 err = self->db_env->remove(self->db_env, db_home, flags);
3883 MYDB_END_ALLOW_THREADS;
3884 RETURN_IF_ERR();
3885 RETURN_NONE();
3886}
3887
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003888#if (DBVER >= 41)
3889static PyObject*
3890DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3891{
3892 int err;
3893 u_int32_t flags=0;
3894 char *file = NULL;
3895 char *database = NULL;
3896 PyObject *txnobj = NULL;
3897 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003898 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003899 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003900
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003902 &file, &database, &txnobj, &flags)) {
3903 return NULL;
3904 }
3905 if (!checkTxnObj(txnobj, &txn)) {
3906 return NULL;
3907 }
3908 CHECK_ENV_NOT_CLOSED(self);
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3914}
3915
3916static PyObject*
3917DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3918{
3919 int err;
3920 u_int32_t flags=0;
3921 char *file = NULL;
3922 char *database = NULL;
3923 char *newname = NULL;
3924 PyObject *txnobj = NULL;
3925 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003926 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003927 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003928
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003930 &file, &database, &newname, &txnobj, &flags)) {
3931 return NULL;
3932 }
3933 if (!checkTxnObj(txnobj, &txn)) {
3934 return NULL;
3935 }
3936 CHECK_ENV_NOT_CLOSED(self);
3937 MYDB_BEGIN_ALLOW_THREADS;
3938 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3939 flags);
3940 MYDB_END_ALLOW_THREADS;
3941 RETURN_IF_ERR();
3942 RETURN_NONE();
3943}
3944
3945static PyObject*
3946DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3947{
3948 int err;
3949 u_int32_t flags=0;
3950 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003951 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003952
3953 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3954 &passwd, &flags)) {
3955 return NULL;
3956 }
3957
3958 MYDB_BEGIN_ALLOW_THREADS;
3959 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3960 MYDB_END_ALLOW_THREADS;
3961
3962 RETURN_IF_ERR();
3963 RETURN_NONE();
3964}
3965#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003966
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003967#if (DBVER >= 40)
3968static PyObject*
3969DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3970{
3971 int err;
3972 u_int32_t flags=0;
3973 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003974 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003975
3976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3977 &timeout, &flags)) {
3978 return NULL;
3979 }
3980
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3983 MYDB_END_ALLOW_THREADS;
3984
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988#endif /* DBVER >= 40 */
3989
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003990static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003991DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3992{
3993 int err;
3994 long shm_key = 0;
3995
3996 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
3999
4000 err = self->db_env->set_shm_key(self->db_env, shm_key);
4001 RETURN_IF_ERR();
4002 RETURN_NONE();
4003}
4004
4005static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004006DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4007{
4008 int err, gbytes=0, bytes=0, ncache=0;
4009
4010 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4011 &gbytes, &bytes, &ncache))
4012 return NULL;
4013 CHECK_ENV_NOT_CLOSED(self);
4014
4015 MYDB_BEGIN_ALLOW_THREADS;
4016 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4017 MYDB_END_ALLOW_THREADS;
4018 RETURN_IF_ERR();
4019 RETURN_NONE();
4020}
4021
4022
4023#if (DBVER >= 32)
4024static PyObject*
4025DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4026{
4027 int err, flags=0, onoff=0;
4028
4029 if (!PyArg_ParseTuple(args, "ii:set_flags",
4030 &flags, &onoff))
4031 return NULL;
4032 CHECK_ENV_NOT_CLOSED(self);
4033
4034 MYDB_BEGIN_ALLOW_THREADS;
4035 err = self->db_env->set_flags(self->db_env, flags, onoff);
4036 MYDB_END_ALLOW_THREADS;
4037 RETURN_IF_ERR();
4038 RETURN_NONE();
4039}
4040#endif
4041
4042
4043static PyObject*
4044DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4045{
4046 int err;
4047 char *dir;
4048
4049 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4050 return NULL;
4051 CHECK_ENV_NOT_CLOSED(self);
4052
4053 MYDB_BEGIN_ALLOW_THREADS;
4054 err = self->db_env->set_data_dir(self->db_env, dir);
4055 MYDB_END_ALLOW_THREADS;
4056 RETURN_IF_ERR();
4057 RETURN_NONE();
4058}
4059
4060
4061static PyObject*
4062DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4063{
4064 int err, lg_bsize;
4065
4066 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4069
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4075}
4076
4077
4078static PyObject*
4079DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4080{
4081 int err;
4082 char *dir;
4083
4084 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_dir(self->db_env, dir);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095static PyObject*
4096DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4097{
4098 int err, lg_max;
4099
4100 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4103
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_lg_max(self->db_env, lg_max);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4109}
4110
4111
Neal Norwitz84562352005-10-20 04:30:15 +00004112#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004113static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004114DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4115{
4116 int err, lg_max;
4117
4118 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4121
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4127}
Neal Norwitz84562352005-10-20 04:30:15 +00004128#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004129
4130
4131static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004132DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4133{
4134 int err, lk_detect;
4135
4136 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4137 return NULL;
4138 CHECK_ENV_NOT_CLOSED(self);
4139
4140 MYDB_BEGIN_ALLOW_THREADS;
4141 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4142 MYDB_END_ALLOW_THREADS;
4143 RETURN_IF_ERR();
4144 RETURN_NONE();
4145}
4146
4147
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004148#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004149static PyObject*
4150DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4151{
4152 int err, max;
4153
4154 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4157
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_lk_max(self->db_env, max);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4163}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004164#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004165
4166
4167#if (DBVER >= 32)
4168
4169static PyObject*
4170DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4171{
4172 int err, max;
4173
4174 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
4178 MYDB_BEGIN_ALLOW_THREADS;
4179 err = self->db_env->set_lk_max_locks(self->db_env, max);
4180 MYDB_END_ALLOW_THREADS;
4181 RETURN_IF_ERR();
4182 RETURN_NONE();
4183}
4184
4185
4186static PyObject*
4187DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4188{
4189 int err, max;
4190
4191 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4194
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
4201
4202
4203static PyObject*
4204DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4205{
4206 int err, max;
4207
4208 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4209 return NULL;
4210 CHECK_ENV_NOT_CLOSED(self);
4211
4212 MYDB_BEGIN_ALLOW_THREADS;
4213 err = self->db_env->set_lk_max_objects(self->db_env, max);
4214 MYDB_END_ALLOW_THREADS;
4215 RETURN_IF_ERR();
4216 RETURN_NONE();
4217}
4218
4219#endif
4220
4221
4222static PyObject*
4223DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4224{
4225 int err, mp_mmapsize;
4226
4227 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4230
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 RETURN_NONE();
4236}
4237
4238
4239static PyObject*
4240DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4241{
4242 int err;
4243 char *dir;
4244
4245 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4246 return NULL;
4247 CHECK_ENV_NOT_CLOSED(self);
4248
4249 MYDB_BEGIN_ALLOW_THREADS;
4250 err = self->db_env->set_tmp_dir(self->db_env, dir);
4251 MYDB_END_ALLOW_THREADS;
4252 RETURN_IF_ERR();
4253 RETURN_NONE();
4254}
4255
4256
4257static PyObject*
4258DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4259{
4260 int flags = 0;
4261 PyObject* txnobj = NULL;
4262 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004263 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004264
4265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4266 &txnobj, &flags))
4267 return NULL;
4268
4269 if (!checkTxnObj(txnobj, &txn))
4270 return NULL;
4271 CHECK_ENV_NOT_CLOSED(self);
4272
4273 return (PyObject*)newDBTxnObject(self, txn, flags);
4274}
4275
4276
4277static PyObject*
4278DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4279{
4280 int err, kbyte=0, min=0, flags=0;
4281
4282 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4283 return NULL;
4284 CHECK_ENV_NOT_CLOSED(self);
4285
4286 MYDB_BEGIN_ALLOW_THREADS;
4287#if (DBVER >= 40)
4288 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4289#else
4290 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4291#endif
4292 MYDB_END_ALLOW_THREADS;
4293 RETURN_IF_ERR();
4294 RETURN_NONE();
4295}
4296
4297
4298static PyObject*
4299DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4300{
4301 int err, max;
4302
4303 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4304 return NULL;
4305 CHECK_ENV_NOT_CLOSED(self);
4306
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004307 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004308 RETURN_IF_ERR();
4309 RETURN_NONE();
4310}
4311
4312
4313static PyObject*
4314DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4315{
4316 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004317 long stamp;
4318 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004319
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004320 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004321 return NULL;
4322 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004323 timestamp = (time_t)stamp;
4324 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004325 RETURN_IF_ERR();
4326 RETURN_NONE();
4327}
4328
4329
4330static PyObject*
4331DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4332{
4333 int err, atype, flags=0;
4334 int aborted = 0;
4335
4336 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4337 return NULL;
4338 CHECK_ENV_NOT_CLOSED(self);
4339
4340 MYDB_BEGIN_ALLOW_THREADS;
4341#if (DBVER >= 40)
4342 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4343#else
4344 err = lock_detect(self->db_env, flags, atype, &aborted);
4345#endif
4346 MYDB_END_ALLOW_THREADS;
4347 RETURN_IF_ERR();
4348 return PyInt_FromLong(aborted);
4349}
4350
4351
4352static PyObject*
4353DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4354{
4355 int flags=0;
4356 int locker, lock_mode;
4357 DBT obj;
4358 PyObject* objobj;
4359
4360 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4361 return NULL;
4362
4363
4364 if (!make_dbt(objobj, &obj))
4365 return NULL;
4366
4367 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4368}
4369
4370
4371static PyObject*
4372DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4373{
4374 int err;
4375 u_int32_t theID;
4376
4377 if (!PyArg_ParseTuple(args, ":lock_id"))
4378 return NULL;
4379
4380 CHECK_ENV_NOT_CLOSED(self);
4381 MYDB_BEGIN_ALLOW_THREADS;
4382#if (DBVER >= 40)
4383 err = self->db_env->lock_id(self->db_env, &theID);
4384#else
4385 err = lock_id(self->db_env, &theID);
4386#endif
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4389
4390 return PyInt_FromLong((long)theID);
4391}
4392
4393
4394static PyObject*
4395DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4396{
4397 int err;
4398 DBLockObject* dblockobj;
4399
4400 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4401 return NULL;
4402
4403 CHECK_ENV_NOT_CLOSED(self);
4404 MYDB_BEGIN_ALLOW_THREADS;
4405#if (DBVER >= 40)
4406 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4407#else
4408 err = lock_put(self->db_env, &dblockobj->lock);
4409#endif
4410 MYDB_END_ALLOW_THREADS;
4411 RETURN_IF_ERR();
4412 RETURN_NONE();
4413}
4414
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004415#if (DBVER >= 44)
4416static PyObject*
4417DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4418{
4419 int err;
4420 char *file;
4421 u_int32_t flags = 0;
4422 static char* kwnames[] = { "file", "flags", NULL};
4423
4424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4425 &file, &flags))
4426 return NULL;
4427 CHECK_ENV_NOT_CLOSED(self);
4428
4429 MYDB_BEGIN_ALLOW_THREADS;
4430 err = self->db_env->lsn_reset(self->db_env, file, flags);
4431 MYDB_END_ALLOW_THREADS;
4432 RETURN_IF_ERR();
4433 RETURN_NONE();
4434}
4435#endif /* DBVER >= 4.4 */
4436
4437#if (DBVER >= 40)
4438static PyObject*
4439DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4440{
4441 int err;
4442 DB_LOG_STAT* statp = NULL;
4443 PyObject* d = NULL;
4444 u_int32_t flags = 0;
4445
4446 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4447 return NULL;
4448 CHECK_ENV_NOT_CLOSED(self);
4449
4450 MYDB_BEGIN_ALLOW_THREADS;
4451 err = self->db_env->log_stat(self->db_env, &statp, flags);
4452 MYDB_END_ALLOW_THREADS;
4453 RETURN_IF_ERR();
4454
4455 /* Turn the stat structure into a dictionary */
4456 d = PyDict_New();
4457 if (d == NULL) {
4458 if (statp)
4459 free(statp);
4460 return NULL;
4461 }
4462
4463#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4464
4465 MAKE_ENTRY(magic);
4466 MAKE_ENTRY(version);
4467 MAKE_ENTRY(mode);
4468 MAKE_ENTRY(lg_bsize);
4469#if (DBVER >= 44)
4470 MAKE_ENTRY(lg_size);
4471 MAKE_ENTRY(record);
4472#endif
4473#if (DBVER <= 40)
4474 MAKE_ENTRY(lg_max);
4475#endif
4476 MAKE_ENTRY(w_mbytes);
4477 MAKE_ENTRY(w_bytes);
4478 MAKE_ENTRY(wc_mbytes);
4479 MAKE_ENTRY(wc_bytes);
4480 MAKE_ENTRY(wcount);
4481 MAKE_ENTRY(wcount_fill);
4482#if (DBVER >= 44)
4483 MAKE_ENTRY(rcount);
4484#endif
4485 MAKE_ENTRY(scount);
4486 MAKE_ENTRY(cur_file);
4487 MAKE_ENTRY(cur_offset);
4488 MAKE_ENTRY(disk_file);
4489 MAKE_ENTRY(disk_offset);
4490 MAKE_ENTRY(maxcommitperflush);
4491 MAKE_ENTRY(mincommitperflush);
4492 MAKE_ENTRY(regsize);
4493 MAKE_ENTRY(region_wait);
4494 MAKE_ENTRY(region_nowait);
4495
4496#undef MAKE_ENTRY
4497 free(statp);
4498 return d;
4499} /* DBEnv_log_stat */
4500#endif /* DBVER >= 4.0 for log_stat method */
4501
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502
4503static PyObject*
4504DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4505{
4506 int err;
4507 DB_LOCK_STAT* sp;
4508 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004509 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510
4511 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4512 return NULL;
4513 CHECK_ENV_NOT_CLOSED(self);
4514
4515 MYDB_BEGIN_ALLOW_THREADS;
4516#if (DBVER >= 40)
4517 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4518#else
4519#if (DBVER >= 33)
4520 err = lock_stat(self->db_env, &sp);
4521#else
4522 err = lock_stat(self->db_env, &sp, NULL);
4523#endif
4524#endif
4525 MYDB_END_ALLOW_THREADS;
4526 RETURN_IF_ERR();
4527
4528 /* Turn the stat structure into a dictionary */
4529 d = PyDict_New();
4530 if (d == NULL) {
4531 free(sp);
4532 return NULL;
4533 }
4534
4535#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4536
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004537#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004539#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540 MAKE_ENTRY(nmodes);
4541#if (DBVER >= 32)
4542 MAKE_ENTRY(maxlocks);
4543 MAKE_ENTRY(maxlockers);
4544 MAKE_ENTRY(maxobjects);
4545 MAKE_ENTRY(nlocks);
4546 MAKE_ENTRY(maxnlocks);
4547#endif
4548 MAKE_ENTRY(nlockers);
4549 MAKE_ENTRY(maxnlockers);
4550#if (DBVER >= 32)
4551 MAKE_ENTRY(nobjects);
4552 MAKE_ENTRY(maxnobjects);
4553#endif
4554 MAKE_ENTRY(nrequests);
4555 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004556#if (DBVER < 44)
4557 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004558 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004559#else
4560 MAKE_ENTRY(lock_nowait);
4561 MAKE_ENTRY(lock_wait);
4562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 MAKE_ENTRY(ndeadlocks);
4564 MAKE_ENTRY(regsize);
4565 MAKE_ENTRY(region_wait);
4566 MAKE_ENTRY(region_nowait);
4567
4568#undef MAKE_ENTRY
4569 free(sp);
4570 return d;
4571}
4572
4573
4574static PyObject*
4575DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4576{
4577 int flags=0;
4578 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004579 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004580 PyObject* list;
4581 PyObject* item = NULL;
4582
4583 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4584 return NULL;
4585
4586 CHECK_ENV_NOT_CLOSED(self);
4587 MYDB_BEGIN_ALLOW_THREADS;
4588#if (DBVER >= 40)
4589 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4590#elif (DBVER == 33)
4591 err = log_archive(self->db_env, &log_list, flags);
4592#else
4593 err = log_archive(self->db_env, &log_list, flags, NULL);
4594#endif
4595 MYDB_END_ALLOW_THREADS;
4596 RETURN_IF_ERR();
4597
4598 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004599 if (list == NULL) {
4600 if (log_list)
4601 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004602 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004603 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004604
4605 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004606 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004608 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004609 if (item == NULL) {
4610 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004611 list = NULL;
4612 break;
4613 }
4614 PyList_Append(list, item);
4615 Py_DECREF(item);
4616 }
4617 free(log_list_start);
4618 }
4619 return list;
4620}
4621
4622
4623static PyObject*
4624DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4625{
4626 int err;
4627 DB_TXN_STAT* sp;
4628 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004629 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630
4631 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4632 return NULL;
4633 CHECK_ENV_NOT_CLOSED(self);
4634
4635 MYDB_BEGIN_ALLOW_THREADS;
4636#if (DBVER >= 40)
4637 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4638#elif (DBVER == 33)
4639 err = txn_stat(self->db_env, &sp);
4640#else
4641 err = txn_stat(self->db_env, &sp, NULL);
4642#endif
4643 MYDB_END_ALLOW_THREADS;
4644 RETURN_IF_ERR();
4645
4646 /* Turn the stat structure into a dictionary */
4647 d = PyDict_New();
4648 if (d == NULL) {
4649 free(sp);
4650 return NULL;
4651 }
4652
4653#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004654#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004655
Guido van Rossumd8faa362007-04-27 19:54:29 +00004656 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004657 MAKE_ENTRY(last_txnid);
4658 MAKE_ENTRY(maxtxns);
4659 MAKE_ENTRY(nactive);
4660 MAKE_ENTRY(maxnactive);
4661 MAKE_ENTRY(nbegins);
4662 MAKE_ENTRY(naborts);
4663 MAKE_ENTRY(ncommits);
4664 MAKE_ENTRY(regsize);
4665 MAKE_ENTRY(region_wait);
4666 MAKE_ENTRY(region_nowait);
4667
4668#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004669#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004670 free(sp);
4671 return d;
4672}
4673
4674
4675static PyObject*
4676DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4677{
4678 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004679 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680
4681 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4682 return NULL;
4683 CHECK_ENV_NOT_CLOSED(self);
4684
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004685 if (self->moduleFlags.getReturnsNone)
4686 ++oldValue;
4687 if (self->moduleFlags.cursorSetReturnsNone)
4688 ++oldValue;
4689 self->moduleFlags.getReturnsNone = (flags >= 1);
4690 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691 return PyInt_FromLong(oldValue);
4692}
4693
4694
4695/* --------------------------------------------------------------------- */
4696/* DBTxn methods */
4697
4698
4699static PyObject*
4700DBTxn_commit(DBTxnObject* self, PyObject* args)
4701{
4702 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004703 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004704
4705 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4706 return NULL;
4707
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004708 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004709 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4710 "after txn_commit or txn_abort");
4711 PyErr_SetObject(DBError, t);
4712 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004713 return NULL;
4714 }
4715 txn = self->txn;
4716 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004717 MYDB_BEGIN_ALLOW_THREADS;
4718#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004719 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004720#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004721 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004722#endif
4723 MYDB_END_ALLOW_THREADS;
4724 RETURN_IF_ERR();
4725 RETURN_NONE();
4726}
4727
4728static PyObject*
4729DBTxn_prepare(DBTxnObject* self, PyObject* args)
4730{
4731#if (DBVER >= 33)
4732 int err;
4733 char* gid=NULL;
4734 int gid_size=0;
4735
4736 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4737 return NULL;
4738
4739 if (gid_size != DB_XIDDATASIZE) {
4740 PyErr_SetString(PyExc_TypeError,
4741 "gid must be DB_XIDDATASIZE bytes long");
4742 return NULL;
4743 }
4744
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004745 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004746 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4747 "after txn_commit or txn_abort");
4748 PyErr_SetObject(DBError, t);
4749 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004750 return NULL;
4751 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004752 MYDB_BEGIN_ALLOW_THREADS;
4753#if (DBVER >= 40)
4754 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4755#else
4756 err = txn_prepare(self->txn, (u_int8_t*)gid);
4757#endif
4758 MYDB_END_ALLOW_THREADS;
4759 RETURN_IF_ERR();
4760 RETURN_NONE();
4761#else
4762 int err;
4763
4764 if (!PyArg_ParseTuple(args, ":prepare"))
4765 return NULL;
4766
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004767 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004768 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4769 "after txn_commit or txn_abort");
4770 PyErr_SetObject(DBError, t);
4771 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004772 return NULL;
4773 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004774 MYDB_BEGIN_ALLOW_THREADS;
4775 err = txn_prepare(self->txn);
4776 MYDB_END_ALLOW_THREADS;
4777 RETURN_IF_ERR();
4778 RETURN_NONE();
4779#endif
4780}
4781
4782
4783static PyObject*
4784DBTxn_abort(DBTxnObject* self, PyObject* args)
4785{
4786 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004787 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004788
4789 if (!PyArg_ParseTuple(args, ":abort"))
4790 return NULL;
4791
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004792 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004793 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4794 "after txn_commit or txn_abort");
4795 PyErr_SetObject(DBError, t);
4796 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004797 return NULL;
4798 }
4799 txn = self->txn;
4800 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004801 MYDB_BEGIN_ALLOW_THREADS;
4802#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004803 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004804#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004805 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004806#endif
4807 MYDB_END_ALLOW_THREADS;
4808 RETURN_IF_ERR();
4809 RETURN_NONE();
4810}
4811
4812
4813static PyObject*
4814DBTxn_id(DBTxnObject* self, PyObject* args)
4815{
4816 int id;
4817
4818 if (!PyArg_ParseTuple(args, ":id"))
4819 return NULL;
4820
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004821 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004822 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4823 "after txn_commit or txn_abort");
4824 PyErr_SetObject(DBError, t);
4825 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004826 return NULL;
4827 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004828 MYDB_BEGIN_ALLOW_THREADS;
4829#if (DBVER >= 40)
4830 id = self->txn->id(self->txn);
4831#else
4832 id = txn_id(self->txn);
4833#endif
4834 MYDB_END_ALLOW_THREADS;
4835 return PyInt_FromLong(id);
4836}
4837
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004838#if (DBVER >= 43)
4839/* --------------------------------------------------------------------- */
4840/* DBSequence methods */
4841
4842
4843static PyObject*
4844DBSequence_close(DBSequenceObject* self, PyObject* args)
4845{
4846 int err, flags=0;
4847 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4848 return NULL;
4849 CHECK_SEQUENCE_NOT_CLOSED(self)
4850
4851 MYDB_BEGIN_ALLOW_THREADS
4852 err = self->sequence->close(self->sequence, flags);
4853 self->sequence = NULL;
4854 MYDB_END_ALLOW_THREADS
4855
4856 RETURN_IF_ERR();
4857
4858 RETURN_NONE();
4859}
4860
4861static PyObject*
4862DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4863{
4864 int err, flags = 0;
4865 int delta = 1;
4866 db_seq_t value;
4867 PyObject *txnobj = NULL;
4868 DB_TXN *txn = NULL;
4869 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4870 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4871 return NULL;
4872 CHECK_SEQUENCE_NOT_CLOSED(self)
4873
4874 if (!checkTxnObj(txnobj, &txn))
4875 return NULL;
4876
4877 MYDB_BEGIN_ALLOW_THREADS
4878 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4879 MYDB_END_ALLOW_THREADS
4880
4881 RETURN_IF_ERR();
4882 return PyLong_FromLongLong(value);
4883
4884}
4885
4886static PyObject*
4887DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4888{
4889 if (!PyArg_ParseTuple(args,":get_dbp"))
4890 return NULL;
4891 CHECK_SEQUENCE_NOT_CLOSED(self)
4892 Py_INCREF(self->mydb);
4893 return (PyObject* )self->mydb;
4894}
4895
4896static PyObject*
4897DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4898{
4899 int err;
4900 DBT key;
4901 CHECK_SEQUENCE_NOT_CLOSED(self)
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->sequence->get_key(self->sequence, &key);
4904 MYDB_END_ALLOW_THREADS
4905
4906 RETURN_IF_ERR();
4907
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004908 return PyBytes_FromStringAndSize(key.data, key.size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004909}
4910
4911static PyObject*
4912DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4913{
4914 int err;
4915 db_seq_t value;
4916 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4917 return NULL;
4918 CHECK_SEQUENCE_NOT_CLOSED(self)
4919
4920 MYDB_BEGIN_ALLOW_THREADS
4921 err = self->sequence->initial_value(self->sequence, value);
4922 MYDB_END_ALLOW_THREADS
4923
4924 RETURN_IF_ERR();
4925
4926 RETURN_NONE();
4927}
4928
4929static PyObject*
4930DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4931{
4932 int err, flags = 0;
4933 PyObject* keyobj;
4934 PyObject *txnobj = NULL;
4935 DB_TXN *txn = NULL;
4936 DBT key;
4937
4938 static char* kwnames[] = {"key", "txn", "flags", NULL };
4939 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4940 return NULL;
4941
4942 if (!checkTxnObj(txnobj, &txn))
4943 return NULL;
4944
4945 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4946 return NULL;
4947
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err = self->sequence->open(self->sequence, txn, &key, flags);
4950 MYDB_END_ALLOW_THREADS
4951
4952 CLEAR_DBT(key);
4953 RETURN_IF_ERR();
4954
4955 RETURN_NONE();
4956}
4957
4958static PyObject*
4959DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4960{
4961 int err, flags = 0;
4962 PyObject *txnobj = NULL;
4963 DB_TXN *txn = NULL;
4964
4965 static char* kwnames[] = {"txn", "flags", NULL };
4966 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4967 return NULL;
4968
4969 if (!checkTxnObj(txnobj, &txn))
4970 return NULL;
4971
4972 CHECK_SEQUENCE_NOT_CLOSED(self)
4973
4974 MYDB_BEGIN_ALLOW_THREADS
4975 err = self->sequence->remove(self->sequence, txn, flags);
4976 MYDB_END_ALLOW_THREADS
4977
4978 RETURN_IF_ERR();
4979 RETURN_NONE();
4980}
4981
4982static PyObject*
4983DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4984{
4985 int err, size;
4986 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4987 return NULL;
4988 CHECK_SEQUENCE_NOT_CLOSED(self)
4989
4990 MYDB_BEGIN_ALLOW_THREADS
4991 err = self->sequence->set_cachesize(self->sequence, size);
4992 MYDB_END_ALLOW_THREADS
4993
4994 RETURN_IF_ERR();
4995 RETURN_NONE();
4996}
4997
4998static PyObject*
4999DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5000{
5001 int err, size;
5002 if (!PyArg_ParseTuple(args,":get_cachesize"))
5003 return NULL;
5004 CHECK_SEQUENCE_NOT_CLOSED(self)
5005
5006 MYDB_BEGIN_ALLOW_THREADS
5007 err = self->sequence->get_cachesize(self->sequence, &size);
5008 MYDB_END_ALLOW_THREADS
5009
5010 RETURN_IF_ERR();
5011 return PyInt_FromLong(size);
5012}
5013
5014static PyObject*
5015DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5016{
5017 int err, flags = 0;
5018 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5019 return NULL;
5020 CHECK_SEQUENCE_NOT_CLOSED(self)
5021
5022 MYDB_BEGIN_ALLOW_THREADS
5023 err = self->sequence->set_flags(self->sequence, flags);
5024 MYDB_END_ALLOW_THREADS
5025
5026 RETURN_IF_ERR();
5027 RETURN_NONE();
5028
5029}
5030
5031static PyObject*
5032DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5033{
5034 unsigned int flags;
5035 int err;
5036 if (!PyArg_ParseTuple(args,":get_flags"))
5037 return NULL;
5038 CHECK_SEQUENCE_NOT_CLOSED(self)
5039
5040 MYDB_BEGIN_ALLOW_THREADS
5041 err = self->sequence->get_flags(self->sequence, &flags);
5042 MYDB_END_ALLOW_THREADS
5043
5044 RETURN_IF_ERR();
5045 return PyInt_FromLong((int)flags);
5046}
5047
5048static PyObject*
5049DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5050{
5051 int err;
5052 db_seq_t min, max;
5053 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5054 return NULL;
5055 CHECK_SEQUENCE_NOT_CLOSED(self)
5056
5057 MYDB_BEGIN_ALLOW_THREADS
5058 err = self->sequence->set_range(self->sequence, min, max);
5059 MYDB_END_ALLOW_THREADS
5060
5061 RETURN_IF_ERR();
5062 RETURN_NONE();
5063}
5064
5065static PyObject*
5066DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5067{
5068 int err;
5069 db_seq_t min, max;
5070 if (!PyArg_ParseTuple(args,":get_range"))
5071 return NULL;
5072 CHECK_SEQUENCE_NOT_CLOSED(self)
5073
5074 MYDB_BEGIN_ALLOW_THREADS
5075 err = self->sequence->get_range(self->sequence, &min, &max);
5076 MYDB_END_ALLOW_THREADS
5077
5078 RETURN_IF_ERR();
5079 return Py_BuildValue("(LL)", min, max);
5080}
5081
5082static PyObject*
5083DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5084{
5085 int err, flags = 0;
5086 DB_SEQUENCE_STAT* sp = NULL;
5087 PyObject* dict_stat;
5088 static char* kwnames[] = {"flags", NULL };
5089 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5090 return NULL;
5091 CHECK_SEQUENCE_NOT_CLOSED(self);
5092
5093 MYDB_BEGIN_ALLOW_THREADS;
5094 err = self->sequence->stat(self->sequence, &sp, flags);
5095 MYDB_END_ALLOW_THREADS;
5096 RETURN_IF_ERR();
5097
5098 if ((dict_stat = PyDict_New()) == NULL) {
5099 free(sp);
5100 return NULL;
5101 }
5102
5103
5104#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5105#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5106
5107 MAKE_INT_ENTRY(wait);
5108 MAKE_INT_ENTRY(nowait);
5109 MAKE_LONG_LONG_ENTRY(current);
5110 MAKE_LONG_LONG_ENTRY(value);
5111 MAKE_LONG_LONG_ENTRY(last_value);
5112 MAKE_LONG_LONG_ENTRY(min);
5113 MAKE_LONG_LONG_ENTRY(max);
5114 MAKE_INT_ENTRY(cache_size);
5115 MAKE_INT_ENTRY(flags);
5116
5117#undef MAKE_INT_ENTRY
5118#undef MAKE_LONG_LONG_ENTRY
5119
5120 free(sp);
5121 return dict_stat;
5122}
5123#endif
5124
5125
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126/* --------------------------------------------------------------------- */
5127/* Method definition tables and type objects */
5128
5129static PyMethodDef DB_methods[] = {
5130 {"append", (PyCFunction)DB_append, METH_VARARGS},
5131#if (DBVER >= 33)
5132 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5133#endif
5134 {"close", (PyCFunction)DB_close, METH_VARARGS},
5135#if (DBVER >= 32)
5136 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5137 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5138#endif
5139 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5140 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5141 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5142 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005143#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005144 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005145#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005146 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5147 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5148 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5149 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5150 {"join", (PyCFunction)DB_join, METH_VARARGS},
5151 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5152 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5153 {"items", (PyCFunction)DB_items, METH_VARARGS},
5154 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5155 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5156 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5157 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5158 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5159 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005160#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005161 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005162#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005163 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005164#if (DBVER >= 41)
5165 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5166#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005167 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5168 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5169 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5170 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5171 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5172 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5173 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5174 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5175 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5176#if (DBVER >= 32)
5177 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5178#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005179 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005180 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5181#if (DBVER >= 33)
5182 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5183#endif
5184 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5185 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5186 {"values", (PyCFunction)DB_values, METH_VARARGS},
5187 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5188 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5189 {NULL, NULL} /* sentinel */
5190};
5191
5192
5193static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005194 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005195 (binaryfunc)DB_subscript, /*mp_subscript*/
5196 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5197};
5198
5199
5200static PyMethodDef DBCursor_methods[] = {
5201 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5202 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5203 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5204 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5205 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5206 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5207 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005208#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005209 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005210#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005211 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5212 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5213 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5214 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5215 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5216 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5217 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5218 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005219 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005220 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005221 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5222 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5223 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5224 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5225 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5226 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5227 {NULL, NULL} /* sentinel */
5228};
5229
5230
5231static PyMethodDef DBEnv_methods[] = {
5232 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5233 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5234 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005235#if (DBVER >= 41)
5236 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5237 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5238 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5239#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005240#if (DBVER >= 40)
5241 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5242#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005243 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005244 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5245 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5246#if (DBVER >= 32)
5247 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5248#endif
5249 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5250 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5251 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005252#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005253 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005254#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005255 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005256#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005257 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259#if (DBVER >= 32)
5260 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5261 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5262 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5263#endif
5264 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5265 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5266 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5267 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5268 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5269 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005270 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005271 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5272 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5273 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5274 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5275 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5276 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005277#if (DBVER >= 40)
5278 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5279#endif
5280#if (DBVER >= 44)
5281 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5282#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005283 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5284 {NULL, NULL} /* sentinel */
5285};
5286
5287
5288static PyMethodDef DBTxn_methods[] = {
5289 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5290 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5291 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5292 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5293 {NULL, NULL} /* sentinel */
5294};
5295
5296
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005297#if (DBVER >= 43)
5298static PyMethodDef DBSequence_methods[] = {
5299 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5300 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5301 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5302 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5303 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5304 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5305 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5306 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5307 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5308 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5309 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5310 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5311 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5312 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5313 {NULL, NULL} /* sentinel */
5314};
5315#endif
5316
5317
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005318static PyObject*
5319DB_getattr(DBObject* self, char *name)
5320{
5321 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5322}
5323
5324
5325static PyObject*
5326DBEnv_getattr(DBEnvObject* self, char *name)
5327{
5328 if (!strcmp(name, "db_home")) {
5329 CHECK_ENV_NOT_CLOSED(self);
5330 if (self->db_env->db_home == NULL) {
5331 RETURN_NONE();
5332 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005333 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005334 }
5335
5336 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5337}
5338
5339
5340static PyObject*
5341DBCursor_getattr(DBCursorObject* self, char *name)
5342{
5343 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5344}
5345
5346static PyObject*
5347DBTxn_getattr(DBTxnObject* self, char *name)
5348{
5349 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5350}
5351
5352static PyObject*
5353DBLock_getattr(DBLockObject* self, char *name)
5354{
5355 return NULL;
5356}
5357
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005358#if (DBVER >= 43)
5359static PyObject*
5360DBSequence_getattr(DBSequenceObject* self, char *name)
5361{
5362 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5363}
5364#endif
5365
Neal Norwitz227b5332006-03-22 09:28:35 +00005366static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005367 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005368 "DB", /*tp_name*/
5369 sizeof(DBObject), /*tp_basicsize*/
5370 0, /*tp_itemsize*/
5371 /* methods */
5372 (destructor)DB_dealloc, /*tp_dealloc*/
5373 0, /*tp_print*/
5374 (getattrfunc)DB_getattr, /*tp_getattr*/
5375 0, /*tp_setattr*/
5376 0, /*tp_compare*/
5377 0, /*tp_repr*/
5378 0, /*tp_as_number*/
5379 0, /*tp_as_sequence*/
5380 &DB_mapping,/*tp_as_mapping*/
5381 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005382#ifdef HAVE_WEAKREF
5383 0, /* tp_call */
5384 0, /* tp_str */
5385 0, /* tp_getattro */
5386 0, /* tp_setattro */
5387 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005388 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005389 0, /* tp_doc */
5390 0, /* tp_traverse */
5391 0, /* tp_clear */
5392 0, /* tp_richcompare */
5393 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5394#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005395};
5396
5397
Neal Norwitz227b5332006-03-22 09:28:35 +00005398static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005399 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005400 "DBCursor", /*tp_name*/
5401 sizeof(DBCursorObject), /*tp_basicsize*/
5402 0, /*tp_itemsize*/
5403 /* methods */
5404 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5405 0, /*tp_print*/
5406 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5407 0, /*tp_setattr*/
5408 0, /*tp_compare*/
5409 0, /*tp_repr*/
5410 0, /*tp_as_number*/
5411 0, /*tp_as_sequence*/
5412 0, /*tp_as_mapping*/
5413 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005414#ifdef HAVE_WEAKREF
5415 0, /* tp_call */
5416 0, /* tp_str */
5417 0, /* tp_getattro */
5418 0, /* tp_setattro */
5419 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005420 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005421 0, /* tp_doc */
5422 0, /* tp_traverse */
5423 0, /* tp_clear */
5424 0, /* tp_richcompare */
5425 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5426#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005427};
5428
5429
Neal Norwitz227b5332006-03-22 09:28:35 +00005430static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005431 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005432 "DBEnv", /*tp_name*/
5433 sizeof(DBEnvObject), /*tp_basicsize*/
5434 0, /*tp_itemsize*/
5435 /* methods */
5436 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5437 0, /*tp_print*/
5438 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5439 0, /*tp_setattr*/
5440 0, /*tp_compare*/
5441 0, /*tp_repr*/
5442 0, /*tp_as_number*/
5443 0, /*tp_as_sequence*/
5444 0, /*tp_as_mapping*/
5445 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005446#ifdef HAVE_WEAKREF
5447 0, /* tp_call */
5448 0, /* tp_str */
5449 0, /* tp_getattro */
5450 0, /* tp_setattro */
5451 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005452 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005453 0, /* tp_doc */
5454 0, /* tp_traverse */
5455 0, /* tp_clear */
5456 0, /* tp_richcompare */
5457 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5458#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005459};
5460
Neal Norwitz227b5332006-03-22 09:28:35 +00005461static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005462 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005463 "DBTxn", /*tp_name*/
5464 sizeof(DBTxnObject), /*tp_basicsize*/
5465 0, /*tp_itemsize*/
5466 /* methods */
5467 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5468 0, /*tp_print*/
5469 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5470 0, /*tp_setattr*/
5471 0, /*tp_compare*/
5472 0, /*tp_repr*/
5473 0, /*tp_as_number*/
5474 0, /*tp_as_sequence*/
5475 0, /*tp_as_mapping*/
5476 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005477#ifdef HAVE_WEAKREF
5478 0, /* tp_call */
5479 0, /* tp_str */
5480 0, /* tp_getattro */
5481 0, /* tp_setattro */
5482 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005483 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005484 0, /* tp_doc */
5485 0, /* tp_traverse */
5486 0, /* tp_clear */
5487 0, /* tp_richcompare */
5488 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5489#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005490};
5491
5492
Neal Norwitz227b5332006-03-22 09:28:35 +00005493static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005494 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005495 "DBLock", /*tp_name*/
5496 sizeof(DBLockObject), /*tp_basicsize*/
5497 0, /*tp_itemsize*/
5498 /* methods */
5499 (destructor)DBLock_dealloc, /*tp_dealloc*/
5500 0, /*tp_print*/
5501 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5502 0, /*tp_setattr*/
5503 0, /*tp_compare*/
5504 0, /*tp_repr*/
5505 0, /*tp_as_number*/
5506 0, /*tp_as_sequence*/
5507 0, /*tp_as_mapping*/
5508 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005509#ifdef HAVE_WEAKREF
5510 0, /* tp_call */
5511 0, /* tp_str */
5512 0, /* tp_getattro */
5513 0, /* tp_setattro */
5514 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005515 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005516 0, /* tp_doc */
5517 0, /* tp_traverse */
5518 0, /* tp_clear */
5519 0, /* tp_richcompare */
5520 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5521#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005522};
5523
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005524#if (DBVER >= 43)
5525static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005526 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005527 "DBSequence", /*tp_name*/
5528 sizeof(DBSequenceObject), /*tp_basicsize*/
5529 0, /*tp_itemsize*/
5530 /* methods */
5531 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5532 0, /*tp_print*/
5533 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5534 0, /*tp_setattr*/
5535 0, /*tp_compare*/
5536 0, /*tp_repr*/
5537 0, /*tp_as_number*/
5538 0, /*tp_as_sequence*/
5539 0, /*tp_as_mapping*/
5540 0, /*tp_hash*/
5541#ifdef HAVE_WEAKREF
5542 0, /* tp_call */
5543 0, /* tp_str */
5544 0, /* tp_getattro */
5545 0, /* tp_setattro */
5546 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005547 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005548 0, /* tp_doc */
5549 0, /* tp_traverse */
5550 0, /* tp_clear */
5551 0, /* tp_richcompare */
5552 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5553#endif
5554};
5555#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005556
5557/* --------------------------------------------------------------------- */
5558/* Module-level functions */
5559
5560static PyObject*
5561DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5562{
5563 PyObject* dbenvobj = NULL;
5564 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005565 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005566
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5568 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005569 return NULL;
5570 if (dbenvobj == Py_None)
5571 dbenvobj = NULL;
5572 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5573 makeTypeError("DBEnv", dbenvobj);
5574 return NULL;
5575 }
5576
5577 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5578}
5579
5580
5581static PyObject*
5582DBEnv_construct(PyObject* self, PyObject* args)
5583{
5584 int flags = 0;
5585 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5586 return (PyObject* )newDBEnvObject(flags);
5587}
5588
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005589#if (DBVER >= 43)
5590static PyObject*
5591DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5592{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005593 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005594 int flags = 0;
5595 static char* kwnames[] = { "db", "flags", NULL};
5596
5597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5598 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005599 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005600 makeTypeError("DB", dbobj);
5601 return NULL;
5602 }
5603 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5604}
5605#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005606
5607static char bsddb_version_doc[] =
5608"Returns a tuple of major, minor, and patch release numbers of the\n\
5609underlying DB library.";
5610
5611static PyObject*
5612bsddb_version(PyObject* self, PyObject* args)
5613{
5614 int major, minor, patch;
5615
5616 if (!PyArg_ParseTuple(args, ":version"))
5617 return NULL;
5618 db_version(&major, &minor, &patch);
5619 return Py_BuildValue("(iii)", major, minor, patch);
5620}
5621
5622
5623/* List of functions defined in the module */
5624
5625static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005626 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5627 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5628#if (DBVER >= 43)
5629 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5630#endif
5631 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005632 {NULL, NULL} /* sentinel */
5633};
5634
5635
5636/* --------------------------------------------------------------------- */
5637/* Module initialization */
5638
5639
5640/* Convenience routine to export an integer value.
5641 * Errors are silently ignored, for better or for worse...
5642 */
5643#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5644
Gregory P. Smith41631e82003-09-21 00:08:14 +00005645#define MODULE_NAME_MAX_LEN 11
5646static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647
Neal Norwitzf6657e62006-12-28 04:47:50 +00005648PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649{
5650 PyObject* m;
5651 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005652 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5653 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5654 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005655
5656 /* Initialize the type of the new type objects here; doing it here
5657 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005658 Py_Type(&DB_Type) = &PyType_Type;
5659 Py_Type(&DBCursor_Type) = &PyType_Type;
5660 Py_Type(&DBEnv_Type) = &PyType_Type;
5661 Py_Type(&DBTxn_Type) = &PyType_Type;
5662 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005663#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005664 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005665#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005666
5667
Mark Hammonda69d4092003-04-22 23:13:27 +00005668#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005669 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005670 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005671#endif
5672
5673 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005674 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005675 if (m == NULL)
5676 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005677
5678 /* Add some symbolic constants to the module */
5679 d = PyModule_GetDict(m);
5680 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005681 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5683 Py_DECREF(pybsddb_version_s);
5684 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005685 Py_DECREF(svnid_s);
5686 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005687 Py_DECREF(db_version_s);
5688 db_version_s = NULL;
5689
5690 ADD_INT(d, DB_VERSION_MAJOR);
5691 ADD_INT(d, DB_VERSION_MINOR);
5692 ADD_INT(d, DB_VERSION_PATCH);
5693
5694 ADD_INT(d, DB_MAX_PAGES);
5695 ADD_INT(d, DB_MAX_RECORDS);
5696
Gregory P. Smith41631e82003-09-21 00:08:14 +00005697#if (DBVER >= 42)
5698 ADD_INT(d, DB_RPCCLIENT);
5699#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005700 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005701 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5702 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5703#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005704 ADD_INT(d, DB_XA_CREATE);
5705
5706 ADD_INT(d, DB_CREATE);
5707 ADD_INT(d, DB_NOMMAP);
5708 ADD_INT(d, DB_THREAD);
5709
5710 ADD_INT(d, DB_FORCE);
5711 ADD_INT(d, DB_INIT_CDB);
5712 ADD_INT(d, DB_INIT_LOCK);
5713 ADD_INT(d, DB_INIT_LOG);
5714 ADD_INT(d, DB_INIT_MPOOL);
5715 ADD_INT(d, DB_INIT_TXN);
5716#if (DBVER >= 32)
5717 ADD_INT(d, DB_JOINENV);
5718#endif
5719
5720 ADD_INT(d, DB_RECOVER);
5721 ADD_INT(d, DB_RECOVER_FATAL);
5722 ADD_INT(d, DB_TXN_NOSYNC);
5723 ADD_INT(d, DB_USE_ENVIRON);
5724 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5725
5726 ADD_INT(d, DB_LOCKDOWN);
5727 ADD_INT(d, DB_PRIVATE);
5728 ADD_INT(d, DB_SYSTEM_MEM);
5729
5730 ADD_INT(d, DB_TXN_SYNC);
5731 ADD_INT(d, DB_TXN_NOWAIT);
5732
5733 ADD_INT(d, DB_EXCL);
5734 ADD_INT(d, DB_FCNTL_LOCKING);
5735 ADD_INT(d, DB_ODDFILESIZE);
5736 ADD_INT(d, DB_RDWRMASTER);
5737 ADD_INT(d, DB_RDONLY);
5738 ADD_INT(d, DB_TRUNCATE);
5739#if (DBVER >= 32)
5740 ADD_INT(d, DB_EXTENT);
5741 ADD_INT(d, DB_CDB_ALLDB);
5742 ADD_INT(d, DB_VERIFY);
5743#endif
5744 ADD_INT(d, DB_UPGRADE);
5745
5746 ADD_INT(d, DB_AGGRESSIVE);
5747 ADD_INT(d, DB_NOORDERCHK);
5748 ADD_INT(d, DB_ORDERCHKONLY);
5749 ADD_INT(d, DB_PR_PAGE);
5750#if ! (DBVER >= 33)
5751 ADD_INT(d, DB_VRFY_FLAGMASK);
5752 ADD_INT(d, DB_PR_HEADERS);
5753#endif
5754 ADD_INT(d, DB_PR_RECOVERYTEST);
5755 ADD_INT(d, DB_SALVAGE);
5756
5757 ADD_INT(d, DB_LOCK_NORUN);
5758 ADD_INT(d, DB_LOCK_DEFAULT);
5759 ADD_INT(d, DB_LOCK_OLDEST);
5760 ADD_INT(d, DB_LOCK_RANDOM);
5761 ADD_INT(d, DB_LOCK_YOUNGEST);
5762#if (DBVER >= 33)
5763 ADD_INT(d, DB_LOCK_MAXLOCKS);
5764 ADD_INT(d, DB_LOCK_MINLOCKS);
5765 ADD_INT(d, DB_LOCK_MINWRITE);
5766#endif
5767
5768
5769#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005770 /* docs say to use zero instead */
5771 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005772#else
5773 ADD_INT(d, DB_LOCK_CONFLICT);
5774#endif
5775
5776 ADD_INT(d, DB_LOCK_DUMP);
5777 ADD_INT(d, DB_LOCK_GET);
5778 ADD_INT(d, DB_LOCK_INHERIT);
5779 ADD_INT(d, DB_LOCK_PUT);
5780 ADD_INT(d, DB_LOCK_PUT_ALL);
5781 ADD_INT(d, DB_LOCK_PUT_OBJ);
5782
5783 ADD_INT(d, DB_LOCK_NG);
5784 ADD_INT(d, DB_LOCK_READ);
5785 ADD_INT(d, DB_LOCK_WRITE);
5786 ADD_INT(d, DB_LOCK_NOWAIT);
5787#if (DBVER >= 32)
5788 ADD_INT(d, DB_LOCK_WAIT);
5789#endif
5790 ADD_INT(d, DB_LOCK_IWRITE);
5791 ADD_INT(d, DB_LOCK_IREAD);
5792 ADD_INT(d, DB_LOCK_IWR);
5793#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005794#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005795 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005796#else
5797 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799 ADD_INT(d, DB_LOCK_WWRITE);
5800#endif
5801
5802 ADD_INT(d, DB_LOCK_RECORD);
5803 ADD_INT(d, DB_LOCK_UPGRADE);
5804#if (DBVER >= 32)
5805 ADD_INT(d, DB_LOCK_SWITCH);
5806#endif
5807#if (DBVER >= 33)
5808 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5809#endif
5810
5811 ADD_INT(d, DB_LOCK_NOWAIT);
5812 ADD_INT(d, DB_LOCK_RECORD);
5813 ADD_INT(d, DB_LOCK_UPGRADE);
5814
5815#if (DBVER >= 33)
5816 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005817#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005818 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005819#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005820 ADD_INT(d, DB_LSTAT_FREE);
5821 ADD_INT(d, DB_LSTAT_HELD);
5822#if (DBVER == 33)
5823 ADD_INT(d, DB_LSTAT_NOGRANT);
5824#endif
5825 ADD_INT(d, DB_LSTAT_PENDING);
5826 ADD_INT(d, DB_LSTAT_WAITING);
5827#endif
5828
5829 ADD_INT(d, DB_ARCH_ABS);
5830 ADD_INT(d, DB_ARCH_DATA);
5831 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005832#if (DBVER >= 42)
5833 ADD_INT(d, DB_ARCH_REMOVE);
5834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005835
5836 ADD_INT(d, DB_BTREE);
5837 ADD_INT(d, DB_HASH);
5838 ADD_INT(d, DB_RECNO);
5839 ADD_INT(d, DB_QUEUE);
5840 ADD_INT(d, DB_UNKNOWN);
5841
5842 ADD_INT(d, DB_DUP);
5843 ADD_INT(d, DB_DUPSORT);
5844 ADD_INT(d, DB_RECNUM);
5845 ADD_INT(d, DB_RENUMBER);
5846 ADD_INT(d, DB_REVSPLITOFF);
5847 ADD_INT(d, DB_SNAPSHOT);
5848
5849 ADD_INT(d, DB_JOIN_NOSORT);
5850
5851 ADD_INT(d, DB_AFTER);
5852 ADD_INT(d, DB_APPEND);
5853 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005854#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005855 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005856#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005857#if (DBVER >= 41)
5858 _addIntToDict(d, "DB_CHECKPOINT", 0);
5859#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005860 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005861 ADD_INT(d, DB_CURLSN);
5862#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005863#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005864 ADD_INT(d, DB_COMMIT);
5865#endif
5866 ADD_INT(d, DB_CONSUME);
5867#if (DBVER >= 32)
5868 ADD_INT(d, DB_CONSUME_WAIT);
5869#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005870 ADD_INT(d, DB_CURRENT);
5871#if (DBVER >= 33)
5872 ADD_INT(d, DB_FAST_STAT);
5873#endif
5874 ADD_INT(d, DB_FIRST);
5875 ADD_INT(d, DB_FLUSH);
5876 ADD_INT(d, DB_GET_BOTH);
5877 ADD_INT(d, DB_GET_RECNO);
5878 ADD_INT(d, DB_JOIN_ITEM);
5879 ADD_INT(d, DB_KEYFIRST);
5880 ADD_INT(d, DB_KEYLAST);
5881 ADD_INT(d, DB_LAST);
5882 ADD_INT(d, DB_NEXT);
5883 ADD_INT(d, DB_NEXT_DUP);
5884 ADD_INT(d, DB_NEXT_NODUP);
5885 ADD_INT(d, DB_NODUPDATA);
5886 ADD_INT(d, DB_NOOVERWRITE);
5887 ADD_INT(d, DB_NOSYNC);
5888 ADD_INT(d, DB_POSITION);
5889 ADD_INT(d, DB_PREV);
5890 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005891#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005892 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005893#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005894 ADD_INT(d, DB_SET);
5895 ADD_INT(d, DB_SET_RANGE);
5896 ADD_INT(d, DB_SET_RECNO);
5897 ADD_INT(d, DB_WRITECURSOR);
5898
5899 ADD_INT(d, DB_OPFLAGS_MASK);
5900 ADD_INT(d, DB_RMW);
5901#if (DBVER >= 33)
5902 ADD_INT(d, DB_DIRTY_READ);
5903 ADD_INT(d, DB_MULTIPLE);
5904 ADD_INT(d, DB_MULTIPLE_KEY);
5905#endif
5906
Gregory P. Smith29602d22006-01-24 09:46:48 +00005907#if (DBVER >= 44)
5908 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5909 ADD_INT(d, DB_READ_COMMITTED);
5910#endif
5911
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005912#if (DBVER >= 33)
5913 ADD_INT(d, DB_DONOTINDEX);
5914#endif
5915
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005916#if (DBVER >= 41)
5917 _addIntToDict(d, "DB_INCOMPLETE", 0);
5918#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005919 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005920#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005921 ADD_INT(d, DB_KEYEMPTY);
5922 ADD_INT(d, DB_KEYEXIST);
5923 ADD_INT(d, DB_LOCK_DEADLOCK);
5924 ADD_INT(d, DB_LOCK_NOTGRANTED);
5925 ADD_INT(d, DB_NOSERVER);
5926 ADD_INT(d, DB_NOSERVER_HOME);
5927 ADD_INT(d, DB_NOSERVER_ID);
5928 ADD_INT(d, DB_NOTFOUND);
5929 ADD_INT(d, DB_OLD_VERSION);
5930 ADD_INT(d, DB_RUNRECOVERY);
5931 ADD_INT(d, DB_VERIFY_BAD);
5932#if (DBVER >= 33)
5933 ADD_INT(d, DB_PAGE_NOTFOUND);
5934 ADD_INT(d, DB_SECONDARY_BAD);
5935#endif
5936#if (DBVER >= 40)
5937 ADD_INT(d, DB_STAT_CLEAR);
5938 ADD_INT(d, DB_REGION_INIT);
5939 ADD_INT(d, DB_NOLOCKING);
5940 ADD_INT(d, DB_YIELDCPU);
5941 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5942 ADD_INT(d, DB_NOPANIC);
5943#endif
5944
Gregory P. Smith41631e82003-09-21 00:08:14 +00005945#if (DBVER >= 42)
5946 ADD_INT(d, DB_TIME_NOTGRANTED);
5947 ADD_INT(d, DB_TXN_NOT_DURABLE);
5948 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5949 ADD_INT(d, DB_LOG_AUTOREMOVE);
5950 ADD_INT(d, DB_DIRECT_LOG);
5951 ADD_INT(d, DB_DIRECT_DB);
5952 ADD_INT(d, DB_INIT_REP);
5953 ADD_INT(d, DB_ENCRYPT);
5954 ADD_INT(d, DB_CHKSUM);
5955#endif
5956
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005957#if (DBVER >= 43)
5958 ADD_INT(d, DB_LOG_INMEMORY);
5959 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005960 ADD_INT(d, DB_SEQ_DEC);
5961 ADD_INT(d, DB_SEQ_INC);
5962 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005963#endif
5964
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005965#if (DBVER >= 41)
5966 ADD_INT(d, DB_ENCRYPT_AES);
5967 ADD_INT(d, DB_AUTO_COMMIT);
5968#else
5969 /* allow berkeleydb 4.1 aware apps to run on older versions */
5970 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5971#endif
5972
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005973 ADD_INT(d, EINVAL);
5974 ADD_INT(d, EACCES);
5975 ADD_INT(d, ENOSPC);
5976 ADD_INT(d, ENOMEM);
5977 ADD_INT(d, EAGAIN);
5978 ADD_INT(d, EBUSY);
5979 ADD_INT(d, EEXIST);
5980 ADD_INT(d, ENOENT);
5981 ADD_INT(d, EPERM);
5982
Barry Warsaw1baa9822003-03-31 19:51:29 +00005983#if (DBVER >= 40)
5984 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5985 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5986#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005987
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005988 /* The exception name must be correct for pickled exception *
5989 * objects to unpickle properly. */
5990#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5991#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5992#else
5993#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5994#endif
5995
5996 /* All the rest of the exceptions derive only from DBError */
5997#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5998 PyDict_SetItemString(d, #name, name)
5999
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006001 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6002 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006003
Gregory P. Smithe9477062005-06-04 06:46:59 +00006004 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6005 * from both DBError and KeyError, since the API only supports
6006 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006008 {
6009 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6010 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6011 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006012 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6013 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 Py_file_input, d, d);
6015 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006016 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006017 PyDict_DelItemString(d, "KeyError");
6018
6019
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006020#if !INCOMPLETE_IS_WARNING
6021 MAKE_EX(DBIncompleteError);
6022#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006023 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006024 MAKE_EX(DBKeyEmptyError);
6025 MAKE_EX(DBKeyExistError);
6026 MAKE_EX(DBLockDeadlockError);
6027 MAKE_EX(DBLockNotGrantedError);
6028 MAKE_EX(DBOldVersionError);
6029 MAKE_EX(DBRunRecoveryError);
6030 MAKE_EX(DBVerifyBadError);
6031 MAKE_EX(DBNoServerError);
6032 MAKE_EX(DBNoServerHomeError);
6033 MAKE_EX(DBNoServerIDError);
6034#if (DBVER >= 33)
6035 MAKE_EX(DBPageNotFoundError);
6036 MAKE_EX(DBSecondaryBadError);
6037#endif
6038
6039 MAKE_EX(DBInvalidArgError);
6040 MAKE_EX(DBAccessError);
6041 MAKE_EX(DBNoSpaceError);
6042 MAKE_EX(DBNoMemoryError);
6043 MAKE_EX(DBAgainError);
6044 MAKE_EX(DBBusyError);
6045 MAKE_EX(DBFileExistsError);
6046 MAKE_EX(DBNoSuchFileError);
6047 MAKE_EX(DBPermissionsError);
6048
6049#undef MAKE_EX
6050
6051 /* Check for errors */
6052 if (PyErr_Occurred()) {
6053 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006054 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006055 }
6056}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006057
6058/* allow this module to be named _pybsddb so that it can be installed
6059 * and imported on top of python >= 2.3 that includes its own older
6060 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006061PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006062{
6063 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6064 init_bsddb();
6065}