blob: 149cd9869133a74ea5bfb4374be8b09cfed5ec47 [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
Skip Montanaro46fc3372007-08-12 11:44:53 +0000549 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000550#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 {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000862 PyErr_WarnEx(PyExc_RuntimeWarning,
863 "DB could not be closed in destructor:"
864 " DBEnv already closed",
865 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000866#endif
867 }
868 self->db = NULL;
869 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000870#ifdef HAVE_WEAKREF
871 if (self->in_weakreflist != NULL) {
872 PyObject_ClearWeakRefs((PyObject *) self);
873 }
874#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (self->myenvobj) {
876 Py_DECREF(self->myenvobj);
877 self->myenvobj = NULL;
878 }
879#if (DBVER >= 33)
880 if (self->associateCallback != NULL) {
881 Py_DECREF(self->associateCallback);
882 self->associateCallback = NULL;
883 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000884 if (self->btCompareCallback != NULL) {
885 Py_DECREF(self->btCompareCallback);
886 self->btCompareCallback = NULL;
887 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000890}
891
892
893static DBCursorObject*
894newDBCursorObject(DBC* dbc, DBObject* db)
895{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000896 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000897 if (self == NULL)
898 return NULL;
899
900 self->dbc = dbc;
901 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000902#ifdef HAVE_WEAKREF
903 self->in_weakreflist = NULL;
904#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905 Py_INCREF(self->mydb);
906 return self;
907}
908
909
910static void
911DBCursor_dealloc(DBCursorObject* self)
912{
913 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000914
915#ifdef HAVE_WEAKREF
916 if (self->in_weakreflist != NULL) {
917 PyObject_ClearWeakRefs((PyObject *) self);
918 }
919#endif
920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 if (self->dbc != NULL) {
922 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000923 /* If the underlying database has been closed, we don't
924 need to do anything. If the environment has been closed
925 we need to leak, as BerkeleyDB will crash trying to access
926 the environment. There was an exception when the
927 user closed the environment even though there still was
928 a database open. */
929 if (self->mydb->db && self->mydb->myenvobj &&
930 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000931 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 self->dbc = NULL;
933 MYDB_END_ALLOW_THREADS;
934 }
935 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000936 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937}
938
939
940static DBEnvObject*
941newDBEnvObject(int flags)
942{
943 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000944 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945 if (self == NULL)
946 return NULL;
947
948 self->closed = 1;
949 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000950 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
951 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000952#ifdef HAVE_WEAKREF
953 self->in_weakreflist = NULL;
954#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000955
956 MYDB_BEGIN_ALLOW_THREADS;
957 err = db_env_create(&self->db_env, flags);
958 MYDB_END_ALLOW_THREADS;
959 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000960 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000961 self = NULL;
962 }
963 else {
964 self->db_env->set_errcall(self->db_env, _db_errorCallback);
965 }
966 return self;
967}
968
969
970static void
971DBEnv_dealloc(DBEnvObject* self)
972{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000973#ifdef HAVE_WEAKREF
974 if (self->in_weakreflist != NULL) {
975 PyObject_ClearWeakRefs((PyObject *) self);
976 }
977#endif
978
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000979 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980 MYDB_BEGIN_ALLOW_THREADS;
981 self->db_env->close(self->db_env, 0);
982 MYDB_END_ALLOW_THREADS;
983 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000984 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985}
986
987
988static DBTxnObject*
989newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
990{
991 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000992 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000993 if (self == NULL)
994 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000995 Py_INCREF(myenv);
996 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000997#ifdef HAVE_WEAKREF
998 self->in_weakreflist = NULL;
999#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001000
1001 MYDB_BEGIN_ALLOW_THREADS;
1002#if (DBVER >= 40)
1003 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1004#else
1005 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1006#endif
1007 MYDB_END_ALLOW_THREADS;
1008 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001009 Py_DECREF(self->env);
1010 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011 self = NULL;
1012 }
1013 return self;
1014}
1015
1016
1017static void
1018DBTxn_dealloc(DBTxnObject* self)
1019{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001020#ifdef HAVE_WEAKREF
1021 if (self->in_weakreflist != NULL) {
1022 PyObject_ClearWeakRefs((PyObject *) self);
1023 }
1024#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025
Gregory P. Smith31c50652004-06-28 01:20:40 +00001026#ifdef HAVE_WARNINGS
1027 if (self->txn) {
1028 /* it hasn't been finalized, abort it! */
1029 MYDB_BEGIN_ALLOW_THREADS;
1030#if (DBVER >= 40)
1031 self->txn->abort(self->txn);
1032#else
1033 txn_abort(self->txn);
1034#endif
1035 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001036 PyErr_WarnEx(PyExc_RuntimeWarning,
1037 "DBTxn aborted in destructor. "
1038 " No prior commit() or abort().",
1039 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001040 }
1041#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001042
Neal Norwitz62a21122006-01-25 05:21:55 +00001043 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045}
1046
1047
1048static DBLockObject*
1049newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1050 db_lockmode_t lock_mode, int flags)
1051{
1052 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001053 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001054 if (self == NULL)
1055 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001056#ifdef HAVE_WEAKREF
1057 self->in_weakreflist = NULL;
1058#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001059
1060 MYDB_BEGIN_ALLOW_THREADS;
1061#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001062 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1063 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001064#else
1065 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1066#endif
1067 MYDB_END_ALLOW_THREADS;
1068 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001069 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001070 self = NULL;
1071 }
1072
1073 return self;
1074}
1075
1076
1077static void
1078DBLock_dealloc(DBLockObject* self)
1079{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001080#ifdef HAVE_WEAKREF
1081 if (self->in_weakreflist != NULL) {
1082 PyObject_ClearWeakRefs((PyObject *) self);
1083 }
1084#endif
1085 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001087 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001088}
1089
1090
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001091#if (DBVER >= 43)
1092static DBSequenceObject*
1093newDBSequenceObject(DBObject* mydb, int flags)
1094{
1095 int err;
1096 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1097 if (self == NULL)
1098 return NULL;
1099 Py_INCREF(mydb);
1100 self->mydb = mydb;
1101#ifdef HAVE_WEAKREF
1102 self->in_weakreflist = NULL;
1103#endif
1104
1105
1106 MYDB_BEGIN_ALLOW_THREADS;
1107 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1108 MYDB_END_ALLOW_THREADS;
1109 if (makeDBError(err)) {
1110 Py_DECREF(self->mydb);
1111 PyObject_Del(self);
1112 self = NULL;
1113 }
1114
1115 return self;
1116}
1117
1118
1119static void
1120DBSequence_dealloc(DBSequenceObject* self)
1121{
1122#ifdef HAVE_WEAKREF
1123 if (self->in_weakreflist != NULL) {
1124 PyObject_ClearWeakRefs((PyObject *) self);
1125 }
1126#endif
1127
1128 Py_DECREF(self->mydb);
1129 PyObject_Del(self);
1130}
1131#endif
1132
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133/* --------------------------------------------------------------------- */
1134/* DB methods */
1135
1136static PyObject*
1137DB_append(DBObject* self, PyObject* args)
1138{
1139 PyObject* txnobj = NULL;
1140 PyObject* dataobj;
1141 db_recno_t recno;
1142 DBT key, data;
1143 DB_TXN *txn = NULL;
1144
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001145 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146 return NULL;
1147
1148 CHECK_DB_NOT_CLOSED(self);
1149
1150 /* make a dummy key out of a recno */
1151 recno = 0;
1152 CLEAR_DBT(key);
1153 key.data = &recno;
1154 key.size = sizeof(recno);
1155 key.ulen = key.size;
1156 key.flags = DB_DBT_USERMEM;
1157
1158 if (!make_dbt(dataobj, &data)) return NULL;
1159 if (!checkTxnObj(txnobj, &txn)) return NULL;
1160
1161 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1162 return NULL;
1163
1164 return PyInt_FromLong(recno);
1165}
1166
1167
1168#if (DBVER >= 33)
1169
1170static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001171_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1172 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173{
1174 int retval = DB_DONOTINDEX;
1175 DBObject* secondaryDB = (DBObject*)db->app_private;
1176 PyObject* callback = secondaryDB->associateCallback;
1177 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001178 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001179 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001180
1181
1182 if (callback != NULL) {
1183 MYDB_BEGIN_BLOCK_THREADS;
1184
Thomas Woutersb3153832006-03-08 01:47:19 +00001185 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001186 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001187 priData->data, priData->size);
1188 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001189 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001190 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001191 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001192 result = PyEval_CallObject(callback, args);
1193 }
1194 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001195 PyErr_Print();
1196 }
1197 else if (result == Py_None) {
1198 retval = DB_DONOTINDEX;
1199 }
1200 else if (PyInt_Check(result)) {
1201 retval = PyInt_AsLong(result);
1202 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001203 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001204 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001205 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206
1207 CLEAR_DBT(*secKey);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001208 size = PyBytes_Size(result);
1209 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1211 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001212 if (secKey->data) {
1213 memcpy(secKey->data, data, size);
1214 secKey->size = size;
1215 retval = 0;
1216 }
1217 else {
1218 PyErr_SetString(PyExc_MemoryError,
1219 "malloc failed in _db_associateCallback");
1220 PyErr_Print();
1221 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001222 }
1223 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001224 PyErr_SetString(
1225 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001226 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227 PyErr_Print();
1228 }
1229
Thomas Woutersb3153832006-03-08 01:47:19 +00001230 Py_XDECREF(args);
1231 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001232
1233 MYDB_END_BLOCK_THREADS;
1234 }
1235 return retval;
1236}
1237
1238
1239static PyObject*
1240DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1241{
1242 int err, flags=0;
1243 DBObject* secondaryDB;
1244 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001245#if (DBVER >= 41)
1246 PyObject *txnobj = NULL;
1247 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001248 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001249 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001250#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001251 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001252#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001253
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001254#if (DBVER >= 41)
1255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1256 &secondaryDB, &callback, &flags,
1257 &txnobj)) {
1258#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001260 &secondaryDB, &callback, &flags)) {
1261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001262 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001263 }
1264
1265#if (DBVER >= 41)
1266 if (!checkTxnObj(txnobj, &txn)) return NULL;
1267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001268
1269 CHECK_DB_NOT_CLOSED(self);
1270 if (!DBObject_Check(secondaryDB)) {
1271 makeTypeError("DB", (PyObject*)secondaryDB);
1272 return NULL;
1273 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001274 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001275 if (callback == Py_None) {
1276 callback = NULL;
1277 }
1278 else if (!PyCallable_Check(callback)) {
1279 makeTypeError("Callable", callback);
1280 return NULL;
1281 }
1282
1283 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001284 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001285 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001286 secondaryDB->associateCallback = callback;
1287 secondaryDB->primaryDBType = _DB_get_type(self);
1288
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001289 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1290 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1291 * The global interepreter lock is not initialized until the first
1292 * thread is created using thread.start_new_thread() or fork() is
1293 * called. that would cause the ALLOW_THREADS here to segfault due
1294 * to a null pointer reference if no threads or child processes
1295 * have been created. This works around that and is a no-op if
1296 * threads have already been initialized.
1297 * (see pybsddb-users mailing list post on 2002-08-07)
1298 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001299#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001300 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001301#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001302 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001303#if (DBVER >= 41)
1304 err = self->db->associate(self->db,
1305 txn,
1306 secondaryDB->db,
1307 _db_associateCallback,
1308 flags);
1309#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310 err = self->db->associate(self->db,
1311 secondaryDB->db,
1312 _db_associateCallback,
1313 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001314#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 MYDB_END_ALLOW_THREADS;
1316
1317 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001318 Py_XDECREF(secondaryDB->associateCallback);
1319 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001320 secondaryDB->primaryDBType = 0;
1321 }
1322
1323 RETURN_IF_ERR();
1324 RETURN_NONE();
1325}
1326
1327
1328#endif
1329
1330
1331static PyObject*
1332DB_close(DBObject* self, PyObject* args)
1333{
1334 int err, flags=0;
1335 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1336 return NULL;
1337 if (self->db != NULL) {
1338 if (self->myenvobj)
1339 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341 self->db = NULL;
1342 RETURN_IF_ERR();
1343 }
1344 RETURN_NONE();
1345}
1346
1347
1348#if (DBVER >= 32)
1349static PyObject*
1350_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1351{
1352 int err, flags=0, type;
1353 PyObject* txnobj = NULL;
1354 PyObject* retval = NULL;
1355 DBT key, data;
1356 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001357 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001358
1359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1360 &txnobj, &flags))
1361 return NULL;
1362
1363 CHECK_DB_NOT_CLOSED(self);
1364 type = _DB_get_type(self);
1365 if (type == -1)
1366 return NULL;
1367 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001368 PyErr_SetString(PyExc_TypeError,
1369 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001370 return NULL;
1371 }
1372 if (!checkTxnObj(txnobj, &txn))
1373 return NULL;
1374
1375 CLEAR_DBT(key);
1376 CLEAR_DBT(data);
1377 if (CHECK_DBFLAG(self, DB_THREAD)) {
1378 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1379 data.flags = DB_DBT_MALLOC;
1380 key.flags = DB_DBT_MALLOC;
1381 }
1382
1383 MYDB_BEGIN_ALLOW_THREADS;
1384 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1385 MYDB_END_ALLOW_THREADS;
1386
Gregory P. Smithe9477062005-06-04 06:46:59 +00001387 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1388 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001389 err = 0;
1390 Py_INCREF(Py_None);
1391 retval = Py_None;
1392 }
1393 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001394 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001395 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396 FREE_DBT(key);
1397 FREE_DBT(data);
1398 }
1399
1400 RETURN_IF_ERR();
1401 return retval;
1402}
1403
1404static PyObject*
1405DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1406{
1407 return _DB_consume(self, args, kwargs, DB_CONSUME);
1408}
1409
1410static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001411DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1412 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001413{
1414 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1415}
1416#endif
1417
1418
1419
1420static PyObject*
1421DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1422{
1423 int err, flags=0;
1424 DBC* dbc;
1425 PyObject* txnobj = NULL;
1426 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001427 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428
1429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1430 &txnobj, &flags))
1431 return NULL;
1432 CHECK_DB_NOT_CLOSED(self);
1433 if (!checkTxnObj(txnobj, &txn))
1434 return NULL;
1435
1436 MYDB_BEGIN_ALLOW_THREADS;
1437 err = self->db->cursor(self->db, txn, &dbc, flags);
1438 MYDB_END_ALLOW_THREADS;
1439 RETURN_IF_ERR();
1440 return (PyObject*) newDBCursorObject(dbc, self);
1441}
1442
1443
1444static PyObject*
1445DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1446{
1447 PyObject* txnobj = NULL;
1448 int flags = 0;
1449 PyObject* keyobj;
1450 DBT key;
1451 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001452 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001453
1454 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1455 &keyobj, &txnobj, &flags))
1456 return NULL;
1457 CHECK_DB_NOT_CLOSED(self);
1458 if (!make_key_dbt(self, keyobj, &key, NULL))
1459 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001460 if (!checkTxnObj(txnobj, &txn)) {
1461 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001462 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001463 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001465 if (-1 == _DB_delete(self, txn, &key, 0)) {
1466 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001467 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001468 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001469
1470 FREE_DBT(key);
1471 RETURN_NONE();
1472}
1473
1474
1475static PyObject*
1476DB_fd(DBObject* self, PyObject* args)
1477{
1478 int err, the_fd;
1479
1480 if (!PyArg_ParseTuple(args,":fd"))
1481 return NULL;
1482 CHECK_DB_NOT_CLOSED(self);
1483
1484 MYDB_BEGIN_ALLOW_THREADS;
1485 err = self->db->fd(self->db, &the_fd);
1486 MYDB_END_ALLOW_THREADS;
1487 RETURN_IF_ERR();
1488 return PyInt_FromLong(the_fd);
1489}
1490
1491
1492static PyObject*
1493DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1494{
1495 int err, flags=0;
1496 PyObject* txnobj = NULL;
1497 PyObject* keyobj;
1498 PyObject* dfltobj = NULL;
1499 PyObject* retval = NULL;
1500 int dlen = -1;
1501 int doff = -1;
1502 DBT key, data;
1503 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001504 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001505 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001506
1507 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001508 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1509 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510 return NULL;
1511
1512 CHECK_DB_NOT_CLOSED(self);
1513 if (!make_key_dbt(self, keyobj, &key, &flags))
1514 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001515 if (!checkTxnObj(txnobj, &txn)) {
1516 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001518 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001519
1520 CLEAR_DBT(data);
1521 if (CHECK_DBFLAG(self, DB_THREAD)) {
1522 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1523 data.flags = DB_DBT_MALLOC;
1524 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001525 if (!add_partial_dbt(&data, dlen, doff)) {
1526 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001527 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001528 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529
1530 MYDB_BEGIN_ALLOW_THREADS;
1531 err = self->db->get(self->db, txn, &key, &data, flags);
1532 MYDB_END_ALLOW_THREADS;
1533
Gregory P. Smithe9477062005-06-04 06:46:59 +00001534 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001535 err = 0;
1536 Py_INCREF(dfltobj);
1537 retval = dfltobj;
1538 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001539 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1540 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001541 err = 0;
1542 Py_INCREF(Py_None);
1543 retval = Py_None;
1544 }
1545 else if (!err) {
1546 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001547 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001548 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001549 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001550 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001551 FREE_DBT(data);
1552 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001553 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554
1555 RETURN_IF_ERR();
1556 return retval;
1557}
1558
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001559#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001560static PyObject*
1561DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1562{
1563 int err, flags=0;
1564 PyObject* txnobj = NULL;
1565 PyObject* keyobj;
1566 PyObject* dfltobj = NULL;
1567 PyObject* retval = NULL;
1568 int dlen = -1;
1569 int doff = -1;
1570 DBT key, pkey, data;
1571 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001572 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001573 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001574
1575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1576 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1577 &doff))
1578 return NULL;
1579
1580 CHECK_DB_NOT_CLOSED(self);
1581 if (!make_key_dbt(self, keyobj, &key, &flags))
1582 return NULL;
1583 if (!checkTxnObj(txnobj, &txn)) {
1584 FREE_DBT(key);
1585 return NULL;
1586 }
1587
1588 CLEAR_DBT(data);
1589 if (CHECK_DBFLAG(self, DB_THREAD)) {
1590 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1591 data.flags = DB_DBT_MALLOC;
1592 }
1593 if (!add_partial_dbt(&data, dlen, doff)) {
1594 FREE_DBT(key);
1595 return NULL;
1596 }
1597
1598 CLEAR_DBT(pkey);
1599 pkey.flags = DB_DBT_MALLOC;
1600
1601 MYDB_BEGIN_ALLOW_THREADS;
1602 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1603 MYDB_END_ALLOW_THREADS;
1604
Gregory P. Smithe9477062005-06-04 06:46:59 +00001605 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001606 err = 0;
1607 Py_INCREF(dfltobj);
1608 retval = dfltobj;
1609 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001610 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1611 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001612 err = 0;
1613 Py_INCREF(Py_None);
1614 retval = Py_None;
1615 }
1616 else if (!err) {
1617 PyObject *pkeyObj;
1618 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001619 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001620
1621 if (self->primaryDBType == DB_RECNO ||
1622 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001623 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001625 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001626
1627 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1628 {
1629 PyObject *keyObj;
1630 int type = _DB_get_type(self);
1631 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001632 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001633 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001634 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001635#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001636 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001637#else
1638 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1639#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001640 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001641 }
1642 else /* return just the pkey and data */
1643 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001644#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001645 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001646#else
1647 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1648#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001649 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001650 Py_DECREF(dataObj);
1651 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001652 FREE_DBT(pkey);
1653 FREE_DBT(data);
1654 }
1655 FREE_DBT(key);
1656
1657 RETURN_IF_ERR();
1658 return retval;
1659}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001660#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001661
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001662
1663/* Return size of entry */
1664static PyObject*
1665DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1666{
1667 int err, flags=0;
1668 PyObject* txnobj = NULL;
1669 PyObject* keyobj;
1670 PyObject* retval = NULL;
1671 DBT key, data;
1672 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001673 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001674
1675 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1676 &keyobj, &txnobj))
1677 return NULL;
1678 CHECK_DB_NOT_CLOSED(self);
1679 if (!make_key_dbt(self, keyobj, &key, &flags))
1680 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001681 if (!checkTxnObj(txnobj, &txn)) {
1682 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001683 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001684 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685 CLEAR_DBT(data);
1686
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001687 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1688 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001689 data.flags = DB_DBT_USERMEM;
1690 data.ulen = 0;
1691 MYDB_BEGIN_ALLOW_THREADS;
1692 err = self->db->get(self->db, txn, &key, &data, flags);
1693 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001694 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001695 retval = PyInt_FromLong((long)data.size);
1696 err = 0;
1697 }
1698
1699 FREE_DBT(key);
1700 FREE_DBT(data);
1701 RETURN_IF_ERR();
1702 return retval;
1703}
1704
1705
1706static PyObject*
1707DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1708{
1709 int err, flags=0;
1710 PyObject* txnobj = NULL;
1711 PyObject* keyobj;
1712 PyObject* dataobj;
1713 PyObject* retval = NULL;
1714 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001715 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001716 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001717 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001718
1719
1720 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1721 &keyobj, &dataobj, &txnobj, &flags))
1722 return NULL;
1723
1724 CHECK_DB_NOT_CLOSED(self);
1725 if (!make_key_dbt(self, keyobj, &key, NULL))
1726 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001727 if ( !make_dbt(dataobj, &data) ||
1728 !checkTxnObj(txnobj, &txn) )
1729 {
1730 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001731 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001732 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001733
1734 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001735 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001736
1737 if (CHECK_DBFLAG(self, DB_THREAD)) {
1738 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001739 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001740 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001741 }
1742
1743 MYDB_BEGIN_ALLOW_THREADS;
1744 err = self->db->get(self->db, txn, &key, &data, flags);
1745 MYDB_END_ALLOW_THREADS;
1746
Gregory P. Smithe9477062005-06-04 06:46:59 +00001747 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1748 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001749 err = 0;
1750 Py_INCREF(Py_None);
1751 retval = Py_None;
1752 }
1753 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001754 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001755 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001756
1757 /* Even though the flags require DB_DBT_MALLOC, data is not always
1758 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1759 if (data.data != orig_data)
1760 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001761 }
1762
1763 FREE_DBT(key);
1764 RETURN_IF_ERR();
1765 return retval;
1766}
1767
1768
1769static PyObject*
1770DB_get_byteswapped(DBObject* self, PyObject* args)
1771{
1772#if (DBVER >= 33)
1773 int err = 0;
1774#endif
1775 int retval = -1;
1776
1777 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1778 return NULL;
1779 CHECK_DB_NOT_CLOSED(self);
1780
1781#if (DBVER >= 33)
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 err = self->db->get_byteswapped(self->db, &retval);
1784 MYDB_END_ALLOW_THREADS;
1785 RETURN_IF_ERR();
1786#else
1787 MYDB_BEGIN_ALLOW_THREADS;
1788 retval = self->db->get_byteswapped(self->db);
1789 MYDB_END_ALLOW_THREADS;
1790#endif
1791 return PyInt_FromLong(retval);
1792}
1793
1794
1795static PyObject*
1796DB_get_type(DBObject* self, PyObject* args)
1797{
1798 int type;
1799
1800 if (!PyArg_ParseTuple(args,":get_type"))
1801 return NULL;
1802 CHECK_DB_NOT_CLOSED(self);
1803
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001804 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 if (type == -1)
1806 return NULL;
1807 return PyInt_FromLong(type);
1808}
1809
1810
1811static PyObject*
1812DB_join(DBObject* self, PyObject* args)
1813{
1814 int err, flags=0;
1815 int length, x;
1816 PyObject* cursorsObj;
1817 DBC** cursors;
1818 DBC* dbc;
1819
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001820 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1821 return NULL;
1822
1823 CHECK_DB_NOT_CLOSED(self);
1824
1825 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001826 PyErr_SetString(PyExc_TypeError,
1827 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 return NULL;
1829 }
1830
1831 length = PyObject_Length(cursorsObj);
1832 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001833 if (!cursors) {
1834 PyErr_NoMemory();
1835 return NULL;
1836 }
1837
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001838 cursors[length] = NULL;
1839 for (x=0; x<length; x++) {
1840 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001841 if (item == NULL) {
1842 free(cursors);
1843 return NULL;
1844 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001846 PyErr_SetString(PyExc_TypeError,
1847 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 free(cursors);
1849 return NULL;
1850 }
1851 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001852 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 }
1854
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 err = self->db->join(self->db, cursors, &dbc, flags);
1857 MYDB_END_ALLOW_THREADS;
1858 free(cursors);
1859 RETURN_IF_ERR();
1860
Gregory P. Smith7441e652003-11-03 21:35:31 +00001861 /* FIXME: this is a buggy interface. The returned cursor
1862 contains internal references to the passed in cursors
1863 but does not hold python references to them or prevent
1864 them from being closed prematurely. This can cause
1865 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001866 return (PyObject*) newDBCursorObject(dbc, self);
1867}
1868
1869
1870static PyObject*
1871DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1872{
1873 int err, flags=0;
1874 PyObject* txnobj = NULL;
1875 PyObject* keyobj;
1876 DBT key;
1877 DB_TXN *txn = NULL;
1878 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001879 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001880
1881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1882 &keyobj, &txnobj, &flags))
1883 return NULL;
1884 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001885 if (!make_dbt(keyobj, &key))
1886 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001887 return NULL;
1888 if (!checkTxnObj(txnobj, &txn))
1889 return NULL;
1890
1891 MYDB_BEGIN_ALLOW_THREADS;
1892 err = self->db->key_range(self->db, txn, &key, &range, flags);
1893 MYDB_END_ALLOW_THREADS;
1894
1895 RETURN_IF_ERR();
1896 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1897}
1898
1899
1900static PyObject*
1901DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1902{
1903 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1904 char* filename = NULL;
1905 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001906#if (DBVER >= 41)
1907 PyObject *txnobj = NULL;
1908 DB_TXN *txn = NULL;
1909 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001910 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001911 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1912 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001913 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001914 "filename", "dbtype", "flags", "mode", "txn", NULL};
1915#else
1916 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001917 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1919 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001920 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001921 "filename", "dbtype", "flags", "mode", NULL};
1922#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001923
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001924#if (DBVER >= 41)
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1926 &filename, &dbname, &type, &flags, &mode,
1927 &txnobj))
1928#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001930 &filename, &dbname, &type, &flags,
1931 &mode))
1932#endif
1933 {
1934 PyErr_Clear();
1935 type = DB_UNKNOWN; flags = 0; mode = 0660;
1936 filename = NULL; dbname = NULL;
1937#if (DBVER >= 41)
1938 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1939 kwnames_basic,
1940 &filename, &type, &flags, &mode,
1941 &txnobj))
1942 return NULL;
1943#else
1944 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1945 kwnames_basic,
1946 &filename, &type, &flags, &mode))
1947 return NULL;
1948#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 }
1950
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001951#if (DBVER >= 41)
1952 if (!checkTxnObj(txnobj, &txn)) return NULL;
1953#endif
1954
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001955 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001956 PyObject *t = Py_BuildValue("(is)", 0,
1957 "Cannot call open() twice for DB object");
1958 PyErr_SetObject(DBError, t);
1959 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 return NULL;
1961 }
1962
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001963#if 0 && (DBVER >= 41)
1964 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1965 && (self->myenvobj->flags & DB_INIT_TXN))
1966 {
1967 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1968 * explicitly passed) but we are in a transaction ready environment:
1969 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1970 * to work on BerkeleyDB 4.1 without needing to modify their
1971 * DBEnv or DB open calls.
1972 * TODO make this behaviour of the library configurable.
1973 */
1974 flags |= DB_AUTO_COMMIT;
1975 }
1976#endif
1977
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001978 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001979#if (DBVER >= 41)
1980 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1981#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001982 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001983#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984 MYDB_END_ALLOW_THREADS;
1985 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001986 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001987 self->db = NULL;
1988 return NULL;
1989 }
1990
1991 self->flags = flags;
1992 RETURN_NONE();
1993}
1994
1995
1996static PyObject*
1997DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1998{
1999 int flags=0;
2000 PyObject* txnobj = NULL;
2001 int dlen = -1;
2002 int doff = -1;
2003 PyObject* keyobj, *dataobj, *retval;
2004 DBT key, data;
2005 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002006 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002007 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002008
2009 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2010 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2011 return NULL;
2012
2013 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002014 if (!make_key_dbt(self, keyobj, &key, NULL))
2015 return NULL;
2016 if ( !make_dbt(dataobj, &data) ||
2017 !add_partial_dbt(&data, dlen, doff) ||
2018 !checkTxnObj(txnobj, &txn) )
2019 {
2020 FREE_DBT(key);
2021 return NULL;
2022 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002023
2024 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2025 FREE_DBT(key);
2026 return NULL;
2027 }
2028
2029 if (flags & DB_APPEND)
2030 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2031 else {
2032 retval = Py_None;
2033 Py_INCREF(retval);
2034 }
2035 FREE_DBT(key);
2036 return retval;
2037}
2038
2039
2040
2041static PyObject*
2042DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2043{
2044 char* filename;
2045 char* database = NULL;
2046 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002047 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002048
2049 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2050 &filename, &database, &flags))
2051 return NULL;
2052 CHECK_DB_NOT_CLOSED(self);
2053
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002054 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002055 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002056 RETURN_IF_ERR();
2057 RETURN_NONE();
2058}
2059
2060
2061
2062static PyObject*
2063DB_rename(DBObject* self, PyObject* args)
2064{
2065 char* filename;
2066 char* database;
2067 char* newname;
2068 int err, flags=0;
2069
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002070 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2071 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002072 return NULL;
2073 CHECK_DB_NOT_CLOSED(self);
2074
2075 MYDB_BEGIN_ALLOW_THREADS;
2076 err = self->db->rename(self->db, filename, database, newname, flags);
2077 MYDB_END_ALLOW_THREADS;
2078 RETURN_IF_ERR();
2079 RETURN_NONE();
2080}
2081
2082
2083static PyObject*
2084DB_set_bt_minkey(DBObject* self, PyObject* args)
2085{
2086 int err, minkey;
2087
2088 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2089 return NULL;
2090 CHECK_DB_NOT_CLOSED(self);
2091
2092 MYDB_BEGIN_ALLOW_THREADS;
2093 err = self->db->set_bt_minkey(self->db, minkey);
2094 MYDB_END_ALLOW_THREADS;
2095 RETURN_IF_ERR();
2096 RETURN_NONE();
2097}
2098
Neal Norwitz84562352005-10-20 04:30:15 +00002099#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002101_default_cmp(const DBT *leftKey,
2102 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103{
2104 int res;
2105 int lsize = leftKey->size, rsize = rightKey->size;
2106
Georg Brandlef1701f2006-03-07 14:57:48 +00002107 res = memcmp(leftKey->data, rightKey->data,
2108 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109
2110 if (res == 0) {
2111 if (lsize < rsize) {
2112 res = -1;
2113 }
2114 else if (lsize > rsize) {
2115 res = 1;
2116 }
2117 }
2118 return res;
2119}
2120
2121static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002122_db_compareCallback(DB* db,
2123 const DBT *leftKey,
2124 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125{
2126 int res = 0;
2127 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002128 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130
2131 if (self == NULL || self->btCompareCallback == NULL) {
2132 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 PyErr_SetString(PyExc_TypeError,
2134 (self == 0
2135 ? "DB_bt_compare db is NULL."
2136 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002138 PyErr_Print();
2139 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002140 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002141 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142 MYDB_BEGIN_BLOCK_THREADS;
2143
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002144 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002145 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002146 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002147 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002149 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002150 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002151 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002152 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002153 PyErr_Print();
2154 res = _default_cmp(leftKey, rightKey);
2155 } else if (PyInt_Check(result)) {
2156 res = PyInt_AsLong(result);
2157 } else {
2158 PyErr_SetString(PyExc_TypeError,
2159 "DB_bt_compare callback MUST return an int.");
2160 /* we're in a callback within the DB code, we can't raise */
2161 PyErr_Print();
2162 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163 }
2164
Thomas Woutersb3153832006-03-08 01:47:19 +00002165 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002166 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002167
2168 MYDB_END_BLOCK_THREADS;
2169 }
2170 return res;
2171}
2172
2173static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002174DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002175{
2176 int err;
2177 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002178 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002179
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181 return NULL;
2182
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184
Georg Brandlef1701f2006-03-07 14:57:48 +00002185 if (!PyCallable_Check(comparator)) {
2186 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187 return NULL;
2188 }
2189
2190 /*
2191 * Perform a test call of the comparator function with two empty
2192 * string objects here. verify that it returns an int (0).
2193 * err if not.
2194 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002195 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002196 result = PyEval_CallObject(comparator, tuple);
2197 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002198 if (result == NULL)
2199 return NULL;
2200 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002201 PyErr_SetString(PyExc_TypeError,
2202 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002203 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002204 } else if (PyInt_AsLong(result) != 0) {
2205 PyErr_SetString(PyExc_TypeError,
2206 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207 return NULL;
2208 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002209 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002210
2211 /* We don't accept multiple set_bt_compare operations, in order to
2212 * simplify the code. This would have no real use, as one cannot
2213 * change the function once the db is opened anyway */
2214 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002215 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216 return NULL;
2217 }
2218
Georg Brandlef1701f2006-03-07 14:57:48 +00002219 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002220 self->btCompareCallback = comparator;
2221
2222 /* This is to workaround a problem with un-initialized threads (see
2223 comment in DB_associate) */
2224#ifdef WITH_THREAD
2225 PyEval_InitThreads();
2226#endif
2227
Thomas Woutersb3153832006-03-08 01:47:19 +00002228 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002229
2230 if (err) {
2231 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002232 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002233 self->btCompareCallback = NULL;
2234 }
2235
Georg Brandlef1701f2006-03-07 14:57:48 +00002236 RETURN_IF_ERR();
2237 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002238}
Neal Norwitz84562352005-10-20 04:30:15 +00002239#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002240
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002241
2242static PyObject*
2243DB_set_cachesize(DBObject* self, PyObject* args)
2244{
2245 int err;
2246 int gbytes = 0, bytes = 0, ncache = 0;
2247
2248 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2249 &gbytes,&bytes,&ncache))
2250 return NULL;
2251 CHECK_DB_NOT_CLOSED(self);
2252
2253 MYDB_BEGIN_ALLOW_THREADS;
2254 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2255 MYDB_END_ALLOW_THREADS;
2256 RETURN_IF_ERR();
2257 RETURN_NONE();
2258}
2259
2260
2261static PyObject*
2262DB_set_flags(DBObject* self, PyObject* args)
2263{
2264 int err, flags;
2265
2266 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2267 return NULL;
2268 CHECK_DB_NOT_CLOSED(self);
2269
2270 MYDB_BEGIN_ALLOW_THREADS;
2271 err = self->db->set_flags(self->db, flags);
2272 MYDB_END_ALLOW_THREADS;
2273 RETURN_IF_ERR();
2274
2275 self->setflags |= flags;
2276 RETURN_NONE();
2277}
2278
2279
2280static PyObject*
2281DB_set_h_ffactor(DBObject* self, PyObject* args)
2282{
2283 int err, ffactor;
2284
2285 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2286 return NULL;
2287 CHECK_DB_NOT_CLOSED(self);
2288
2289 MYDB_BEGIN_ALLOW_THREADS;
2290 err = self->db->set_h_ffactor(self->db, ffactor);
2291 MYDB_END_ALLOW_THREADS;
2292 RETURN_IF_ERR();
2293 RETURN_NONE();
2294}
2295
2296
2297static PyObject*
2298DB_set_h_nelem(DBObject* self, PyObject* args)
2299{
2300 int err, nelem;
2301
2302 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2303 return NULL;
2304 CHECK_DB_NOT_CLOSED(self);
2305
2306 MYDB_BEGIN_ALLOW_THREADS;
2307 err = self->db->set_h_nelem(self->db, nelem);
2308 MYDB_END_ALLOW_THREADS;
2309 RETURN_IF_ERR();
2310 RETURN_NONE();
2311}
2312
2313
2314static PyObject*
2315DB_set_lorder(DBObject* self, PyObject* args)
2316{
2317 int err, lorder;
2318
2319 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2320 return NULL;
2321 CHECK_DB_NOT_CLOSED(self);
2322
2323 MYDB_BEGIN_ALLOW_THREADS;
2324 err = self->db->set_lorder(self->db, lorder);
2325 MYDB_END_ALLOW_THREADS;
2326 RETURN_IF_ERR();
2327 RETURN_NONE();
2328}
2329
2330
2331static PyObject*
2332DB_set_pagesize(DBObject* self, PyObject* args)
2333{
2334 int err, pagesize;
2335
2336 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2337 return NULL;
2338 CHECK_DB_NOT_CLOSED(self);
2339
2340 MYDB_BEGIN_ALLOW_THREADS;
2341 err = self->db->set_pagesize(self->db, pagesize);
2342 MYDB_END_ALLOW_THREADS;
2343 RETURN_IF_ERR();
2344 RETURN_NONE();
2345}
2346
2347
2348static PyObject*
2349DB_set_re_delim(DBObject* self, PyObject* args)
2350{
2351 int err;
2352 char delim;
2353
2354 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2355 PyErr_Clear();
2356 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2357 return NULL;
2358 }
2359
2360 CHECK_DB_NOT_CLOSED(self);
2361
2362 MYDB_BEGIN_ALLOW_THREADS;
2363 err = self->db->set_re_delim(self->db, delim);
2364 MYDB_END_ALLOW_THREADS;
2365 RETURN_IF_ERR();
2366 RETURN_NONE();
2367}
2368
2369static PyObject*
2370DB_set_re_len(DBObject* self, PyObject* args)
2371{
2372 int err, len;
2373
2374 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2375 return NULL;
2376 CHECK_DB_NOT_CLOSED(self);
2377
2378 MYDB_BEGIN_ALLOW_THREADS;
2379 err = self->db->set_re_len(self->db, len);
2380 MYDB_END_ALLOW_THREADS;
2381 RETURN_IF_ERR();
2382 RETURN_NONE();
2383}
2384
2385
2386static PyObject*
2387DB_set_re_pad(DBObject* self, PyObject* args)
2388{
2389 int err;
2390 char pad;
2391
2392 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2393 PyErr_Clear();
2394 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2395 return NULL;
2396 }
2397 CHECK_DB_NOT_CLOSED(self);
2398
2399 MYDB_BEGIN_ALLOW_THREADS;
2400 err = self->db->set_re_pad(self->db, pad);
2401 MYDB_END_ALLOW_THREADS;
2402 RETURN_IF_ERR();
2403 RETURN_NONE();
2404}
2405
2406
2407static PyObject*
2408DB_set_re_source(DBObject* self, PyObject* args)
2409{
2410 int err;
2411 char *re_source;
2412
2413 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2414 return NULL;
2415 CHECK_DB_NOT_CLOSED(self);
2416
2417 MYDB_BEGIN_ALLOW_THREADS;
2418 err = self->db->set_re_source(self->db, re_source);
2419 MYDB_END_ALLOW_THREADS;
2420 RETURN_IF_ERR();
2421 RETURN_NONE();
2422}
2423
2424
2425#if (DBVER >= 32)
2426static PyObject*
2427DB_set_q_extentsize(DBObject* self, PyObject* args)
2428{
2429 int err;
2430 int extentsize;
2431
2432 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2433 return NULL;
2434 CHECK_DB_NOT_CLOSED(self);
2435
2436 MYDB_BEGIN_ALLOW_THREADS;
2437 err = self->db->set_q_extentsize(self->db, extentsize);
2438 MYDB_END_ALLOW_THREADS;
2439 RETURN_IF_ERR();
2440 RETURN_NONE();
2441}
2442#endif
2443
2444static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002445DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002446{
2447 int err, flags = 0, type;
2448 void* sp;
2449 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002450#if (DBVER >= 43)
2451 PyObject* txnobj = NULL;
2452 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002453 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002454#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002455 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002456#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002457
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002458#if (DBVER >= 43)
2459 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2460 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002461 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002462 if (!checkTxnObj(txnobj, &txn))
2463 return NULL;
2464#else
2465 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2466 return NULL;
2467#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002468 CHECK_DB_NOT_CLOSED(self);
2469
2470 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002471#if (DBVER >= 43)
2472 err = self->db->stat(self->db, txn, &sp, flags);
2473#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002474 err = self->db->stat(self->db, &sp, flags);
2475#else
2476 err = self->db->stat(self->db, &sp, NULL, flags);
2477#endif
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480
2481 self->haveStat = 1;
2482
2483 /* Turn the stat structure into a dictionary */
2484 type = _DB_get_type(self);
2485 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2486 free(sp);
2487 return NULL;
2488 }
2489
2490#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2491#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2492#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2493
2494 switch (type) {
2495 case DB_HASH:
2496 MAKE_HASH_ENTRY(magic);
2497 MAKE_HASH_ENTRY(version);
2498 MAKE_HASH_ENTRY(nkeys);
2499 MAKE_HASH_ENTRY(ndata);
2500 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002501#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002502 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002503#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002504 MAKE_HASH_ENTRY(ffactor);
2505 MAKE_HASH_ENTRY(buckets);
2506 MAKE_HASH_ENTRY(free);
2507 MAKE_HASH_ENTRY(bfree);
2508 MAKE_HASH_ENTRY(bigpages);
2509 MAKE_HASH_ENTRY(big_bfree);
2510 MAKE_HASH_ENTRY(overflows);
2511 MAKE_HASH_ENTRY(ovfl_free);
2512 MAKE_HASH_ENTRY(dup);
2513 MAKE_HASH_ENTRY(dup_free);
2514 break;
2515
2516 case DB_BTREE:
2517 case DB_RECNO:
2518 MAKE_BT_ENTRY(magic);
2519 MAKE_BT_ENTRY(version);
2520 MAKE_BT_ENTRY(nkeys);
2521 MAKE_BT_ENTRY(ndata);
2522 MAKE_BT_ENTRY(pagesize);
2523 MAKE_BT_ENTRY(minkey);
2524 MAKE_BT_ENTRY(re_len);
2525 MAKE_BT_ENTRY(re_pad);
2526 MAKE_BT_ENTRY(levels);
2527 MAKE_BT_ENTRY(int_pg);
2528 MAKE_BT_ENTRY(leaf_pg);
2529 MAKE_BT_ENTRY(dup_pg);
2530 MAKE_BT_ENTRY(over_pg);
2531 MAKE_BT_ENTRY(free);
2532 MAKE_BT_ENTRY(int_pgfree);
2533 MAKE_BT_ENTRY(leaf_pgfree);
2534 MAKE_BT_ENTRY(dup_pgfree);
2535 MAKE_BT_ENTRY(over_pgfree);
2536 break;
2537
2538 case DB_QUEUE:
2539 MAKE_QUEUE_ENTRY(magic);
2540 MAKE_QUEUE_ENTRY(version);
2541 MAKE_QUEUE_ENTRY(nkeys);
2542 MAKE_QUEUE_ENTRY(ndata);
2543 MAKE_QUEUE_ENTRY(pagesize);
2544 MAKE_QUEUE_ENTRY(pages);
2545 MAKE_QUEUE_ENTRY(re_len);
2546 MAKE_QUEUE_ENTRY(re_pad);
2547 MAKE_QUEUE_ENTRY(pgfree);
2548#if (DBVER == 31)
2549 MAKE_QUEUE_ENTRY(start);
2550#endif
2551 MAKE_QUEUE_ENTRY(first_recno);
2552 MAKE_QUEUE_ENTRY(cur_recno);
2553 break;
2554
2555 default:
2556 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2557 Py_DECREF(d);
2558 d = NULL;
2559 }
2560
2561#undef MAKE_HASH_ENTRY
2562#undef MAKE_BT_ENTRY
2563#undef MAKE_QUEUE_ENTRY
2564
2565 free(sp);
2566 return d;
2567}
2568
2569static PyObject*
2570DB_sync(DBObject* self, PyObject* args)
2571{
2572 int err;
2573 int flags = 0;
2574
2575 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2576 return NULL;
2577 CHECK_DB_NOT_CLOSED(self);
2578
2579 MYDB_BEGIN_ALLOW_THREADS;
2580 err = self->db->sync(self->db, flags);
2581 MYDB_END_ALLOW_THREADS;
2582 RETURN_IF_ERR();
2583 RETURN_NONE();
2584}
2585
2586
2587#if (DBVER >= 33)
2588static PyObject*
2589DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2590{
2591 int err, flags=0;
2592 u_int32_t count=0;
2593 PyObject* txnobj = NULL;
2594 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002595 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002596
2597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2598 &txnobj, &flags))
2599 return NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601 if (!checkTxnObj(txnobj, &txn))
2602 return NULL;
2603
2604 MYDB_BEGIN_ALLOW_THREADS;
2605 err = self->db->truncate(self->db, txn, &count, flags);
2606 MYDB_END_ALLOW_THREADS;
2607 RETURN_IF_ERR();
2608 return PyInt_FromLong(count);
2609}
2610#endif
2611
2612
2613static PyObject*
2614DB_upgrade(DBObject* self, PyObject* args)
2615{
2616 int err, flags=0;
2617 char *filename;
2618
2619 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2620 return NULL;
2621 CHECK_DB_NOT_CLOSED(self);
2622
2623 MYDB_BEGIN_ALLOW_THREADS;
2624 err = self->db->upgrade(self->db, filename, flags);
2625 MYDB_END_ALLOW_THREADS;
2626 RETURN_IF_ERR();
2627 RETURN_NONE();
2628}
2629
2630
2631static PyObject*
2632DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2633{
2634 int err, flags=0;
2635 char* fileName;
2636 char* dbName=NULL;
2637 char* outFileName=NULL;
2638 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002639 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002640 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002641
2642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2643 &fileName, &dbName, &outFileName, &flags))
2644 return NULL;
2645
2646 CHECK_DB_NOT_CLOSED(self);
2647 if (outFileName)
2648 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002649 /* XXX(nnorwitz): it should probably be an exception if outFile
2650 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651
2652 MYDB_BEGIN_ALLOW_THREADS;
2653 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2654 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002655 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002656 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002657
2658 /* DB.verify acts as a DB handle destructor (like close); this was
2659 * documented in BerkeleyDB 4.2 but had the undocumented effect
2660 * of not being safe in prior versions while still requiring an explicit
2661 * DB.close call afterwards. Lets call close for the user to emulate
2662 * the safe 4.2 behaviour. */
2663#if (DBVER <= 41)
2664 self->db->close(self->db, 0);
2665#endif
2666 self->db = NULL;
2667
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002668 RETURN_IF_ERR();
2669 RETURN_NONE();
2670}
2671
2672
2673static PyObject*
2674DB_set_get_returns_none(DBObject* self, PyObject* args)
2675{
2676 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002677 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002678
2679 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2680 return NULL;
2681 CHECK_DB_NOT_CLOSED(self);
2682
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002683 if (self->moduleFlags.getReturnsNone)
2684 ++oldValue;
2685 if (self->moduleFlags.cursorSetReturnsNone)
2686 ++oldValue;
2687 self->moduleFlags.getReturnsNone = (flags >= 1);
2688 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002689 return PyInt_FromLong(oldValue);
2690}
2691
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002692#if (DBVER >= 41)
2693static PyObject*
2694DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2695{
2696 int err;
2697 u_int32_t flags=0;
2698 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002699 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002700
2701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2702 &passwd, &flags)) {
2703 return NULL;
2704 }
2705
2706 MYDB_BEGIN_ALLOW_THREADS;
2707 err = self->db->set_encrypt(self->db, passwd, flags);
2708 MYDB_END_ALLOW_THREADS;
2709
2710 RETURN_IF_ERR();
2711 RETURN_NONE();
2712}
2713#endif /* DBVER >= 41 */
2714
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002715
2716/*-------------------------------------------------------------- */
2717/* Mapping and Dictionary-like access routines */
2718
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002719Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720{
2721 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002722 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723 int flags = 0;
2724 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002725 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726
2727 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002728 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2729 PyErr_SetObject(DBError, t);
2730 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002731 return -1;
2732 }
2733
2734 if (self->haveStat) { /* Has the stat function been called recently? If
2735 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002736 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 }
2738
2739 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002740redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002741#if (DBVER >= 43)
2742 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2743#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 err = self->db->stat(self->db, &sp, flags);
2745#else
2746 err = self->db->stat(self->db, &sp, NULL, flags);
2747#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002748
2749 /* All the stat structures have matching fields upto the ndata field,
2750 so we can use any of them for the type cast */
2751 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2752
2753 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2754 * redo a full stat to make sure.
2755 * Fixes SF python bug 1493322, pybsddb bug 1184012
2756 */
2757 if (size == 0 && (flags & DB_FAST_STAT)) {
2758 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002759 if (!err)
2760 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002761 goto redo_stat_for_length;
2762 }
2763
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002764 MYDB_END_ALLOW_THREADS;
2765
2766 if (err)
2767 return -1;
2768
2769 self->haveStat = 1;
2770
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002771 free(sp);
2772 return size;
2773}
2774
2775
2776PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2777{
2778 int err;
2779 PyObject* retval;
2780 DBT key;
2781 DBT data;
2782
2783 CHECK_DB_NOT_CLOSED(self);
2784 if (!make_key_dbt(self, keyobj, &key, NULL))
2785 return NULL;
2786
2787 CLEAR_DBT(data);
2788 if (CHECK_DBFLAG(self, DB_THREAD)) {
2789 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2790 data.flags = DB_DBT_MALLOC;
2791 }
2792 MYDB_BEGIN_ALLOW_THREADS;
2793 err = self->db->get(self->db, NULL, &key, &data, 0);
2794 MYDB_END_ALLOW_THREADS;
2795 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2796 PyErr_SetObject(PyExc_KeyError, keyobj);
2797 retval = NULL;
2798 }
2799 else if (makeDBError(err)) {
2800 retval = NULL;
2801 }
2802 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002803 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804 FREE_DBT(data);
2805 }
2806
2807 FREE_DBT(key);
2808 return retval;
2809}
2810
2811
2812static int
2813DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2814{
2815 DBT key, data;
2816 int retval;
2817 int flags = 0;
2818
2819 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002820 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2821 PyErr_SetObject(DBError, t);
2822 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002823 return -1;
2824 }
2825
2826 if (!make_key_dbt(self, keyobj, &key, NULL))
2827 return -1;
2828
2829 if (dataobj != NULL) {
2830 if (!make_dbt(dataobj, &data))
2831 retval = -1;
2832 else {
2833 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002834 /* dictionaries shouldn't have duplicate keys */
2835 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836 retval = _DB_put(self, NULL, &key, &data, flags);
2837
2838 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002839 /* try deleting any old record that matches and then PUT it
2840 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002841 _DB_delete(self, NULL, &key, 0);
2842 PyErr_Clear();
2843 retval = _DB_put(self, NULL, &key, &data, flags);
2844 }
2845 }
2846 }
2847 else {
2848 /* dataobj == NULL, so delete the key */
2849 retval = _DB_delete(self, NULL, &key, 0);
2850 }
2851 FREE_DBT(key);
2852 return retval;
2853}
2854
2855
2856static PyObject*
2857DB_has_key(DBObject* self, PyObject* args)
2858{
2859 int err;
2860 PyObject* keyobj;
2861 DBT key, data;
2862 PyObject* txnobj = NULL;
2863 DB_TXN *txn = NULL;
2864
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002865 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 return NULL;
2867 CHECK_DB_NOT_CLOSED(self);
2868 if (!make_key_dbt(self, keyobj, &key, NULL))
2869 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002870 if (!checkTxnObj(txnobj, &txn)) {
2871 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002873 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002874
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002875 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002876 it has a record but can't allocate a buffer for the data. This saves
2877 having to deal with data we won't be using.
2878 */
2879 CLEAR_DBT(data);
2880 data.flags = DB_DBT_USERMEM;
2881
2882 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002883 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002884 MYDB_END_ALLOW_THREADS;
2885 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002886
2887 if (err == DB_BUFFER_SMALL || err == 0) {
2888 return PyInt_FromLong(1);
2889 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2890 return PyInt_FromLong(0);
2891 }
2892
2893 makeDBError(err);
2894 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002895}
2896
2897
2898#define _KEYS_LIST 1
2899#define _VALUES_LIST 2
2900#define _ITEMS_LIST 3
2901
2902static PyObject*
2903_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2904{
2905 int err, dbtype;
2906 DBT key;
2907 DBT data;
2908 DBC *cursor;
2909 PyObject* list;
2910 PyObject* item = NULL;
2911
2912 CHECK_DB_NOT_CLOSED(self);
2913 CLEAR_DBT(key);
2914 CLEAR_DBT(data);
2915
2916 dbtype = _DB_get_type(self);
2917 if (dbtype == -1)
2918 return NULL;
2919
2920 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002921 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002922 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923
2924 /* get a cursor */
2925 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002926 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002928 if (makeDBError(err)) {
2929 Py_DECREF(list);
2930 return NULL;
2931 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002932
2933 if (CHECK_DBFLAG(self, DB_THREAD)) {
2934 key.flags = DB_DBT_REALLOC;
2935 data.flags = DB_DBT_REALLOC;
2936 }
2937
2938 while (1) { /* use the cursor to traverse the DB, collecting items */
2939 MYDB_BEGIN_ALLOW_THREADS;
2940 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2941 MYDB_END_ALLOW_THREADS;
2942
2943 if (err) {
2944 /* for any error, break out of the loop */
2945 break;
2946 }
2947
2948 switch (type) {
2949 case _KEYS_LIST:
2950 switch(dbtype) {
2951 case DB_BTREE:
2952 case DB_HASH:
2953 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002954 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002955 break;
2956 case DB_RECNO:
2957 case DB_QUEUE:
2958 item = PyInt_FromLong(*((db_recno_t*)key.data));
2959 break;
2960 }
2961 break;
2962
2963 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002964 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965 break;
2966
2967 case _ITEMS_LIST:
2968 switch(dbtype) {
2969 case DB_BTREE:
2970 case DB_HASH:
2971 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002972 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002973 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002974 break;
2975 case DB_RECNO:
2976 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002977 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002978 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002979 break;
2980 }
2981 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002982 default:
2983 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2984 item = NULL;
2985 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986 }
2987 if (item == NULL) {
2988 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002989 list = NULL;
2990 goto done;
2991 }
2992 PyList_Append(list, item);
2993 Py_DECREF(item);
2994 }
2995
Gregory P. Smithe9477062005-06-04 06:46:59 +00002996 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2997 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998 Py_DECREF(list);
2999 list = NULL;
3000 }
3001
3002 done:
3003 FREE_DBT(key);
3004 FREE_DBT(data);
3005 MYDB_BEGIN_ALLOW_THREADS;
3006 cursor->c_close(cursor);
3007 MYDB_END_ALLOW_THREADS;
3008 return list;
3009}
3010
3011
3012static PyObject*
3013DB_keys(DBObject* self, PyObject* args)
3014{
3015 PyObject* txnobj = NULL;
3016 DB_TXN *txn = NULL;
3017
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003018 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003019 return NULL;
3020 if (!checkTxnObj(txnobj, &txn))
3021 return NULL;
3022 return _DB_make_list(self, txn, _KEYS_LIST);
3023}
3024
3025
3026static PyObject*
3027DB_items(DBObject* self, PyObject* args)
3028{
3029 PyObject* txnobj = NULL;
3030 DB_TXN *txn = NULL;
3031
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003032 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033 return NULL;
3034 if (!checkTxnObj(txnobj, &txn))
3035 return NULL;
3036 return _DB_make_list(self, txn, _ITEMS_LIST);
3037}
3038
3039
3040static PyObject*
3041DB_values(DBObject* self, PyObject* args)
3042{
3043 PyObject* txnobj = NULL;
3044 DB_TXN *txn = NULL;
3045
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003046 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003047 return NULL;
3048 if (!checkTxnObj(txnobj, &txn))
3049 return NULL;
3050 return _DB_make_list(self, txn, _VALUES_LIST);
3051}
3052
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053/* --------------------------------------------------------------------- */
3054/* DBCursor methods */
3055
3056
3057static PyObject*
3058DBC_close(DBCursorObject* self, PyObject* args)
3059{
3060 int err = 0;
3061
3062 if (!PyArg_ParseTuple(args, ":close"))
3063 return NULL;
3064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065 if (self->dbc != NULL) {
3066 MYDB_BEGIN_ALLOW_THREADS;
3067 err = self->dbc->c_close(self->dbc);
3068 self->dbc = NULL;
3069 MYDB_END_ALLOW_THREADS;
3070 }
3071 RETURN_IF_ERR();
3072 RETURN_NONE();
3073}
3074
3075
3076static PyObject*
3077DBC_count(DBCursorObject* self, PyObject* args)
3078{
3079 int err = 0;
3080 db_recno_t count;
3081 int flags = 0;
3082
3083 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3084 return NULL;
3085
3086 CHECK_CURSOR_NOT_CLOSED(self);
3087
3088 MYDB_BEGIN_ALLOW_THREADS;
3089 err = self->dbc->c_count(self->dbc, &count, flags);
3090 MYDB_END_ALLOW_THREADS;
3091 RETURN_IF_ERR();
3092
3093 return PyInt_FromLong(count);
3094}
3095
3096
3097static PyObject*
3098DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3099{
3100 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3101}
3102
3103
3104static PyObject*
3105DBC_delete(DBCursorObject* self, PyObject* args)
3106{
3107 int err, flags=0;
3108
3109 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3110 return NULL;
3111
3112 CHECK_CURSOR_NOT_CLOSED(self);
3113
3114 MYDB_BEGIN_ALLOW_THREADS;
3115 err = self->dbc->c_del(self->dbc, flags);
3116 MYDB_END_ALLOW_THREADS;
3117 RETURN_IF_ERR();
3118
3119 self->mydb->haveStat = 0;
3120 RETURN_NONE();
3121}
3122
3123
3124static PyObject*
3125DBC_dup(DBCursorObject* self, PyObject* args)
3126{
3127 int err, flags =0;
3128 DBC* dbc = NULL;
3129
3130 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3131 return NULL;
3132
3133 CHECK_CURSOR_NOT_CLOSED(self);
3134
3135 MYDB_BEGIN_ALLOW_THREADS;
3136 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3137 MYDB_END_ALLOW_THREADS;
3138 RETURN_IF_ERR();
3139
3140 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3141}
3142
3143static PyObject*
3144DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3145{
3146 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3147}
3148
3149
3150static PyObject*
3151DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3152{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003153 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003154 PyObject* keyobj = NULL;
3155 PyObject* dataobj = NULL;
3156 PyObject* retval = NULL;
3157 int dlen = -1;
3158 int doff = -1;
3159 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003160 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003161 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162
3163 CLEAR_DBT(key);
3164 CLEAR_DBT(data);
3165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003166 &flags, &dlen, &doff))
3167 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003169 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3170 &kwnames[1],
3171 &keyobj, &flags, &dlen, &doff))
3172 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003174 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3175 kwnames, &keyobj, &dataobj,
3176 &flags, &dlen, &doff))
3177 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003178 return NULL;
3179 }
3180 }
3181 }
3182
3183 CHECK_CURSOR_NOT_CLOSED(self);
3184
3185 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3186 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003187 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3188 (!add_partial_dbt(&data, dlen, doff)) )
3189 {
3190 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003192 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003193
3194 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3195 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003196 if (!(key.flags & DB_DBT_REALLOC)) {
3197 key.flags |= DB_DBT_MALLOC;
3198 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003199 }
3200
3201 MYDB_BEGIN_ALLOW_THREADS;
3202 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3203 MYDB_END_ALLOW_THREADS;
3204
Gregory P. Smithe9477062005-06-04 06:46:59 +00003205 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3206 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003207 Py_INCREF(Py_None);
3208 retval = Py_None;
3209 }
3210 else if (makeDBError(err)) {
3211 retval = NULL;
3212 }
3213 else {
3214 switch (_DB_get_type(self->mydb)) {
3215 case -1:
3216 retval = NULL;
3217 break;
3218 case DB_BTREE:
3219 case DB_HASH:
3220 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003221 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003222 data.data, data.size);
3223 break;
3224 case DB_RECNO:
3225 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003226 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003227 data.data, data.size);
3228 break;
3229 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003230 FREE_DBT(data);
3231 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003232 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003233 return retval;
3234}
3235
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003236#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003237static PyObject*
3238DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3239{
3240 int err, flags=0;
3241 PyObject* keyobj = NULL;
3242 PyObject* dataobj = NULL;
3243 PyObject* retval = NULL;
3244 int dlen = -1;
3245 int doff = -1;
3246 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003247 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3248 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003249
3250 CLEAR_DBT(key);
3251 CLEAR_DBT(data);
3252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3253 &flags, &dlen, &doff))
3254 {
3255 PyErr_Clear();
3256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003257 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003258 &keyobj, &flags, &dlen, &doff))
3259 {
3260 PyErr_Clear();
3261 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3262 kwnames, &keyobj, &dataobj,
3263 &flags, &dlen, &doff))
3264 {
3265 return NULL;
3266 }
3267 }
3268 }
3269
3270 CHECK_CURSOR_NOT_CLOSED(self);
3271
3272 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3273 return NULL;
3274 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3275 (!add_partial_dbt(&data, dlen, doff)) ) {
3276 FREE_DBT(key);
3277 return NULL;
3278 }
3279
3280 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3281 data.flags = DB_DBT_MALLOC;
3282 if (!(key.flags & DB_DBT_REALLOC)) {
3283 key.flags |= DB_DBT_MALLOC;
3284 }
3285 }
3286
3287 CLEAR_DBT(pkey);
3288 pkey.flags = DB_DBT_MALLOC;
3289
3290 MYDB_BEGIN_ALLOW_THREADS;
3291 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3292 MYDB_END_ALLOW_THREADS;
3293
Gregory P. Smithe9477062005-06-04 06:46:59 +00003294 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3295 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003296 Py_INCREF(Py_None);
3297 retval = Py_None;
3298 }
3299 else if (makeDBError(err)) {
3300 retval = NULL;
3301 }
3302 else {
3303 PyObject *pkeyObj;
3304 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003305 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003306
3307 if (self->mydb->primaryDBType == DB_RECNO ||
3308 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003309 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003310 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003311 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003312
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003313 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003314 {
3315 PyObject *keyObj;
3316 int type = _DB_get_type(self->mydb);
3317 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003318 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003319 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003320 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003321#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003322 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003323#else
3324 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3325#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003326 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003327 FREE_DBT(key);
3328 }
3329 else /* return just the pkey and data */
3330 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003331#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003332 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003333#else
3334 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3335#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003336 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003337 Py_DECREF(dataObj);
3338 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003339 FREE_DBT(pkey);
3340 FREE_DBT(data);
3341 }
3342 /* the only time REALLOC should be set is if we used an integer
3343 * key that make_key_dbt malloc'd for us. always free these. */
3344 if (key.flags & DB_DBT_REALLOC) {
3345 FREE_DBT(key);
3346 }
3347 return retval;
3348}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003349#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003350
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003351
3352static PyObject*
3353DBC_get_recno(DBCursorObject* self, PyObject* args)
3354{
3355 int err;
3356 db_recno_t recno;
3357 DBT key;
3358 DBT data;
3359
3360 if (!PyArg_ParseTuple(args, ":get_recno"))
3361 return NULL;
3362
3363 CHECK_CURSOR_NOT_CLOSED(self);
3364
3365 CLEAR_DBT(key);
3366 CLEAR_DBT(data);
3367 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3368 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3369 data.flags = DB_DBT_MALLOC;
3370 key.flags = DB_DBT_MALLOC;
3371 }
3372
3373 MYDB_BEGIN_ALLOW_THREADS;
3374 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3375 MYDB_END_ALLOW_THREADS;
3376 RETURN_IF_ERR();
3377
3378 recno = *((db_recno_t*)data.data);
3379 FREE_DBT(key);
3380 FREE_DBT(data);
3381 return PyInt_FromLong(recno);
3382}
3383
3384
3385static PyObject*
3386DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3387{
3388 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3389}
3390
3391
3392static PyObject*
3393DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3394{
3395 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3396}
3397
3398
3399static PyObject*
3400DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3401{
3402 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3403}
3404
3405
3406static PyObject*
3407DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3408{
3409 int err, flags = 0;
3410 PyObject* keyobj, *dataobj;
3411 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003412 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003413 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 int dlen = -1;
3415 int doff = -1;
3416
3417 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3418 &keyobj, &dataobj, &flags, &dlen, &doff))
3419 return NULL;
3420
3421 CHECK_CURSOR_NOT_CLOSED(self);
3422
3423 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3424 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003425 if (!make_dbt(dataobj, &data) ||
3426 !add_partial_dbt(&data, dlen, doff) )
3427 {
3428 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003429 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003430 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431
3432 MYDB_BEGIN_ALLOW_THREADS;
3433 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3434 MYDB_END_ALLOW_THREADS;
3435 FREE_DBT(key);
3436 RETURN_IF_ERR();
3437 self->mydb->haveStat = 0;
3438 RETURN_NONE();
3439}
3440
3441
3442static PyObject*
3443DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3444{
3445 int err, flags = 0;
3446 DBT key, data;
3447 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003448 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 int dlen = -1;
3450 int doff = -1;
3451
3452 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3453 &keyobj, &flags, &dlen, &doff))
3454 return NULL;
3455
3456 CHECK_CURSOR_NOT_CLOSED(self);
3457
3458 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3459 return NULL;
3460
3461 CLEAR_DBT(data);
3462 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3463 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3464 data.flags = DB_DBT_MALLOC;
3465 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003466 if (!add_partial_dbt(&data, dlen, doff)) {
3467 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003468 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003469 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470
3471 MYDB_BEGIN_ALLOW_THREADS;
3472 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3473 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003474 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3475 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003476 Py_INCREF(Py_None);
3477 retval = Py_None;
3478 }
3479 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 retval = NULL;
3481 }
3482 else {
3483 switch (_DB_get_type(self->mydb)) {
3484 case -1:
3485 retval = NULL;
3486 break;
3487 case DB_BTREE:
3488 case DB_HASH:
3489 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003490 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003491 data.data, data.size);
3492 break;
3493 case DB_RECNO:
3494 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003495 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003496 data.data, data.size);
3497 break;
3498 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003499 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003500 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003501 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003502 /* the only time REALLOC should be set is if we used an integer
3503 * key that make_key_dbt malloc'd for us. always free these. */
3504 if (key.flags & DB_DBT_REALLOC) {
3505 FREE_DBT(key);
3506 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003507
3508 return retval;
3509}
3510
3511
3512static PyObject*
3513DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3514{
3515 int err, flags = 0;
3516 DBT key, data;
3517 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003518 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003519 int dlen = -1;
3520 int doff = -1;
3521
3522 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3523 &keyobj, &flags, &dlen, &doff))
3524 return NULL;
3525
3526 CHECK_CURSOR_NOT_CLOSED(self);
3527
3528 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3529 return NULL;
3530
3531 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003532 if (!add_partial_dbt(&data, dlen, doff)) {
3533 FREE_DBT(key);
3534 return NULL;
3535 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3537 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003538 data.flags |= DB_DBT_MALLOC;
3539 /* only BTREE databases will return anything in the key */
3540 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3541 key.flags |= DB_DBT_MALLOC;
3542 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544 MYDB_BEGIN_ALLOW_THREADS;
3545 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3546 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003547 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3548 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003549 Py_INCREF(Py_None);
3550 retval = Py_None;
3551 }
3552 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553 retval = NULL;
3554 }
3555 else {
3556 switch (_DB_get_type(self->mydb)) {
3557 case -1:
3558 retval = NULL;
3559 break;
3560 case DB_BTREE:
3561 case DB_HASH:
3562 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003563 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003564 data.data, data.size);
3565 break;
3566 case DB_RECNO:
3567 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003568 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569 data.data, data.size);
3570 break;
3571 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573 FREE_DBT(data);
3574 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003575 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003576 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003577 if (key.flags & DB_DBT_REALLOC) {
3578 FREE_DBT(key);
3579 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580
3581 return retval;
3582}
3583
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003585_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3586 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003588 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003590 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003591
Gregory P. Smith7441e652003-11-03 21:35:31 +00003592 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003593 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3594 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003595 if (!make_dbt(dataobj, &data)) {
3596 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003597 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003598 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599
3600 MYDB_BEGIN_ALLOW_THREADS;
3601 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3602 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003603 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003604 Py_INCREF(Py_None);
3605 retval = Py_None;
3606 }
3607 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003608 retval = NULL;
3609 }
3610 else {
3611 switch (_DB_get_type(self->mydb)) {
3612 case -1:
3613 retval = NULL;
3614 break;
3615 case DB_BTREE:
3616 case DB_HASH:
3617 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003618 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619 data.data, data.size);
3620 break;
3621 case DB_RECNO:
3622 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003623 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003624 data.data, data.size);
3625 break;
3626 }
3627 }
3628
3629 FREE_DBT(key);
3630 return retval;
3631}
3632
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003633static PyObject*
3634DBC_get_both(DBCursorObject* self, PyObject* args)
3635{
3636 int flags=0;
3637 PyObject *keyobj, *dataobj;
3638
3639 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3640 return NULL;
3641
Gregory P. Smith7441e652003-11-03 21:35:31 +00003642 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003643 CHECK_CURSOR_NOT_CLOSED(self);
3644
3645 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3646 self->mydb->moduleFlags.getReturnsNone);
3647}
3648
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003649/* Return size of entry */
3650static PyObject*
3651DBC_get_current_size(DBCursorObject* self, PyObject* args)
3652{
3653 int err, flags=DB_CURRENT;
3654 PyObject* retval = NULL;
3655 DBT key, data;
3656
3657 if (!PyArg_ParseTuple(args, ":get_current_size"))
3658 return NULL;
3659 CHECK_CURSOR_NOT_CLOSED(self);
3660 CLEAR_DBT(key);
3661 CLEAR_DBT(data);
3662
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003663 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003664 getting the record size. */
3665 data.flags = DB_DBT_USERMEM;
3666 data.ulen = 0;
3667 MYDB_BEGIN_ALLOW_THREADS;
3668 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3669 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003670 if (err == DB_BUFFER_SMALL || !err) {
3671 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003672 retval = PyInt_FromLong((long)data.size);
3673 err = 0;
3674 }
3675
3676 FREE_DBT(key);
3677 FREE_DBT(data);
3678 RETURN_IF_ERR();
3679 return retval;
3680}
3681
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003682static PyObject*
3683DBC_set_both(DBCursorObject* self, PyObject* args)
3684{
3685 int flags=0;
3686 PyObject *keyobj, *dataobj;
3687
3688 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3689 return NULL;
3690
Gregory P. Smith7441e652003-11-03 21:35:31 +00003691 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003692 CHECK_CURSOR_NOT_CLOSED(self);
3693
3694 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3695 self->mydb->moduleFlags.cursorSetReturnsNone);
3696}
3697
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003698
3699static PyObject*
3700DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3701{
3702 int err, irecno, flags=0;
3703 db_recno_t recno;
3704 DBT key, data;
3705 PyObject* retval;
3706 int dlen = -1;
3707 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003708 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003709
3710 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3711 &irecno, &flags, &dlen, &doff))
3712 return NULL;
3713
3714 CHECK_CURSOR_NOT_CLOSED(self);
3715
3716 CLEAR_DBT(key);
3717 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003718 /* use allocated space so DB will be able to realloc room for the real
3719 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003720 key.data = malloc(sizeof(db_recno_t));
3721 if (key.data == NULL) {
3722 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3723 return NULL;
3724 }
3725 key.size = sizeof(db_recno_t);
3726 key.ulen = key.size;
3727 memcpy(key.data, &recno, sizeof(db_recno_t));
3728 key.flags = DB_DBT_REALLOC;
3729
3730 CLEAR_DBT(data);
3731 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3732 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3733 data.flags = DB_DBT_MALLOC;
3734 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003735 if (!add_partial_dbt(&data, dlen, doff)) {
3736 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003737 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003738 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003739
3740 MYDB_BEGIN_ALLOW_THREADS;
3741 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3742 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003743 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3744 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003745 Py_INCREF(Py_None);
3746 retval = Py_None;
3747 }
3748 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749 retval = NULL;
3750 }
3751 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003752 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003753 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754 FREE_DBT(data);
3755 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003756 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757
3758 return retval;
3759}
3760
3761
3762static PyObject*
3763DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3764{
3765 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3766}
3767
3768
3769static PyObject*
3770DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3771{
3772 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3773}
3774
3775
3776static PyObject*
3777DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3778{
3779 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3780}
3781
3782
3783static PyObject*
3784DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3785{
3786 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3787}
3788
3789
3790static PyObject*
3791DBC_join_item(DBCursorObject* self, PyObject* args)
3792{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794 DBT key, data;
3795 PyObject* retval;
3796
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003797 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003798 return NULL;
3799
3800 CHECK_CURSOR_NOT_CLOSED(self);
3801
3802 CLEAR_DBT(key);
3803 CLEAR_DBT(data);
3804 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3805 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3806 key.flags = DB_DBT_MALLOC;
3807 }
3808
3809 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003810 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003811 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003812 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3813 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003814 Py_INCREF(Py_None);
3815 retval = Py_None;
3816 }
3817 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 retval = NULL;
3819 }
3820 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003821 retval = Py_BuildValue("y#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003822 FREE_DBT(key);
3823 }
3824
3825 return retval;
3826}
3827
3828
3829
3830/* --------------------------------------------------------------------- */
3831/* DBEnv methods */
3832
3833
3834static PyObject*
3835DBEnv_close(DBEnvObject* self, PyObject* args)
3836{
3837 int err, flags = 0;
3838
3839 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3840 return NULL;
3841 if (!self->closed) { /* Don't close more than once */
3842 MYDB_BEGIN_ALLOW_THREADS;
3843 err = self->db_env->close(self->db_env, flags);
3844 MYDB_END_ALLOW_THREADS;
3845 /* after calling DBEnv->close, regardless of error, this DBEnv
3846 * may not be accessed again (BerkeleyDB docs). */
3847 self->closed = 1;
3848 self->db_env = NULL;
3849 RETURN_IF_ERR();
3850 }
3851 RETURN_NONE();
3852}
3853
3854
3855static PyObject*
3856DBEnv_open(DBEnvObject* self, PyObject* args)
3857{
3858 int err, flags=0, mode=0660;
3859 char *db_home;
3860
3861 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3862 return NULL;
3863
3864 CHECK_ENV_NOT_CLOSED(self);
3865
3866 MYDB_BEGIN_ALLOW_THREADS;
3867 err = self->db_env->open(self->db_env, db_home, flags, mode);
3868 MYDB_END_ALLOW_THREADS;
3869 RETURN_IF_ERR();
3870 self->closed = 0;
3871 self->flags = flags;
3872 RETURN_NONE();
3873}
3874
3875
3876static PyObject*
3877DBEnv_remove(DBEnvObject* self, PyObject* args)
3878{
3879 int err, flags=0;
3880 char *db_home;
3881
3882 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3883 return NULL;
3884 CHECK_ENV_NOT_CLOSED(self);
3885 MYDB_BEGIN_ALLOW_THREADS;
3886 err = self->db_env->remove(self->db_env, db_home, flags);
3887 MYDB_END_ALLOW_THREADS;
3888 RETURN_IF_ERR();
3889 RETURN_NONE();
3890}
3891
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003892#if (DBVER >= 41)
3893static PyObject*
3894DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3895{
3896 int err;
3897 u_int32_t flags=0;
3898 char *file = NULL;
3899 char *database = NULL;
3900 PyObject *txnobj = NULL;
3901 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003902 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003903 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003904
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003906 &file, &database, &txnobj, &flags)) {
3907 return NULL;
3908 }
3909 if (!checkTxnObj(txnobj, &txn)) {
3910 return NULL;
3911 }
3912 CHECK_ENV_NOT_CLOSED(self);
3913 MYDB_BEGIN_ALLOW_THREADS;
3914 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3915 MYDB_END_ALLOW_THREADS;
3916 RETURN_IF_ERR();
3917 RETURN_NONE();
3918}
3919
3920static PyObject*
3921DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3922{
3923 int err;
3924 u_int32_t flags=0;
3925 char *file = NULL;
3926 char *database = NULL;
3927 char *newname = NULL;
3928 PyObject *txnobj = NULL;
3929 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003930 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003931 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003932
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003933 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003934 &file, &database, &newname, &txnobj, &flags)) {
3935 return NULL;
3936 }
3937 if (!checkTxnObj(txnobj, &txn)) {
3938 return NULL;
3939 }
3940 CHECK_ENV_NOT_CLOSED(self);
3941 MYDB_BEGIN_ALLOW_THREADS;
3942 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3943 flags);
3944 MYDB_END_ALLOW_THREADS;
3945 RETURN_IF_ERR();
3946 RETURN_NONE();
3947}
3948
3949static PyObject*
3950DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3951{
3952 int err;
3953 u_int32_t flags=0;
3954 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003955 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003956
3957 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3958 &passwd, &flags)) {
3959 return NULL;
3960 }
3961
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3964 MYDB_END_ALLOW_THREADS;
3965
3966 RETURN_IF_ERR();
3967 RETURN_NONE();
3968}
3969#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003970
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003971#if (DBVER >= 40)
3972static PyObject*
3973DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3974{
3975 int err;
3976 u_int32_t flags=0;
3977 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003978 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003979
3980 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3981 &timeout, &flags)) {
3982 return NULL;
3983 }
3984
3985 MYDB_BEGIN_ALLOW_THREADS;
3986 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3987 MYDB_END_ALLOW_THREADS;
3988
3989 RETURN_IF_ERR();
3990 RETURN_NONE();
3991}
3992#endif /* DBVER >= 40 */
3993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003994static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003995DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3996{
3997 int err;
3998 long shm_key = 0;
3999
4000 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4001 return NULL;
4002 CHECK_ENV_NOT_CLOSED(self);
4003
4004 err = self->db_env->set_shm_key(self->db_env, shm_key);
4005 RETURN_IF_ERR();
4006 RETURN_NONE();
4007}
4008
4009static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004010DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4011{
4012 int err, gbytes=0, bytes=0, ncache=0;
4013
4014 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4015 &gbytes, &bytes, &ncache))
4016 return NULL;
4017 CHECK_ENV_NOT_CLOSED(self);
4018
4019 MYDB_BEGIN_ALLOW_THREADS;
4020 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4021 MYDB_END_ALLOW_THREADS;
4022 RETURN_IF_ERR();
4023 RETURN_NONE();
4024}
4025
4026
4027#if (DBVER >= 32)
4028static PyObject*
4029DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4030{
4031 int err, flags=0, onoff=0;
4032
4033 if (!PyArg_ParseTuple(args, "ii:set_flags",
4034 &flags, &onoff))
4035 return NULL;
4036 CHECK_ENV_NOT_CLOSED(self);
4037
4038 MYDB_BEGIN_ALLOW_THREADS;
4039 err = self->db_env->set_flags(self->db_env, flags, onoff);
4040 MYDB_END_ALLOW_THREADS;
4041 RETURN_IF_ERR();
4042 RETURN_NONE();
4043}
4044#endif
4045
4046
4047static PyObject*
4048DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4049{
4050 int err;
4051 char *dir;
4052
4053 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4056
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_data_dir(self->db_env, dir);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063
4064
4065static PyObject*
4066DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4067{
4068 int err, lg_bsize;
4069
4070 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4071 return NULL;
4072 CHECK_ENV_NOT_CLOSED(self);
4073
4074 MYDB_BEGIN_ALLOW_THREADS;
4075 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4076 MYDB_END_ALLOW_THREADS;
4077 RETURN_IF_ERR();
4078 RETURN_NONE();
4079}
4080
4081
4082static PyObject*
4083DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4084{
4085 int err;
4086 char *dir;
4087
4088 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4089 return NULL;
4090 CHECK_ENV_NOT_CLOSED(self);
4091
4092 MYDB_BEGIN_ALLOW_THREADS;
4093 err = self->db_env->set_lg_dir(self->db_env, dir);
4094 MYDB_END_ALLOW_THREADS;
4095 RETURN_IF_ERR();
4096 RETURN_NONE();
4097}
4098
4099static PyObject*
4100DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4101{
4102 int err, lg_max;
4103
4104 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4105 return NULL;
4106 CHECK_ENV_NOT_CLOSED(self);
4107
4108 MYDB_BEGIN_ALLOW_THREADS;
4109 err = self->db_env->set_lg_max(self->db_env, lg_max);
4110 MYDB_END_ALLOW_THREADS;
4111 RETURN_IF_ERR();
4112 RETURN_NONE();
4113}
4114
4115
Neal Norwitz84562352005-10-20 04:30:15 +00004116#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004117static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004118DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4119{
4120 int err, lg_max;
4121
4122 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4123 return NULL;
4124 CHECK_ENV_NOT_CLOSED(self);
4125
4126 MYDB_BEGIN_ALLOW_THREADS;
4127 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4128 MYDB_END_ALLOW_THREADS;
4129 RETURN_IF_ERR();
4130 RETURN_NONE();
4131}
Neal Norwitz84562352005-10-20 04:30:15 +00004132#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004133
4134
4135static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004136DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4137{
4138 int err, lk_detect;
4139
4140 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4141 return NULL;
4142 CHECK_ENV_NOT_CLOSED(self);
4143
4144 MYDB_BEGIN_ALLOW_THREADS;
4145 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4146 MYDB_END_ALLOW_THREADS;
4147 RETURN_IF_ERR();
4148 RETURN_NONE();
4149}
4150
4151
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004152#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004153static PyObject*
4154DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4155{
4156 int err, max;
4157
4158 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4159 return NULL;
4160 CHECK_ENV_NOT_CLOSED(self);
4161
4162 MYDB_BEGIN_ALLOW_THREADS;
4163 err = self->db_env->set_lk_max(self->db_env, max);
4164 MYDB_END_ALLOW_THREADS;
4165 RETURN_IF_ERR();
4166 RETURN_NONE();
4167}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004168#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004169
4170
4171#if (DBVER >= 32)
4172
4173static PyObject*
4174DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4175{
4176 int err, max;
4177
4178 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4179 return NULL;
4180 CHECK_ENV_NOT_CLOSED(self);
4181
4182 MYDB_BEGIN_ALLOW_THREADS;
4183 err = self->db_env->set_lk_max_locks(self->db_env, max);
4184 MYDB_END_ALLOW_THREADS;
4185 RETURN_IF_ERR();
4186 RETURN_NONE();
4187}
4188
4189
4190static PyObject*
4191DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4192{
4193 int err, max;
4194
4195 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4196 return NULL;
4197 CHECK_ENV_NOT_CLOSED(self);
4198
4199 MYDB_BEGIN_ALLOW_THREADS;
4200 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4201 MYDB_END_ALLOW_THREADS;
4202 RETURN_IF_ERR();
4203 RETURN_NONE();
4204}
4205
4206
4207static PyObject*
4208DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4209{
4210 int err, max;
4211
4212 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4213 return NULL;
4214 CHECK_ENV_NOT_CLOSED(self);
4215
4216 MYDB_BEGIN_ALLOW_THREADS;
4217 err = self->db_env->set_lk_max_objects(self->db_env, max);
4218 MYDB_END_ALLOW_THREADS;
4219 RETURN_IF_ERR();
4220 RETURN_NONE();
4221}
4222
4223#endif
4224
4225
4226static PyObject*
4227DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4228{
4229 int err, mp_mmapsize;
4230
4231 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4232 return NULL;
4233 CHECK_ENV_NOT_CLOSED(self);
4234
4235 MYDB_BEGIN_ALLOW_THREADS;
4236 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4237 MYDB_END_ALLOW_THREADS;
4238 RETURN_IF_ERR();
4239 RETURN_NONE();
4240}
4241
4242
4243static PyObject*
4244DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4245{
4246 int err;
4247 char *dir;
4248
4249 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4250 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4252
4253 MYDB_BEGIN_ALLOW_THREADS;
4254 err = self->db_env->set_tmp_dir(self->db_env, dir);
4255 MYDB_END_ALLOW_THREADS;
4256 RETURN_IF_ERR();
4257 RETURN_NONE();
4258}
4259
4260
4261static PyObject*
4262DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4263{
4264 int flags = 0;
4265 PyObject* txnobj = NULL;
4266 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004267 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004268
4269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4270 &txnobj, &flags))
4271 return NULL;
4272
4273 if (!checkTxnObj(txnobj, &txn))
4274 return NULL;
4275 CHECK_ENV_NOT_CLOSED(self);
4276
4277 return (PyObject*)newDBTxnObject(self, txn, flags);
4278}
4279
4280
4281static PyObject*
4282DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4283{
4284 int err, kbyte=0, min=0, flags=0;
4285
4286 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4287 return NULL;
4288 CHECK_ENV_NOT_CLOSED(self);
4289
4290 MYDB_BEGIN_ALLOW_THREADS;
4291#if (DBVER >= 40)
4292 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4293#else
4294 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4295#endif
4296 MYDB_END_ALLOW_THREADS;
4297 RETURN_IF_ERR();
4298 RETURN_NONE();
4299}
4300
4301
4302static PyObject*
4303DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4304{
4305 int err, max;
4306
4307 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4308 return NULL;
4309 CHECK_ENV_NOT_CLOSED(self);
4310
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004311 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004312 RETURN_IF_ERR();
4313 RETURN_NONE();
4314}
4315
4316
4317static PyObject*
4318DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4319{
4320 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004321 long stamp;
4322 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004323
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004324 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004325 return NULL;
4326 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004327 timestamp = (time_t)stamp;
4328 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004329 RETURN_IF_ERR();
4330 RETURN_NONE();
4331}
4332
4333
4334static PyObject*
4335DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4336{
4337 int err, atype, flags=0;
4338 int aborted = 0;
4339
4340 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4341 return NULL;
4342 CHECK_ENV_NOT_CLOSED(self);
4343
4344 MYDB_BEGIN_ALLOW_THREADS;
4345#if (DBVER >= 40)
4346 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4347#else
4348 err = lock_detect(self->db_env, flags, atype, &aborted);
4349#endif
4350 MYDB_END_ALLOW_THREADS;
4351 RETURN_IF_ERR();
4352 return PyInt_FromLong(aborted);
4353}
4354
4355
4356static PyObject*
4357DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4358{
4359 int flags=0;
4360 int locker, lock_mode;
4361 DBT obj;
4362 PyObject* objobj;
4363
4364 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4365 return NULL;
4366
4367
4368 if (!make_dbt(objobj, &obj))
4369 return NULL;
4370
4371 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4372}
4373
4374
4375static PyObject*
4376DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4377{
4378 int err;
4379 u_int32_t theID;
4380
4381 if (!PyArg_ParseTuple(args, ":lock_id"))
4382 return NULL;
4383
4384 CHECK_ENV_NOT_CLOSED(self);
4385 MYDB_BEGIN_ALLOW_THREADS;
4386#if (DBVER >= 40)
4387 err = self->db_env->lock_id(self->db_env, &theID);
4388#else
4389 err = lock_id(self->db_env, &theID);
4390#endif
4391 MYDB_END_ALLOW_THREADS;
4392 RETURN_IF_ERR();
4393
4394 return PyInt_FromLong((long)theID);
4395}
4396
4397
4398static PyObject*
4399DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4400{
4401 int err;
4402 DBLockObject* dblockobj;
4403
4404 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4405 return NULL;
4406
4407 CHECK_ENV_NOT_CLOSED(self);
4408 MYDB_BEGIN_ALLOW_THREADS;
4409#if (DBVER >= 40)
4410 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4411#else
4412 err = lock_put(self->db_env, &dblockobj->lock);
4413#endif
4414 MYDB_END_ALLOW_THREADS;
4415 RETURN_IF_ERR();
4416 RETURN_NONE();
4417}
4418
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004419#if (DBVER >= 44)
4420static PyObject*
4421DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4422{
4423 int err;
4424 char *file;
4425 u_int32_t flags = 0;
4426 static char* kwnames[] = { "file", "flags", NULL};
4427
4428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4429 &file, &flags))
4430 return NULL;
4431 CHECK_ENV_NOT_CLOSED(self);
4432
4433 MYDB_BEGIN_ALLOW_THREADS;
4434 err = self->db_env->lsn_reset(self->db_env, file, flags);
4435 MYDB_END_ALLOW_THREADS;
4436 RETURN_IF_ERR();
4437 RETURN_NONE();
4438}
4439#endif /* DBVER >= 4.4 */
4440
4441#if (DBVER >= 40)
4442static PyObject*
4443DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4444{
4445 int err;
4446 DB_LOG_STAT* statp = NULL;
4447 PyObject* d = NULL;
4448 u_int32_t flags = 0;
4449
4450 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4451 return NULL;
4452 CHECK_ENV_NOT_CLOSED(self);
4453
4454 MYDB_BEGIN_ALLOW_THREADS;
4455 err = self->db_env->log_stat(self->db_env, &statp, flags);
4456 MYDB_END_ALLOW_THREADS;
4457 RETURN_IF_ERR();
4458
4459 /* Turn the stat structure into a dictionary */
4460 d = PyDict_New();
4461 if (d == NULL) {
4462 if (statp)
4463 free(statp);
4464 return NULL;
4465 }
4466
4467#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4468
4469 MAKE_ENTRY(magic);
4470 MAKE_ENTRY(version);
4471 MAKE_ENTRY(mode);
4472 MAKE_ENTRY(lg_bsize);
4473#if (DBVER >= 44)
4474 MAKE_ENTRY(lg_size);
4475 MAKE_ENTRY(record);
4476#endif
4477#if (DBVER <= 40)
4478 MAKE_ENTRY(lg_max);
4479#endif
4480 MAKE_ENTRY(w_mbytes);
4481 MAKE_ENTRY(w_bytes);
4482 MAKE_ENTRY(wc_mbytes);
4483 MAKE_ENTRY(wc_bytes);
4484 MAKE_ENTRY(wcount);
4485 MAKE_ENTRY(wcount_fill);
4486#if (DBVER >= 44)
4487 MAKE_ENTRY(rcount);
4488#endif
4489 MAKE_ENTRY(scount);
4490 MAKE_ENTRY(cur_file);
4491 MAKE_ENTRY(cur_offset);
4492 MAKE_ENTRY(disk_file);
4493 MAKE_ENTRY(disk_offset);
4494 MAKE_ENTRY(maxcommitperflush);
4495 MAKE_ENTRY(mincommitperflush);
4496 MAKE_ENTRY(regsize);
4497 MAKE_ENTRY(region_wait);
4498 MAKE_ENTRY(region_nowait);
4499
4500#undef MAKE_ENTRY
4501 free(statp);
4502 return d;
4503} /* DBEnv_log_stat */
4504#endif /* DBVER >= 4.0 for log_stat method */
4505
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004506
4507static PyObject*
4508DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4509{
4510 int err;
4511 DB_LOCK_STAT* sp;
4512 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004513 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004514
4515 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4516 return NULL;
4517 CHECK_ENV_NOT_CLOSED(self);
4518
4519 MYDB_BEGIN_ALLOW_THREADS;
4520#if (DBVER >= 40)
4521 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4522#else
4523#if (DBVER >= 33)
4524 err = lock_stat(self->db_env, &sp);
4525#else
4526 err = lock_stat(self->db_env, &sp, NULL);
4527#endif
4528#endif
4529 MYDB_END_ALLOW_THREADS;
4530 RETURN_IF_ERR();
4531
4532 /* Turn the stat structure into a dictionary */
4533 d = PyDict_New();
4534 if (d == NULL) {
4535 free(sp);
4536 return NULL;
4537 }
4538
4539#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4540
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004541#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004542 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004543#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004544 MAKE_ENTRY(nmodes);
4545#if (DBVER >= 32)
4546 MAKE_ENTRY(maxlocks);
4547 MAKE_ENTRY(maxlockers);
4548 MAKE_ENTRY(maxobjects);
4549 MAKE_ENTRY(nlocks);
4550 MAKE_ENTRY(maxnlocks);
4551#endif
4552 MAKE_ENTRY(nlockers);
4553 MAKE_ENTRY(maxnlockers);
4554#if (DBVER >= 32)
4555 MAKE_ENTRY(nobjects);
4556 MAKE_ENTRY(maxnobjects);
4557#endif
4558 MAKE_ENTRY(nrequests);
4559 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004560#if (DBVER < 44)
4561 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004563#else
4564 MAKE_ENTRY(lock_nowait);
4565 MAKE_ENTRY(lock_wait);
4566#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004567 MAKE_ENTRY(ndeadlocks);
4568 MAKE_ENTRY(regsize);
4569 MAKE_ENTRY(region_wait);
4570 MAKE_ENTRY(region_nowait);
4571
4572#undef MAKE_ENTRY
4573 free(sp);
4574 return d;
4575}
4576
4577
4578static PyObject*
4579DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4580{
4581 int flags=0;
4582 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004583 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584 PyObject* list;
4585 PyObject* item = NULL;
4586
4587 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4588 return NULL;
4589
4590 CHECK_ENV_NOT_CLOSED(self);
4591 MYDB_BEGIN_ALLOW_THREADS;
4592#if (DBVER >= 40)
4593 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4594#elif (DBVER == 33)
4595 err = log_archive(self->db_env, &log_list, flags);
4596#else
4597 err = log_archive(self->db_env, &log_list, flags, NULL);
4598#endif
4599 MYDB_END_ALLOW_THREADS;
4600 RETURN_IF_ERR();
4601
4602 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004603 if (list == NULL) {
4604 if (log_list)
4605 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004607 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608
4609 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004610 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004611 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004612 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613 if (item == NULL) {
4614 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615 list = NULL;
4616 break;
4617 }
4618 PyList_Append(list, item);
4619 Py_DECREF(item);
4620 }
4621 free(log_list_start);
4622 }
4623 return list;
4624}
4625
4626
4627static PyObject*
4628DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4629{
4630 int err;
4631 DB_TXN_STAT* sp;
4632 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004633 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004634
4635 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4636 return NULL;
4637 CHECK_ENV_NOT_CLOSED(self);
4638
4639 MYDB_BEGIN_ALLOW_THREADS;
4640#if (DBVER >= 40)
4641 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4642#elif (DBVER == 33)
4643 err = txn_stat(self->db_env, &sp);
4644#else
4645 err = txn_stat(self->db_env, &sp, NULL);
4646#endif
4647 MYDB_END_ALLOW_THREADS;
4648 RETURN_IF_ERR();
4649
4650 /* Turn the stat structure into a dictionary */
4651 d = PyDict_New();
4652 if (d == NULL) {
4653 free(sp);
4654 return NULL;
4655 }
4656
4657#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004658#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004659
Guido van Rossumd8faa362007-04-27 19:54:29 +00004660 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661 MAKE_ENTRY(last_txnid);
4662 MAKE_ENTRY(maxtxns);
4663 MAKE_ENTRY(nactive);
4664 MAKE_ENTRY(maxnactive);
4665 MAKE_ENTRY(nbegins);
4666 MAKE_ENTRY(naborts);
4667 MAKE_ENTRY(ncommits);
4668 MAKE_ENTRY(regsize);
4669 MAKE_ENTRY(region_wait);
4670 MAKE_ENTRY(region_nowait);
4671
4672#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004673#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004674 free(sp);
4675 return d;
4676}
4677
4678
4679static PyObject*
4680DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4681{
4682 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004683 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684
4685 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4686 return NULL;
4687 CHECK_ENV_NOT_CLOSED(self);
4688
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004689 if (self->moduleFlags.getReturnsNone)
4690 ++oldValue;
4691 if (self->moduleFlags.cursorSetReturnsNone)
4692 ++oldValue;
4693 self->moduleFlags.getReturnsNone = (flags >= 1);
4694 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004695 return PyInt_FromLong(oldValue);
4696}
4697
4698
4699/* --------------------------------------------------------------------- */
4700/* DBTxn methods */
4701
4702
4703static PyObject*
4704DBTxn_commit(DBTxnObject* self, PyObject* args)
4705{
4706 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004707 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004708
4709 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4710 return NULL;
4711
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004712 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004713 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4714 "after txn_commit or txn_abort");
4715 PyErr_SetObject(DBError, t);
4716 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004717 return NULL;
4718 }
4719 txn = self->txn;
4720 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004721 MYDB_BEGIN_ALLOW_THREADS;
4722#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004723 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004725 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004726#endif
4727 MYDB_END_ALLOW_THREADS;
4728 RETURN_IF_ERR();
4729 RETURN_NONE();
4730}
4731
4732static PyObject*
4733DBTxn_prepare(DBTxnObject* self, PyObject* args)
4734{
4735#if (DBVER >= 33)
4736 int err;
4737 char* gid=NULL;
4738 int gid_size=0;
4739
4740 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4741 return NULL;
4742
4743 if (gid_size != DB_XIDDATASIZE) {
4744 PyErr_SetString(PyExc_TypeError,
4745 "gid must be DB_XIDDATASIZE bytes long");
4746 return NULL;
4747 }
4748
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004749 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004750 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4751 "after txn_commit or txn_abort");
4752 PyErr_SetObject(DBError, t);
4753 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004754 return NULL;
4755 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004756 MYDB_BEGIN_ALLOW_THREADS;
4757#if (DBVER >= 40)
4758 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4759#else
4760 err = txn_prepare(self->txn, (u_int8_t*)gid);
4761#endif
4762 MYDB_END_ALLOW_THREADS;
4763 RETURN_IF_ERR();
4764 RETURN_NONE();
4765#else
4766 int err;
4767
4768 if (!PyArg_ParseTuple(args, ":prepare"))
4769 return NULL;
4770
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004771 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004772 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4773 "after txn_commit or txn_abort");
4774 PyErr_SetObject(DBError, t);
4775 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004776 return NULL;
4777 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004778 MYDB_BEGIN_ALLOW_THREADS;
4779 err = txn_prepare(self->txn);
4780 MYDB_END_ALLOW_THREADS;
4781 RETURN_IF_ERR();
4782 RETURN_NONE();
4783#endif
4784}
4785
4786
4787static PyObject*
4788DBTxn_abort(DBTxnObject* self, PyObject* args)
4789{
4790 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004791 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004792
4793 if (!PyArg_ParseTuple(args, ":abort"))
4794 return NULL;
4795
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004796 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004797 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4798 "after txn_commit or txn_abort");
4799 PyErr_SetObject(DBError, t);
4800 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004801 return NULL;
4802 }
4803 txn = self->txn;
4804 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004805 MYDB_BEGIN_ALLOW_THREADS;
4806#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004807 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004809 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004810#endif
4811 MYDB_END_ALLOW_THREADS;
4812 RETURN_IF_ERR();
4813 RETURN_NONE();
4814}
4815
4816
4817static PyObject*
4818DBTxn_id(DBTxnObject* self, PyObject* args)
4819{
4820 int id;
4821
4822 if (!PyArg_ParseTuple(args, ":id"))
4823 return NULL;
4824
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004825 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004826 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4827 "after txn_commit or txn_abort");
4828 PyErr_SetObject(DBError, t);
4829 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004830 return NULL;
4831 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004832 MYDB_BEGIN_ALLOW_THREADS;
4833#if (DBVER >= 40)
4834 id = self->txn->id(self->txn);
4835#else
4836 id = txn_id(self->txn);
4837#endif
4838 MYDB_END_ALLOW_THREADS;
4839 return PyInt_FromLong(id);
4840}
4841
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004842#if (DBVER >= 43)
4843/* --------------------------------------------------------------------- */
4844/* DBSequence methods */
4845
4846
4847static PyObject*
4848DBSequence_close(DBSequenceObject* self, PyObject* args)
4849{
4850 int err, flags=0;
4851 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4852 return NULL;
4853 CHECK_SEQUENCE_NOT_CLOSED(self)
4854
4855 MYDB_BEGIN_ALLOW_THREADS
4856 err = self->sequence->close(self->sequence, flags);
4857 self->sequence = NULL;
4858 MYDB_END_ALLOW_THREADS
4859
4860 RETURN_IF_ERR();
4861
4862 RETURN_NONE();
4863}
4864
4865static PyObject*
4866DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4867{
4868 int err, flags = 0;
4869 int delta = 1;
4870 db_seq_t value;
4871 PyObject *txnobj = NULL;
4872 DB_TXN *txn = NULL;
4873 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4874 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4875 return NULL;
4876 CHECK_SEQUENCE_NOT_CLOSED(self)
4877
4878 if (!checkTxnObj(txnobj, &txn))
4879 return NULL;
4880
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4883 MYDB_END_ALLOW_THREADS
4884
4885 RETURN_IF_ERR();
4886 return PyLong_FromLongLong(value);
4887
4888}
4889
4890static PyObject*
4891DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4892{
4893 if (!PyArg_ParseTuple(args,":get_dbp"))
4894 return NULL;
4895 CHECK_SEQUENCE_NOT_CLOSED(self)
4896 Py_INCREF(self->mydb);
4897 return (PyObject* )self->mydb;
4898}
4899
4900static PyObject*
4901DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4902{
4903 int err;
4904 DBT key;
4905 CHECK_SEQUENCE_NOT_CLOSED(self)
4906 MYDB_BEGIN_ALLOW_THREADS
4907 err = self->sequence->get_key(self->sequence, &key);
4908 MYDB_END_ALLOW_THREADS
4909
4910 RETURN_IF_ERR();
4911
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004912 return PyBytes_FromStringAndSize(key.data, key.size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004913}
4914
4915static PyObject*
4916DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4917{
4918 int err;
4919 db_seq_t value;
4920 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4921 return NULL;
4922 CHECK_SEQUENCE_NOT_CLOSED(self)
4923
4924 MYDB_BEGIN_ALLOW_THREADS
4925 err = self->sequence->initial_value(self->sequence, value);
4926 MYDB_END_ALLOW_THREADS
4927
4928 RETURN_IF_ERR();
4929
4930 RETURN_NONE();
4931}
4932
4933static PyObject*
4934DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4935{
4936 int err, flags = 0;
4937 PyObject* keyobj;
4938 PyObject *txnobj = NULL;
4939 DB_TXN *txn = NULL;
4940 DBT key;
4941
4942 static char* kwnames[] = {"key", "txn", "flags", NULL };
4943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4944 return NULL;
4945
4946 if (!checkTxnObj(txnobj, &txn))
4947 return NULL;
4948
4949 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4950 return NULL;
4951
4952 MYDB_BEGIN_ALLOW_THREADS
4953 err = self->sequence->open(self->sequence, txn, &key, flags);
4954 MYDB_END_ALLOW_THREADS
4955
4956 CLEAR_DBT(key);
4957 RETURN_IF_ERR();
4958
4959 RETURN_NONE();
4960}
4961
4962static PyObject*
4963DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4964{
4965 int err, flags = 0;
4966 PyObject *txnobj = NULL;
4967 DB_TXN *txn = NULL;
4968
4969 static char* kwnames[] = {"txn", "flags", NULL };
4970 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4971 return NULL;
4972
4973 if (!checkTxnObj(txnobj, &txn))
4974 return NULL;
4975
4976 CHECK_SEQUENCE_NOT_CLOSED(self)
4977
4978 MYDB_BEGIN_ALLOW_THREADS
4979 err = self->sequence->remove(self->sequence, txn, flags);
4980 MYDB_END_ALLOW_THREADS
4981
4982 RETURN_IF_ERR();
4983 RETURN_NONE();
4984}
4985
4986static PyObject*
4987DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4988{
4989 int err, size;
4990 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4991 return NULL;
4992 CHECK_SEQUENCE_NOT_CLOSED(self)
4993
4994 MYDB_BEGIN_ALLOW_THREADS
4995 err = self->sequence->set_cachesize(self->sequence, size);
4996 MYDB_END_ALLOW_THREADS
4997
4998 RETURN_IF_ERR();
4999 RETURN_NONE();
5000}
5001
5002static PyObject*
5003DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5004{
5005 int err, size;
5006 if (!PyArg_ParseTuple(args,":get_cachesize"))
5007 return NULL;
5008 CHECK_SEQUENCE_NOT_CLOSED(self)
5009
5010 MYDB_BEGIN_ALLOW_THREADS
5011 err = self->sequence->get_cachesize(self->sequence, &size);
5012 MYDB_END_ALLOW_THREADS
5013
5014 RETURN_IF_ERR();
5015 return PyInt_FromLong(size);
5016}
5017
5018static PyObject*
5019DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5020{
5021 int err, flags = 0;
5022 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5023 return NULL;
5024 CHECK_SEQUENCE_NOT_CLOSED(self)
5025
5026 MYDB_BEGIN_ALLOW_THREADS
5027 err = self->sequence->set_flags(self->sequence, flags);
5028 MYDB_END_ALLOW_THREADS
5029
5030 RETURN_IF_ERR();
5031 RETURN_NONE();
5032
5033}
5034
5035static PyObject*
5036DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5037{
5038 unsigned int flags;
5039 int err;
5040 if (!PyArg_ParseTuple(args,":get_flags"))
5041 return NULL;
5042 CHECK_SEQUENCE_NOT_CLOSED(self)
5043
5044 MYDB_BEGIN_ALLOW_THREADS
5045 err = self->sequence->get_flags(self->sequence, &flags);
5046 MYDB_END_ALLOW_THREADS
5047
5048 RETURN_IF_ERR();
5049 return PyInt_FromLong((int)flags);
5050}
5051
5052static PyObject*
5053DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5054{
5055 int err;
5056 db_seq_t min, max;
5057 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5058 return NULL;
5059 CHECK_SEQUENCE_NOT_CLOSED(self)
5060
5061 MYDB_BEGIN_ALLOW_THREADS
5062 err = self->sequence->set_range(self->sequence, min, max);
5063 MYDB_END_ALLOW_THREADS
5064
5065 RETURN_IF_ERR();
5066 RETURN_NONE();
5067}
5068
5069static PyObject*
5070DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5071{
5072 int err;
5073 db_seq_t min, max;
5074 if (!PyArg_ParseTuple(args,":get_range"))
5075 return NULL;
5076 CHECK_SEQUENCE_NOT_CLOSED(self)
5077
5078 MYDB_BEGIN_ALLOW_THREADS
5079 err = self->sequence->get_range(self->sequence, &min, &max);
5080 MYDB_END_ALLOW_THREADS
5081
5082 RETURN_IF_ERR();
5083 return Py_BuildValue("(LL)", min, max);
5084}
5085
5086static PyObject*
5087DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5088{
5089 int err, flags = 0;
5090 DB_SEQUENCE_STAT* sp = NULL;
5091 PyObject* dict_stat;
5092 static char* kwnames[] = {"flags", NULL };
5093 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5094 return NULL;
5095 CHECK_SEQUENCE_NOT_CLOSED(self);
5096
5097 MYDB_BEGIN_ALLOW_THREADS;
5098 err = self->sequence->stat(self->sequence, &sp, flags);
5099 MYDB_END_ALLOW_THREADS;
5100 RETURN_IF_ERR();
5101
5102 if ((dict_stat = PyDict_New()) == NULL) {
5103 free(sp);
5104 return NULL;
5105 }
5106
5107
5108#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5109#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5110
5111 MAKE_INT_ENTRY(wait);
5112 MAKE_INT_ENTRY(nowait);
5113 MAKE_LONG_LONG_ENTRY(current);
5114 MAKE_LONG_LONG_ENTRY(value);
5115 MAKE_LONG_LONG_ENTRY(last_value);
5116 MAKE_LONG_LONG_ENTRY(min);
5117 MAKE_LONG_LONG_ENTRY(max);
5118 MAKE_INT_ENTRY(cache_size);
5119 MAKE_INT_ENTRY(flags);
5120
5121#undef MAKE_INT_ENTRY
5122#undef MAKE_LONG_LONG_ENTRY
5123
5124 free(sp);
5125 return dict_stat;
5126}
5127#endif
5128
5129
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005130/* --------------------------------------------------------------------- */
5131/* Method definition tables and type objects */
5132
5133static PyMethodDef DB_methods[] = {
5134 {"append", (PyCFunction)DB_append, METH_VARARGS},
5135#if (DBVER >= 33)
5136 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5137#endif
5138 {"close", (PyCFunction)DB_close, METH_VARARGS},
5139#if (DBVER >= 32)
5140 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5141 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5142#endif
5143 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5144 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5145 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5146 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005147#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005148 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005149#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5151 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5152 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5153 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5154 {"join", (PyCFunction)DB_join, METH_VARARGS},
5155 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5156 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5157 {"items", (PyCFunction)DB_items, METH_VARARGS},
5158 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5159 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5160 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5161 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5162 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5163 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005164#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005165 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005166#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005167 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005168#if (DBVER >= 41)
5169 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5170#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005171 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5172 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5173 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5174 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5175 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5176 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5177 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5178 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5179 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5180#if (DBVER >= 32)
5181 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5182#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005183 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005184 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5185#if (DBVER >= 33)
5186 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5187#endif
5188 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5189 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5190 {"values", (PyCFunction)DB_values, METH_VARARGS},
5191 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5192 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5193 {NULL, NULL} /* sentinel */
5194};
5195
5196
5197static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005198 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005199 (binaryfunc)DB_subscript, /*mp_subscript*/
5200 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5201};
5202
5203
5204static PyMethodDef DBCursor_methods[] = {
5205 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5206 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5207 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5208 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5209 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5210 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5211 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005212#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005213 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005214#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005215 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5216 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5217 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5218 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5219 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5220 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5221 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5222 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005223 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005224 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005225 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5226 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5227 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5228 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5229 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5230 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5231 {NULL, NULL} /* sentinel */
5232};
5233
5234
5235static PyMethodDef DBEnv_methods[] = {
5236 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5237 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5238 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005239#if (DBVER >= 41)
5240 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5241 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5242 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5243#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005244#if (DBVER >= 40)
5245 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5246#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005247 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005248 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5249 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5250#if (DBVER >= 32)
5251 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5252#endif
5253 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5254 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5255 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005256#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005257 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005260#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005261 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005263#if (DBVER >= 32)
5264 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5265 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5266 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5267#endif
5268 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5269 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5270 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5271 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5272 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5273 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005274 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005275 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5276 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5277 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5278 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5279 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5280 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005281#if (DBVER >= 40)
5282 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5283#endif
5284#if (DBVER >= 44)
5285 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005287 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5288 {NULL, NULL} /* sentinel */
5289};
5290
5291
5292static PyMethodDef DBTxn_methods[] = {
5293 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5294 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5295 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5296 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5297 {NULL, NULL} /* sentinel */
5298};
5299
5300
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005301#if (DBVER >= 43)
5302static PyMethodDef DBSequence_methods[] = {
5303 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5304 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5305 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5306 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5307 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5308 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5309 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5310 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5311 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5312 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5313 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5314 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5315 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5316 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5317 {NULL, NULL} /* sentinel */
5318};
5319#endif
5320
5321
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005322static PyObject*
5323DB_getattr(DBObject* self, char *name)
5324{
5325 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5326}
5327
5328
5329static PyObject*
5330DBEnv_getattr(DBEnvObject* self, char *name)
5331{
5332 if (!strcmp(name, "db_home")) {
5333 CHECK_ENV_NOT_CLOSED(self);
5334 if (self->db_env->db_home == NULL) {
5335 RETURN_NONE();
5336 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005337 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005338 }
5339
5340 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5341}
5342
5343
5344static PyObject*
5345DBCursor_getattr(DBCursorObject* self, char *name)
5346{
5347 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5348}
5349
5350static PyObject*
5351DBTxn_getattr(DBTxnObject* self, char *name)
5352{
5353 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5354}
5355
5356static PyObject*
5357DBLock_getattr(DBLockObject* self, char *name)
5358{
5359 return NULL;
5360}
5361
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005362#if (DBVER >= 43)
5363static PyObject*
5364DBSequence_getattr(DBSequenceObject* self, char *name)
5365{
5366 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5367}
5368#endif
5369
Neal Norwitz227b5332006-03-22 09:28:35 +00005370static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005371 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005372 "DB", /*tp_name*/
5373 sizeof(DBObject), /*tp_basicsize*/
5374 0, /*tp_itemsize*/
5375 /* methods */
5376 (destructor)DB_dealloc, /*tp_dealloc*/
5377 0, /*tp_print*/
5378 (getattrfunc)DB_getattr, /*tp_getattr*/
5379 0, /*tp_setattr*/
5380 0, /*tp_compare*/
5381 0, /*tp_repr*/
5382 0, /*tp_as_number*/
5383 0, /*tp_as_sequence*/
5384 &DB_mapping,/*tp_as_mapping*/
5385 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005386#ifdef HAVE_WEAKREF
5387 0, /* tp_call */
5388 0, /* tp_str */
5389 0, /* tp_getattro */
5390 0, /* tp_setattro */
5391 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005392 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005393 0, /* tp_doc */
5394 0, /* tp_traverse */
5395 0, /* tp_clear */
5396 0, /* tp_richcompare */
5397 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5398#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005399};
5400
5401
Neal Norwitz227b5332006-03-22 09:28:35 +00005402static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005403 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005404 "DBCursor", /*tp_name*/
5405 sizeof(DBCursorObject), /*tp_basicsize*/
5406 0, /*tp_itemsize*/
5407 /* methods */
5408 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5409 0, /*tp_print*/
5410 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5411 0, /*tp_setattr*/
5412 0, /*tp_compare*/
5413 0, /*tp_repr*/
5414 0, /*tp_as_number*/
5415 0, /*tp_as_sequence*/
5416 0, /*tp_as_mapping*/
5417 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005418#ifdef HAVE_WEAKREF
5419 0, /* tp_call */
5420 0, /* tp_str */
5421 0, /* tp_getattro */
5422 0, /* tp_setattro */
5423 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005424 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005425 0, /* tp_doc */
5426 0, /* tp_traverse */
5427 0, /* tp_clear */
5428 0, /* tp_richcompare */
5429 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5430#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005431};
5432
5433
Neal Norwitz227b5332006-03-22 09:28:35 +00005434static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005435 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005436 "DBEnv", /*tp_name*/
5437 sizeof(DBEnvObject), /*tp_basicsize*/
5438 0, /*tp_itemsize*/
5439 /* methods */
5440 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5441 0, /*tp_print*/
5442 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5443 0, /*tp_setattr*/
5444 0, /*tp_compare*/
5445 0, /*tp_repr*/
5446 0, /*tp_as_number*/
5447 0, /*tp_as_sequence*/
5448 0, /*tp_as_mapping*/
5449 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005450#ifdef HAVE_WEAKREF
5451 0, /* tp_call */
5452 0, /* tp_str */
5453 0, /* tp_getattro */
5454 0, /* tp_setattro */
5455 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005456 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005457 0, /* tp_doc */
5458 0, /* tp_traverse */
5459 0, /* tp_clear */
5460 0, /* tp_richcompare */
5461 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5462#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005463};
5464
Neal Norwitz227b5332006-03-22 09:28:35 +00005465static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005466 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005467 "DBTxn", /*tp_name*/
5468 sizeof(DBTxnObject), /*tp_basicsize*/
5469 0, /*tp_itemsize*/
5470 /* methods */
5471 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5472 0, /*tp_print*/
5473 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5474 0, /*tp_setattr*/
5475 0, /*tp_compare*/
5476 0, /*tp_repr*/
5477 0, /*tp_as_number*/
5478 0, /*tp_as_sequence*/
5479 0, /*tp_as_mapping*/
5480 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005481#ifdef HAVE_WEAKREF
5482 0, /* tp_call */
5483 0, /* tp_str */
5484 0, /* tp_getattro */
5485 0, /* tp_setattro */
5486 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005487 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005488 0, /* tp_doc */
5489 0, /* tp_traverse */
5490 0, /* tp_clear */
5491 0, /* tp_richcompare */
5492 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5493#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005494};
5495
5496
Neal Norwitz227b5332006-03-22 09:28:35 +00005497static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005498 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499 "DBLock", /*tp_name*/
5500 sizeof(DBLockObject), /*tp_basicsize*/
5501 0, /*tp_itemsize*/
5502 /* methods */
5503 (destructor)DBLock_dealloc, /*tp_dealloc*/
5504 0, /*tp_print*/
5505 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5506 0, /*tp_setattr*/
5507 0, /*tp_compare*/
5508 0, /*tp_repr*/
5509 0, /*tp_as_number*/
5510 0, /*tp_as_sequence*/
5511 0, /*tp_as_mapping*/
5512 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005513#ifdef HAVE_WEAKREF
5514 0, /* tp_call */
5515 0, /* tp_str */
5516 0, /* tp_getattro */
5517 0, /* tp_setattro */
5518 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005519 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005520 0, /* tp_doc */
5521 0, /* tp_traverse */
5522 0, /* tp_clear */
5523 0, /* tp_richcompare */
5524 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5525#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005526};
5527
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005528#if (DBVER >= 43)
5529static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005530 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005531 "DBSequence", /*tp_name*/
5532 sizeof(DBSequenceObject), /*tp_basicsize*/
5533 0, /*tp_itemsize*/
5534 /* methods */
5535 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5536 0, /*tp_print*/
5537 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5538 0, /*tp_setattr*/
5539 0, /*tp_compare*/
5540 0, /*tp_repr*/
5541 0, /*tp_as_number*/
5542 0, /*tp_as_sequence*/
5543 0, /*tp_as_mapping*/
5544 0, /*tp_hash*/
5545#ifdef HAVE_WEAKREF
5546 0, /* tp_call */
5547 0, /* tp_str */
5548 0, /* tp_getattro */
5549 0, /* tp_setattro */
5550 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005551 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005552 0, /* tp_doc */
5553 0, /* tp_traverse */
5554 0, /* tp_clear */
5555 0, /* tp_richcompare */
5556 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5557#endif
5558};
5559#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005560
5561/* --------------------------------------------------------------------- */
5562/* Module-level functions */
5563
5564static PyObject*
5565DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5566{
5567 PyObject* dbenvobj = NULL;
5568 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005569 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005570
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005571 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5572 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005573 return NULL;
5574 if (dbenvobj == Py_None)
5575 dbenvobj = NULL;
5576 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5577 makeTypeError("DBEnv", dbenvobj);
5578 return NULL;
5579 }
5580
5581 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5582}
5583
5584
5585static PyObject*
5586DBEnv_construct(PyObject* self, PyObject* args)
5587{
5588 int flags = 0;
5589 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5590 return (PyObject* )newDBEnvObject(flags);
5591}
5592
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005593#if (DBVER >= 43)
5594static PyObject*
5595DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5596{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005597 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005598 int flags = 0;
5599 static char* kwnames[] = { "db", "flags", NULL};
5600
5601 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5602 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005603 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005604 makeTypeError("DB", dbobj);
5605 return NULL;
5606 }
5607 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5608}
5609#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005610
5611static char bsddb_version_doc[] =
5612"Returns a tuple of major, minor, and patch release numbers of the\n\
5613underlying DB library.";
5614
5615static PyObject*
5616bsddb_version(PyObject* self, PyObject* args)
5617{
5618 int major, minor, patch;
5619
5620 if (!PyArg_ParseTuple(args, ":version"))
5621 return NULL;
5622 db_version(&major, &minor, &patch);
5623 return Py_BuildValue("(iii)", major, minor, patch);
5624}
5625
5626
5627/* List of functions defined in the module */
5628
5629static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005630 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5631 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5632#if (DBVER >= 43)
5633 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5634#endif
5635 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005636 {NULL, NULL} /* sentinel */
5637};
5638
5639
5640/* --------------------------------------------------------------------- */
5641/* Module initialization */
5642
5643
5644/* Convenience routine to export an integer value.
5645 * Errors are silently ignored, for better or for worse...
5646 */
5647#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5648
Gregory P. Smith41631e82003-09-21 00:08:14 +00005649#define MODULE_NAME_MAX_LEN 11
5650static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005651
Neal Norwitzf6657e62006-12-28 04:47:50 +00005652PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653{
5654 PyObject* m;
5655 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005656 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5657 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5658 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005659
5660 /* Initialize the type of the new type objects here; doing it here
5661 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005662 Py_Type(&DB_Type) = &PyType_Type;
5663 Py_Type(&DBCursor_Type) = &PyType_Type;
5664 Py_Type(&DBEnv_Type) = &PyType_Type;
5665 Py_Type(&DBTxn_Type) = &PyType_Type;
5666 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005667#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005668 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005669#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005670
5671
Mark Hammonda69d4092003-04-22 23:13:27 +00005672#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005674 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675#endif
5676
5677 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005678 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005679 if (m == NULL)
5680 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005681
5682 /* Add some symbolic constants to the module */
5683 d = PyModule_GetDict(m);
5684 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005685 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005686 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5687 Py_DECREF(pybsddb_version_s);
5688 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005689 Py_DECREF(svnid_s);
5690 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005691 Py_DECREF(db_version_s);
5692 db_version_s = NULL;
5693
5694 ADD_INT(d, DB_VERSION_MAJOR);
5695 ADD_INT(d, DB_VERSION_MINOR);
5696 ADD_INT(d, DB_VERSION_PATCH);
5697
5698 ADD_INT(d, DB_MAX_PAGES);
5699 ADD_INT(d, DB_MAX_RECORDS);
5700
Gregory P. Smith41631e82003-09-21 00:08:14 +00005701#if (DBVER >= 42)
5702 ADD_INT(d, DB_RPCCLIENT);
5703#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005704 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005705 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5706 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5707#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005708 ADD_INT(d, DB_XA_CREATE);
5709
5710 ADD_INT(d, DB_CREATE);
5711 ADD_INT(d, DB_NOMMAP);
5712 ADD_INT(d, DB_THREAD);
5713
5714 ADD_INT(d, DB_FORCE);
5715 ADD_INT(d, DB_INIT_CDB);
5716 ADD_INT(d, DB_INIT_LOCK);
5717 ADD_INT(d, DB_INIT_LOG);
5718 ADD_INT(d, DB_INIT_MPOOL);
5719 ADD_INT(d, DB_INIT_TXN);
5720#if (DBVER >= 32)
5721 ADD_INT(d, DB_JOINENV);
5722#endif
5723
5724 ADD_INT(d, DB_RECOVER);
5725 ADD_INT(d, DB_RECOVER_FATAL);
5726 ADD_INT(d, DB_TXN_NOSYNC);
5727 ADD_INT(d, DB_USE_ENVIRON);
5728 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5729
5730 ADD_INT(d, DB_LOCKDOWN);
5731 ADD_INT(d, DB_PRIVATE);
5732 ADD_INT(d, DB_SYSTEM_MEM);
5733
5734 ADD_INT(d, DB_TXN_SYNC);
5735 ADD_INT(d, DB_TXN_NOWAIT);
5736
5737 ADD_INT(d, DB_EXCL);
5738 ADD_INT(d, DB_FCNTL_LOCKING);
5739 ADD_INT(d, DB_ODDFILESIZE);
5740 ADD_INT(d, DB_RDWRMASTER);
5741 ADD_INT(d, DB_RDONLY);
5742 ADD_INT(d, DB_TRUNCATE);
5743#if (DBVER >= 32)
5744 ADD_INT(d, DB_EXTENT);
5745 ADD_INT(d, DB_CDB_ALLDB);
5746 ADD_INT(d, DB_VERIFY);
5747#endif
5748 ADD_INT(d, DB_UPGRADE);
5749
5750 ADD_INT(d, DB_AGGRESSIVE);
5751 ADD_INT(d, DB_NOORDERCHK);
5752 ADD_INT(d, DB_ORDERCHKONLY);
5753 ADD_INT(d, DB_PR_PAGE);
5754#if ! (DBVER >= 33)
5755 ADD_INT(d, DB_VRFY_FLAGMASK);
5756 ADD_INT(d, DB_PR_HEADERS);
5757#endif
5758 ADD_INT(d, DB_PR_RECOVERYTEST);
5759 ADD_INT(d, DB_SALVAGE);
5760
5761 ADD_INT(d, DB_LOCK_NORUN);
5762 ADD_INT(d, DB_LOCK_DEFAULT);
5763 ADD_INT(d, DB_LOCK_OLDEST);
5764 ADD_INT(d, DB_LOCK_RANDOM);
5765 ADD_INT(d, DB_LOCK_YOUNGEST);
5766#if (DBVER >= 33)
5767 ADD_INT(d, DB_LOCK_MAXLOCKS);
5768 ADD_INT(d, DB_LOCK_MINLOCKS);
5769 ADD_INT(d, DB_LOCK_MINWRITE);
5770#endif
5771
5772
5773#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005774 /* docs say to use zero instead */
5775 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005776#else
5777 ADD_INT(d, DB_LOCK_CONFLICT);
5778#endif
5779
5780 ADD_INT(d, DB_LOCK_DUMP);
5781 ADD_INT(d, DB_LOCK_GET);
5782 ADD_INT(d, DB_LOCK_INHERIT);
5783 ADD_INT(d, DB_LOCK_PUT);
5784 ADD_INT(d, DB_LOCK_PUT_ALL);
5785 ADD_INT(d, DB_LOCK_PUT_OBJ);
5786
5787 ADD_INT(d, DB_LOCK_NG);
5788 ADD_INT(d, DB_LOCK_READ);
5789 ADD_INT(d, DB_LOCK_WRITE);
5790 ADD_INT(d, DB_LOCK_NOWAIT);
5791#if (DBVER >= 32)
5792 ADD_INT(d, DB_LOCK_WAIT);
5793#endif
5794 ADD_INT(d, DB_LOCK_IWRITE);
5795 ADD_INT(d, DB_LOCK_IREAD);
5796 ADD_INT(d, DB_LOCK_IWR);
5797#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005798#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005800#else
5801 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5802#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005803 ADD_INT(d, DB_LOCK_WWRITE);
5804#endif
5805
5806 ADD_INT(d, DB_LOCK_RECORD);
5807 ADD_INT(d, DB_LOCK_UPGRADE);
5808#if (DBVER >= 32)
5809 ADD_INT(d, DB_LOCK_SWITCH);
5810#endif
5811#if (DBVER >= 33)
5812 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5813#endif
5814
5815 ADD_INT(d, DB_LOCK_NOWAIT);
5816 ADD_INT(d, DB_LOCK_RECORD);
5817 ADD_INT(d, DB_LOCK_UPGRADE);
5818
5819#if (DBVER >= 33)
5820 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005821#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005822 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005823#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005824 ADD_INT(d, DB_LSTAT_FREE);
5825 ADD_INT(d, DB_LSTAT_HELD);
5826#if (DBVER == 33)
5827 ADD_INT(d, DB_LSTAT_NOGRANT);
5828#endif
5829 ADD_INT(d, DB_LSTAT_PENDING);
5830 ADD_INT(d, DB_LSTAT_WAITING);
5831#endif
5832
5833 ADD_INT(d, DB_ARCH_ABS);
5834 ADD_INT(d, DB_ARCH_DATA);
5835 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005836#if (DBVER >= 42)
5837 ADD_INT(d, DB_ARCH_REMOVE);
5838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005839
5840 ADD_INT(d, DB_BTREE);
5841 ADD_INT(d, DB_HASH);
5842 ADD_INT(d, DB_RECNO);
5843 ADD_INT(d, DB_QUEUE);
5844 ADD_INT(d, DB_UNKNOWN);
5845
5846 ADD_INT(d, DB_DUP);
5847 ADD_INT(d, DB_DUPSORT);
5848 ADD_INT(d, DB_RECNUM);
5849 ADD_INT(d, DB_RENUMBER);
5850 ADD_INT(d, DB_REVSPLITOFF);
5851 ADD_INT(d, DB_SNAPSHOT);
5852
5853 ADD_INT(d, DB_JOIN_NOSORT);
5854
5855 ADD_INT(d, DB_AFTER);
5856 ADD_INT(d, DB_APPEND);
5857 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005858#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005859 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005860#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005861#if (DBVER >= 41)
5862 _addIntToDict(d, "DB_CHECKPOINT", 0);
5863#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005864 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005865 ADD_INT(d, DB_CURLSN);
5866#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005867#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005868 ADD_INT(d, DB_COMMIT);
5869#endif
5870 ADD_INT(d, DB_CONSUME);
5871#if (DBVER >= 32)
5872 ADD_INT(d, DB_CONSUME_WAIT);
5873#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005874 ADD_INT(d, DB_CURRENT);
5875#if (DBVER >= 33)
5876 ADD_INT(d, DB_FAST_STAT);
5877#endif
5878 ADD_INT(d, DB_FIRST);
5879 ADD_INT(d, DB_FLUSH);
5880 ADD_INT(d, DB_GET_BOTH);
5881 ADD_INT(d, DB_GET_RECNO);
5882 ADD_INT(d, DB_JOIN_ITEM);
5883 ADD_INT(d, DB_KEYFIRST);
5884 ADD_INT(d, DB_KEYLAST);
5885 ADD_INT(d, DB_LAST);
5886 ADD_INT(d, DB_NEXT);
5887 ADD_INT(d, DB_NEXT_DUP);
5888 ADD_INT(d, DB_NEXT_NODUP);
5889 ADD_INT(d, DB_NODUPDATA);
5890 ADD_INT(d, DB_NOOVERWRITE);
5891 ADD_INT(d, DB_NOSYNC);
5892 ADD_INT(d, DB_POSITION);
5893 ADD_INT(d, DB_PREV);
5894 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005895#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005896 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005897#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005898 ADD_INT(d, DB_SET);
5899 ADD_INT(d, DB_SET_RANGE);
5900 ADD_INT(d, DB_SET_RECNO);
5901 ADD_INT(d, DB_WRITECURSOR);
5902
5903 ADD_INT(d, DB_OPFLAGS_MASK);
5904 ADD_INT(d, DB_RMW);
5905#if (DBVER >= 33)
5906 ADD_INT(d, DB_DIRTY_READ);
5907 ADD_INT(d, DB_MULTIPLE);
5908 ADD_INT(d, DB_MULTIPLE_KEY);
5909#endif
5910
Gregory P. Smith29602d22006-01-24 09:46:48 +00005911#if (DBVER >= 44)
5912 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5913 ADD_INT(d, DB_READ_COMMITTED);
5914#endif
5915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005916#if (DBVER >= 33)
5917 ADD_INT(d, DB_DONOTINDEX);
5918#endif
5919
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005920#if (DBVER >= 41)
5921 _addIntToDict(d, "DB_INCOMPLETE", 0);
5922#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005923 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005924#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005925 ADD_INT(d, DB_KEYEMPTY);
5926 ADD_INT(d, DB_KEYEXIST);
5927 ADD_INT(d, DB_LOCK_DEADLOCK);
5928 ADD_INT(d, DB_LOCK_NOTGRANTED);
5929 ADD_INT(d, DB_NOSERVER);
5930 ADD_INT(d, DB_NOSERVER_HOME);
5931 ADD_INT(d, DB_NOSERVER_ID);
5932 ADD_INT(d, DB_NOTFOUND);
5933 ADD_INT(d, DB_OLD_VERSION);
5934 ADD_INT(d, DB_RUNRECOVERY);
5935 ADD_INT(d, DB_VERIFY_BAD);
5936#if (DBVER >= 33)
5937 ADD_INT(d, DB_PAGE_NOTFOUND);
5938 ADD_INT(d, DB_SECONDARY_BAD);
5939#endif
5940#if (DBVER >= 40)
5941 ADD_INT(d, DB_STAT_CLEAR);
5942 ADD_INT(d, DB_REGION_INIT);
5943 ADD_INT(d, DB_NOLOCKING);
5944 ADD_INT(d, DB_YIELDCPU);
5945 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5946 ADD_INT(d, DB_NOPANIC);
5947#endif
5948
Gregory P. Smith41631e82003-09-21 00:08:14 +00005949#if (DBVER >= 42)
5950 ADD_INT(d, DB_TIME_NOTGRANTED);
5951 ADD_INT(d, DB_TXN_NOT_DURABLE);
5952 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5953 ADD_INT(d, DB_LOG_AUTOREMOVE);
5954 ADD_INT(d, DB_DIRECT_LOG);
5955 ADD_INT(d, DB_DIRECT_DB);
5956 ADD_INT(d, DB_INIT_REP);
5957 ADD_INT(d, DB_ENCRYPT);
5958 ADD_INT(d, DB_CHKSUM);
5959#endif
5960
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005961#if (DBVER >= 43)
5962 ADD_INT(d, DB_LOG_INMEMORY);
5963 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005964 ADD_INT(d, DB_SEQ_DEC);
5965 ADD_INT(d, DB_SEQ_INC);
5966 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005967#endif
5968
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005969#if (DBVER >= 41)
5970 ADD_INT(d, DB_ENCRYPT_AES);
5971 ADD_INT(d, DB_AUTO_COMMIT);
5972#else
5973 /* allow berkeleydb 4.1 aware apps to run on older versions */
5974 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5975#endif
5976
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005977 ADD_INT(d, EINVAL);
5978 ADD_INT(d, EACCES);
5979 ADD_INT(d, ENOSPC);
5980 ADD_INT(d, ENOMEM);
5981 ADD_INT(d, EAGAIN);
5982 ADD_INT(d, EBUSY);
5983 ADD_INT(d, EEXIST);
5984 ADD_INT(d, ENOENT);
5985 ADD_INT(d, EPERM);
5986
Barry Warsaw1baa9822003-03-31 19:51:29 +00005987#if (DBVER >= 40)
5988 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5989 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5990#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005991
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005992 /* The exception name must be correct for pickled exception *
5993 * objects to unpickle properly. */
5994#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5995#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5996#else
5997#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5998#endif
5999
6000 /* All the rest of the exceptions derive only from DBError */
6001#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6002 PyDict_SetItemString(d, #name, name)
6003
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006004 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006005 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6006 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007
Gregory P. Smithe9477062005-06-04 06:46:59 +00006008 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6009 * from both DBError and KeyError, since the API only supports
6010 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006011 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006012 {
6013 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6014 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6015 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006016 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6017 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006018 Py_file_input, d, d);
6019 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006020 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006021 PyDict_DelItemString(d, "KeyError");
6022
6023
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006024#if !INCOMPLETE_IS_WARNING
6025 MAKE_EX(DBIncompleteError);
6026#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006027 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006028 MAKE_EX(DBKeyEmptyError);
6029 MAKE_EX(DBKeyExistError);
6030 MAKE_EX(DBLockDeadlockError);
6031 MAKE_EX(DBLockNotGrantedError);
6032 MAKE_EX(DBOldVersionError);
6033 MAKE_EX(DBRunRecoveryError);
6034 MAKE_EX(DBVerifyBadError);
6035 MAKE_EX(DBNoServerError);
6036 MAKE_EX(DBNoServerHomeError);
6037 MAKE_EX(DBNoServerIDError);
6038#if (DBVER >= 33)
6039 MAKE_EX(DBPageNotFoundError);
6040 MAKE_EX(DBSecondaryBadError);
6041#endif
6042
6043 MAKE_EX(DBInvalidArgError);
6044 MAKE_EX(DBAccessError);
6045 MAKE_EX(DBNoSpaceError);
6046 MAKE_EX(DBNoMemoryError);
6047 MAKE_EX(DBAgainError);
6048 MAKE_EX(DBBusyError);
6049 MAKE_EX(DBFileExistsError);
6050 MAKE_EX(DBNoSuchFileError);
6051 MAKE_EX(DBPermissionsError);
6052
6053#undef MAKE_EX
6054
6055 /* Check for errors */
6056 if (PyErr_Occurred()) {
6057 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006058 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006059 }
6060}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006061
6062/* allow this module to be named _pybsddb so that it can be installed
6063 * and imported on top of python >= 2.3 that includes its own older
6064 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006065PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006066{
6067 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6068 init_bsddb();
6069}