blob: 50568e7e66eca3c6e825e0f71f16fe7f1e0a86ce [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 */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000382 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000383 }
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000384 if (!PyBytes_Check(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000385 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith361ed152007-08-23 07:32:27 +0000386 "Data values must be of type bytes or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000387 return 0;
388 }
Gregory P. Smith361ed152007-08-23 07:32:27 +0000389 dbt->data = PyBytes_AS_STRING(obj);
390 dbt->size = PyBytes_GET_SIZE(obj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000391 return 1;
392}
393
394
395/* Recno and Queue DBs can have integer keys. This function figures out
396 what's been given, verifies that it's allowed, and then makes the DBT.
397
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000398 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000399static int
400make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000401{
402 db_recno_t recno;
403 int type;
404
405 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000406 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000408 if (type == -1)
409 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000410 if (type == DB_RECNO || type == DB_QUEUE) {
411 PyErr_SetString(
412 PyExc_TypeError,
413 "None keys not allowed for Recno and Queue DB's");
414 return 0;
415 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416 /* no need to do anything, the structure has already been zeroed */
417 }
418
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000419 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000420 /* verify access method type */
421 type = _DB_get_type(self);
422 if (type == -1)
423 return 0;
424 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000425 PyErr_SetString(
426 PyExc_TypeError,
427 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 return 0;
429 }
430
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000431 key->data = PyBytes_AS_STRING(keyobj);
432 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000433 }
434
435 else if (PyInt_Check(keyobj)) {
436 /* verify access method type */
437 type = _DB_get_type(self);
438 if (type == -1)
439 return 0;
440 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000441 /* if BTREE then an Integer key is allowed with the
442 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000443 *pflags |= DB_SET_RECNO;
444 }
445 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000446 PyErr_SetString(
447 PyExc_TypeError,
448 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000449 return 0;
450 }
451
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000452 /* Make a key out of the requested recno, use allocated space so DB
453 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 recno = PyInt_AS_LONG(keyobj);
455 key->data = malloc(sizeof(db_recno_t));
456 if (key->data == NULL) {
457 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
458 return 0;
459 }
460 key->ulen = key->size = sizeof(db_recno_t);
461 memcpy(key->data, &recno, sizeof(db_recno_t));
462 key->flags = DB_DBT_REALLOC;
463 }
464 else {
465 PyErr_Format(PyExc_TypeError,
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000466 "Bytes or Integer object expected for key, %s found",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000467 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000468 return 0;
469 }
470
471 return 1;
472}
473
474
475/* Add partial record access to an existing DBT data struct.
476 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
477 and the data storage/retrieval will be done using dlen and doff. */
478static int add_partial_dbt(DBT* d, int dlen, int doff) {
479 /* if neither were set we do nothing (-1 is the default value) */
480 if ((dlen == -1) && (doff == -1)) {
481 return 1;
482 }
483
484 if ((dlen < 0) || (doff < 0)) {
485 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
486 return 0;
487 }
488
489 d->flags = d->flags | DB_DBT_PARTIAL;
490 d->dlen = (unsigned int) dlen;
491 d->doff = (unsigned int) doff;
492 return 1;
493}
494
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000495/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
496/* TODO: make this use the native libc strlcpy() when available (BSD) */
497unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
498{
499 unsigned int srclen, copylen;
500
501 srclen = strlen(src);
502 if (n <= 0)
503 return srclen;
504 copylen = (srclen > n-1) ? n-1 : srclen;
505 /* populate dest[0] thru dest[copylen-1] */
506 memcpy(dest, src, copylen);
507 /* guarantee null termination */
508 dest[copylen] = 0;
509
510 return srclen;
511}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000513/* Callback used to save away more information about errors from the DB
514 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000515static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000516#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000517static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000518#else
519static void _db_errorCallback(const DB_ENV *db_env,
520 const char* prefix, const char* msg)
521#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000522{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000523 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000524}
525
526
527/* make a nice exception object to raise for errors. */
528static int makeDBError(int err)
529{
530 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000531 PyObject *errObj = NULL;
532 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000534 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000535
536 switch (err) {
537 case 0: /* successful, no error */ break;
538
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000539#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000540 case DB_INCOMPLETE:
541#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000542 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
543 /* Ensure that bytes_left never goes negative */
544 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
545 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
546 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000547 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000548 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000550 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000551#ifdef HAVE_WARNINGS
Skip Montanaro46fc3372007-08-12 11:44:53 +0000552 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000553#else
554 fprintf(stderr, errTxt);
555 fprintf(stderr, "\n");
556#endif
557
558#else /* do an exception instead */
559 errObj = DBIncompleteError;
560#endif
561 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000562#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563
564 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
565 case DB_KEYEXIST: errObj = DBKeyExistError; break;
566 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
567 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
568 case DB_NOTFOUND: errObj = DBNotFoundError; break;
569 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
570 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
571 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
572 case DB_NOSERVER: errObj = DBNoServerError; break;
573 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
574 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
575#if (DBVER >= 33)
576 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
577 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
578#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000579 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000580
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000581#if (DBVER >= 43)
582 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
583 case ENOMEM: errObj = PyExc_MemoryError; break;
584#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EINVAL: errObj = DBInvalidArgError; break;
586 case EACCES: errObj = DBAccessError; break;
587 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000588 case EAGAIN: errObj = DBAgainError; break;
589 case EBUSY : errObj = DBBusyError; break;
590 case EEXIST: errObj = DBFileExistsError; break;
591 case ENOENT: errObj = DBNoSuchFileError; break;
592 case EPERM : errObj = DBPermissionsError; break;
593
594 default: errObj = DBError; break;
595 }
596
597 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000598 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
599 /* Ensure that bytes_left never goes negative */
600 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
601 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
602 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000604 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000605 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000606 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000607
608 errTuple = Py_BuildValue("(is)", err, errTxt);
609 PyErr_SetObject(errObj, errTuple);
610 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000611 }
612
613 return ((errObj != NULL) || exceptionRaised);
614}
615
616
617
618/* set a type exception */
619static void makeTypeError(char* expected, PyObject* found)
620{
621 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000622 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000623}
624
625
626/* verify that an obj is either None or a DBTxn, and set the txn pointer */
627static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
628{
629 if (txnobj == Py_None || txnobj == NULL) {
630 *txn = NULL;
631 return 1;
632 }
633 if (DBTxnObject_Check(txnobj)) {
634 *txn = ((DBTxnObject*)txnobj)->txn;
635 return 1;
636 }
637 else
638 makeTypeError("DBTxn", txnobj);
639 return 0;
640}
641
642
643/* Delete a key from a database
644 Returns 0 on success, -1 on an error. */
645static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
646{
647 int err;
648
649 MYDB_BEGIN_ALLOW_THREADS;
650 err = self->db->del(self->db, txn, key, 0);
651 MYDB_END_ALLOW_THREADS;
652 if (makeDBError(err)) {
653 return -1;
654 }
655 self->haveStat = 0;
656 return 0;
657}
658
659
660/* Store a key into a database
661 Returns 0 on success, -1 on an error. */
662static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
663{
664 int err;
665
666 MYDB_BEGIN_ALLOW_THREADS;
667 err = self->db->put(self->db, txn, key, data, flags);
668 MYDB_END_ALLOW_THREADS;
669 if (makeDBError(err)) {
670 return -1;
671 }
672 self->haveStat = 0;
673 return 0;
674}
675
676/* Get a key/data pair from a cursor */
677static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
678 PyObject *args, PyObject *kwargs, char *format)
679{
680 int err;
681 PyObject* retval = NULL;
682 DBT key, data;
683 int dlen = -1;
684 int doff = -1;
685 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000686 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000687
688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
689 &flags, &dlen, &doff))
690 return NULL;
691
692 CHECK_CURSOR_NOT_CLOSED(self);
693
694 flags |= extra_flags;
695 CLEAR_DBT(key);
696 CLEAR_DBT(data);
697 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
698 /* Tell BerkeleyDB to malloc the return value (thread safe) */
699 data.flags = DB_DBT_MALLOC;
700 key.flags = DB_DBT_MALLOC;
701 }
702 if (!add_partial_dbt(&data, dlen, doff))
703 return NULL;
704
705 MYDB_BEGIN_ALLOW_THREADS;
706 err = self->dbc->c_get(self->dbc, &key, &data, flags);
707 MYDB_END_ALLOW_THREADS;
708
Gregory P. Smithe9477062005-06-04 06:46:59 +0000709 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
710 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711 Py_INCREF(Py_None);
712 retval = Py_None;
713 }
714 else if (makeDBError(err)) {
715 retval = NULL;
716 }
717 else { /* otherwise, success! */
718
719 /* if Recno or Queue, return the key as an Int */
720 switch (_DB_get_type(self->mydb)) {
721 case -1:
722 retval = NULL;
723 break;
724
725 case DB_RECNO:
726 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000727 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000728 data.data, data.size);
729 break;
730 case DB_HASH:
731 case DB_BTREE:
732 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000733 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000734 data.data, data.size);
735 break;
736 }
737 }
738 if (!err) {
739 FREE_DBT(key);
740 FREE_DBT(data);
741 }
742 return retval;
743}
744
745
746/* add an integer to a dictionary using the given name as a key */
747static void _addIntToDict(PyObject* dict, char *name, int value)
748{
749 PyObject* v = PyInt_FromLong((long) value);
750 if (!v || PyDict_SetItemString(dict, name, v))
751 PyErr_Clear();
752
753 Py_XDECREF(v);
754}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000755
756/* The same, when the value is a time_t */
757static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
758{
759 PyObject* v;
760 /* if the value fits in regular int, use that. */
761#ifdef HAVE_LONG_LONG
762 if (sizeof(time_t) > sizeof(long))
763 v = PyLong_FromLongLong((PY_LONG_LONG) value);
764 else
765#endif
766 v = PyInt_FromLong((long) value);
767 if (!v || PyDict_SetItemString(dict, name, v))
768 PyErr_Clear();
769
770 Py_XDECREF(v);
771}
772
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000773#if (DBVER >= 43)
774/* add an db_seq_t to a dictionary using the given name as a key */
775static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
776{
777 PyObject* v = PyLong_FromLongLong(value);
778 if (!v || PyDict_SetItemString(dict, name, v))
779 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000780
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000781 Py_XDECREF(v);
782}
783#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000784
785
786
787/* --------------------------------------------------------------------- */
788/* Allocators and deallocators */
789
790static DBObject*
791newDBObject(DBEnvObject* arg, int flags)
792{
793 DBObject* self;
794 DB_ENV* db_env = NULL;
795 int err;
796
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000798 if (self == NULL)
799 return NULL;
800
801 self->haveStat = 0;
802 self->flags = 0;
803 self->setflags = 0;
804 self->myenvobj = NULL;
805#if (DBVER >= 33)
806 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000807 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000808 self->primaryDBType = 0;
809#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000810#ifdef HAVE_WEAKREF
811 self->in_weakreflist = NULL;
812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813
814 /* keep a reference to our python DBEnv object */
815 if (arg) {
816 Py_INCREF(arg);
817 self->myenvobj = arg;
818 db_env = arg->db_env;
819 }
820
821 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000822 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000824 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
825 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826
827 MYDB_BEGIN_ALLOW_THREADS;
828 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000829 if (self->db != NULL) {
830 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000831#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000832 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000834 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000836 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
837 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000838 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839 if (makeDBError(err)) {
840 if (self->myenvobj) {
841 Py_DECREF(self->myenvobj);
842 self->myenvobj = NULL;
843 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000844 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000845 self = NULL;
846 }
847 return self;
848}
849
850
851static void
852DB_dealloc(DBObject* self)
853{
854 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000855 /* avoid closing a DB when its DBEnv has been closed out from under
856 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000858 (self->myenvobj && self->myenvobj->db_env))
859 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860 MYDB_BEGIN_ALLOW_THREADS;
861 self->db->close(self->db, 0);
862 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000863#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000865 PyErr_WarnEx(PyExc_RuntimeWarning,
866 "DB could not be closed in destructor:"
867 " DBEnv already closed",
868 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869#endif
870 }
871 self->db = NULL;
872 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000873#ifdef HAVE_WEAKREF
874 if (self->in_weakreflist != NULL) {
875 PyObject_ClearWeakRefs((PyObject *) self);
876 }
877#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 if (self->myenvobj) {
879 Py_DECREF(self->myenvobj);
880 self->myenvobj = NULL;
881 }
882#if (DBVER >= 33)
883 if (self->associateCallback != NULL) {
884 Py_DECREF(self->associateCallback);
885 self->associateCallback = NULL;
886 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000887 if (self->btCompareCallback != NULL) {
888 Py_DECREF(self->btCompareCallback);
889 self->btCompareCallback = NULL;
890 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000891#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893}
894
895
896static DBCursorObject*
897newDBCursorObject(DBC* dbc, DBObject* db)
898{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000899 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000900 if (self == NULL)
901 return NULL;
902
903 self->dbc = dbc;
904 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000905#ifdef HAVE_WEAKREF
906 self->in_weakreflist = NULL;
907#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908 Py_INCREF(self->mydb);
909 return self;
910}
911
912
913static void
914DBCursor_dealloc(DBCursorObject* self)
915{
916 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000917
918#ifdef HAVE_WEAKREF
919 if (self->in_weakreflist != NULL) {
920 PyObject_ClearWeakRefs((PyObject *) self);
921 }
922#endif
923
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 if (self->dbc != NULL) {
925 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000926 /* If the underlying database has been closed, we don't
927 need to do anything. If the environment has been closed
928 we need to leak, as BerkeleyDB will crash trying to access
929 the environment. There was an exception when the
930 user closed the environment even though there still was
931 a database open. */
932 if (self->mydb->db && self->mydb->myenvobj &&
933 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000934 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935 self->dbc = NULL;
936 MYDB_END_ALLOW_THREADS;
937 }
938 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000940}
941
942
943static DBEnvObject*
944newDBEnvObject(int flags)
945{
946 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000947 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948 if (self == NULL)
949 return NULL;
950
951 self->closed = 1;
952 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000953 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
954 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000955#ifdef HAVE_WEAKREF
956 self->in_weakreflist = NULL;
957#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958
959 MYDB_BEGIN_ALLOW_THREADS;
960 err = db_env_create(&self->db_env, flags);
961 MYDB_END_ALLOW_THREADS;
962 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000963 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 self = NULL;
965 }
966 else {
967 self->db_env->set_errcall(self->db_env, _db_errorCallback);
968 }
969 return self;
970}
971
972
973static void
974DBEnv_dealloc(DBEnvObject* self)
975{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000976#ifdef HAVE_WEAKREF
977 if (self->in_weakreflist != NULL) {
978 PyObject_ClearWeakRefs((PyObject *) self);
979 }
980#endif
981
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000982 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983 MYDB_BEGIN_ALLOW_THREADS;
984 self->db_env->close(self->db_env, 0);
985 MYDB_END_ALLOW_THREADS;
986 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000987 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000988}
989
990
991static DBTxnObject*
992newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
993{
994 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000995 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996 if (self == NULL)
997 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000998 Py_INCREF(myenv);
999 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000#ifdef HAVE_WEAKREF
1001 self->in_weakreflist = NULL;
1002#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001003
1004 MYDB_BEGIN_ALLOW_THREADS;
1005#if (DBVER >= 40)
1006 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1007#else
1008 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1009#endif
1010 MYDB_END_ALLOW_THREADS;
1011 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001012 Py_DECREF(self->env);
1013 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 self = NULL;
1015 }
1016 return self;
1017}
1018
1019
1020static void
1021DBTxn_dealloc(DBTxnObject* self)
1022{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001023#ifdef HAVE_WEAKREF
1024 if (self->in_weakreflist != NULL) {
1025 PyObject_ClearWeakRefs((PyObject *) self);
1026 }
1027#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001028
Gregory P. Smith31c50652004-06-28 01:20:40 +00001029#ifdef HAVE_WARNINGS
1030 if (self->txn) {
1031 /* it hasn't been finalized, abort it! */
1032 MYDB_BEGIN_ALLOW_THREADS;
1033#if (DBVER >= 40)
1034 self->txn->abort(self->txn);
1035#else
1036 txn_abort(self->txn);
1037#endif
1038 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001039 PyErr_WarnEx(PyExc_RuntimeWarning,
1040 "DBTxn aborted in destructor. "
1041 " No prior commit() or abort().",
1042 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001043 }
1044#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045
Neal Norwitz62a21122006-01-25 05:21:55 +00001046 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001047 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001048}
1049
1050
1051static DBLockObject*
1052newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1053 db_lockmode_t lock_mode, int flags)
1054{
1055 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001056 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057 if (self == NULL)
1058 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001059#ifdef HAVE_WEAKREF
1060 self->in_weakreflist = NULL;
1061#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062
1063 MYDB_BEGIN_ALLOW_THREADS;
1064#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001065 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1066 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067#else
1068 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1069#endif
1070 MYDB_END_ALLOW_THREADS;
1071 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001072 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001073 self = NULL;
1074 }
1075
1076 return self;
1077}
1078
1079
1080static void
1081DBLock_dealloc(DBLockObject* self)
1082{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001083#ifdef HAVE_WEAKREF
1084 if (self->in_weakreflist != NULL) {
1085 PyObject_ClearWeakRefs((PyObject *) self);
1086 }
1087#endif
1088 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001089
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001090 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001091}
1092
1093
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001094#if (DBVER >= 43)
1095static DBSequenceObject*
1096newDBSequenceObject(DBObject* mydb, int flags)
1097{
1098 int err;
1099 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1100 if (self == NULL)
1101 return NULL;
1102 Py_INCREF(mydb);
1103 self->mydb = mydb;
1104#ifdef HAVE_WEAKREF
1105 self->in_weakreflist = NULL;
1106#endif
1107
1108
1109 MYDB_BEGIN_ALLOW_THREADS;
1110 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1111 MYDB_END_ALLOW_THREADS;
1112 if (makeDBError(err)) {
1113 Py_DECREF(self->mydb);
1114 PyObject_Del(self);
1115 self = NULL;
1116 }
1117
1118 return self;
1119}
1120
1121
1122static void
1123DBSequence_dealloc(DBSequenceObject* self)
1124{
1125#ifdef HAVE_WEAKREF
1126 if (self->in_weakreflist != NULL) {
1127 PyObject_ClearWeakRefs((PyObject *) self);
1128 }
1129#endif
1130
1131 Py_DECREF(self->mydb);
1132 PyObject_Del(self);
1133}
1134#endif
1135
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136/* --------------------------------------------------------------------- */
1137/* DB methods */
1138
1139static PyObject*
1140DB_append(DBObject* self, PyObject* args)
1141{
1142 PyObject* txnobj = NULL;
1143 PyObject* dataobj;
1144 db_recno_t recno;
1145 DBT key, data;
1146 DB_TXN *txn = NULL;
1147
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001148 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149 return NULL;
1150
1151 CHECK_DB_NOT_CLOSED(self);
1152
1153 /* make a dummy key out of a recno */
1154 recno = 0;
1155 CLEAR_DBT(key);
1156 key.data = &recno;
1157 key.size = sizeof(recno);
1158 key.ulen = key.size;
1159 key.flags = DB_DBT_USERMEM;
1160
1161 if (!make_dbt(dataobj, &data)) return NULL;
1162 if (!checkTxnObj(txnobj, &txn)) return NULL;
1163
1164 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1165 return NULL;
1166
1167 return PyInt_FromLong(recno);
1168}
1169
1170
1171#if (DBVER >= 33)
1172
1173static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001174_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1175 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176{
1177 int retval = DB_DONOTINDEX;
1178 DBObject* secondaryDB = (DBObject*)db->app_private;
1179 PyObject* callback = secondaryDB->associateCallback;
1180 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001182 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001183
1184
1185 if (callback != NULL) {
1186 MYDB_BEGIN_BLOCK_THREADS;
1187
Thomas Woutersb3153832006-03-08 01:47:19 +00001188 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001189 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001190 priData->data, priData->size);
1191 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001192 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001193 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001194 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001195 result = PyEval_CallObject(callback, args);
1196 }
1197 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198 PyErr_Print();
1199 }
1200 else if (result == Py_None) {
1201 retval = DB_DONOTINDEX;
1202 }
1203 else if (PyInt_Check(result)) {
1204 retval = PyInt_AsLong(result);
1205 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001206 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001208 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001209
1210 CLEAR_DBT(*secKey);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001211 size = PyBytes_Size(result);
1212 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001213 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1214 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001215 if (secKey->data) {
1216 memcpy(secKey->data, data, size);
1217 secKey->size = size;
1218 retval = 0;
1219 }
1220 else {
1221 PyErr_SetString(PyExc_MemoryError,
1222 "malloc failed in _db_associateCallback");
1223 PyErr_Print();
1224 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225 }
1226 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001227 PyErr_SetString(
1228 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001229 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001230 PyErr_Print();
1231 }
1232
Thomas Woutersb3153832006-03-08 01:47:19 +00001233 Py_XDECREF(args);
1234 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001235
1236 MYDB_END_BLOCK_THREADS;
1237 }
1238 return retval;
1239}
1240
1241
1242static PyObject*
1243DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1244{
1245 int err, flags=0;
1246 DBObject* secondaryDB;
1247 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001248#if (DBVER >= 41)
1249 PyObject *txnobj = NULL;
1250 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001251 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001252 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001253#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001254 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001255#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001256
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001257#if (DBVER >= 41)
1258 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1259 &secondaryDB, &callback, &flags,
1260 &txnobj)) {
1261#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001263 &secondaryDB, &callback, &flags)) {
1264#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001266 }
1267
1268#if (DBVER >= 41)
1269 if (!checkTxnObj(txnobj, &txn)) return NULL;
1270#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271
1272 CHECK_DB_NOT_CLOSED(self);
1273 if (!DBObject_Check(secondaryDB)) {
1274 makeTypeError("DB", (PyObject*)secondaryDB);
1275 return NULL;
1276 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001277 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001278 if (callback == Py_None) {
1279 callback = NULL;
1280 }
1281 else if (!PyCallable_Check(callback)) {
1282 makeTypeError("Callable", callback);
1283 return NULL;
1284 }
1285
1286 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001287 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001288 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289 secondaryDB->associateCallback = callback;
1290 secondaryDB->primaryDBType = _DB_get_type(self);
1291
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001292 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1293 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1294 * The global interepreter lock is not initialized until the first
1295 * thread is created using thread.start_new_thread() or fork() is
1296 * called. that would cause the ALLOW_THREADS here to segfault due
1297 * to a null pointer reference if no threads or child processes
1298 * have been created. This works around that and is a no-op if
1299 * threads have already been initialized.
1300 * (see pybsddb-users mailing list post on 2002-08-07)
1301 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001302#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001303 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001304#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001306#if (DBVER >= 41)
1307 err = self->db->associate(self->db,
1308 txn,
1309 secondaryDB->db,
1310 _db_associateCallback,
1311 flags);
1312#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001313 err = self->db->associate(self->db,
1314 secondaryDB->db,
1315 _db_associateCallback,
1316 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001317#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001318 MYDB_END_ALLOW_THREADS;
1319
1320 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001321 Py_XDECREF(secondaryDB->associateCallback);
1322 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 secondaryDB->primaryDBType = 0;
1324 }
1325
1326 RETURN_IF_ERR();
1327 RETURN_NONE();
1328}
1329
1330
1331#endif
1332
1333
1334static PyObject*
1335DB_close(DBObject* self, PyObject* args)
1336{
1337 int err, flags=0;
1338 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1339 return NULL;
1340 if (self->db != NULL) {
1341 if (self->myenvobj)
1342 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001344 self->db = NULL;
1345 RETURN_IF_ERR();
1346 }
1347 RETURN_NONE();
1348}
1349
1350
1351#if (DBVER >= 32)
1352static PyObject*
1353_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1354{
1355 int err, flags=0, type;
1356 PyObject* txnobj = NULL;
1357 PyObject* retval = NULL;
1358 DBT key, data;
1359 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001360 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001361
1362 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1363 &txnobj, &flags))
1364 return NULL;
1365
1366 CHECK_DB_NOT_CLOSED(self);
1367 type = _DB_get_type(self);
1368 if (type == -1)
1369 return NULL;
1370 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001371 PyErr_SetString(PyExc_TypeError,
1372 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001373 return NULL;
1374 }
1375 if (!checkTxnObj(txnobj, &txn))
1376 return NULL;
1377
1378 CLEAR_DBT(key);
1379 CLEAR_DBT(data);
1380 if (CHECK_DBFLAG(self, DB_THREAD)) {
1381 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1382 data.flags = DB_DBT_MALLOC;
1383 key.flags = DB_DBT_MALLOC;
1384 }
1385
1386 MYDB_BEGIN_ALLOW_THREADS;
1387 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1388 MYDB_END_ALLOW_THREADS;
1389
Gregory P. Smithe9477062005-06-04 06:46:59 +00001390 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1391 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392 err = 0;
1393 Py_INCREF(Py_None);
1394 retval = Py_None;
1395 }
1396 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001397 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001398 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001399 FREE_DBT(key);
1400 FREE_DBT(data);
1401 }
1402
1403 RETURN_IF_ERR();
1404 return retval;
1405}
1406
1407static PyObject*
1408DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1409{
1410 return _DB_consume(self, args, kwargs, DB_CONSUME);
1411}
1412
1413static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001414DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1415 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001416{
1417 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1418}
1419#endif
1420
1421
1422
1423static PyObject*
1424DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1425{
1426 int err, flags=0;
1427 DBC* dbc;
1428 PyObject* txnobj = NULL;
1429 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001430 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431
1432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1433 &txnobj, &flags))
1434 return NULL;
1435 CHECK_DB_NOT_CLOSED(self);
1436 if (!checkTxnObj(txnobj, &txn))
1437 return NULL;
1438
1439 MYDB_BEGIN_ALLOW_THREADS;
1440 err = self->db->cursor(self->db, txn, &dbc, flags);
1441 MYDB_END_ALLOW_THREADS;
1442 RETURN_IF_ERR();
1443 return (PyObject*) newDBCursorObject(dbc, self);
1444}
1445
1446
1447static PyObject*
1448DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1449{
1450 PyObject* txnobj = NULL;
1451 int flags = 0;
1452 PyObject* keyobj;
1453 DBT key;
1454 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001455 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456
1457 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1458 &keyobj, &txnobj, &flags))
1459 return NULL;
1460 CHECK_DB_NOT_CLOSED(self);
1461 if (!make_key_dbt(self, keyobj, &key, NULL))
1462 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001463 if (!checkTxnObj(txnobj, &txn)) {
1464 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001466 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001467
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001468 if (-1 == _DB_delete(self, txn, &key, 0)) {
1469 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001471 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001472
1473 FREE_DBT(key);
1474 RETURN_NONE();
1475}
1476
1477
1478static PyObject*
1479DB_fd(DBObject* self, PyObject* args)
1480{
1481 int err, the_fd;
1482
1483 if (!PyArg_ParseTuple(args,":fd"))
1484 return NULL;
1485 CHECK_DB_NOT_CLOSED(self);
1486
1487 MYDB_BEGIN_ALLOW_THREADS;
1488 err = self->db->fd(self->db, &the_fd);
1489 MYDB_END_ALLOW_THREADS;
1490 RETURN_IF_ERR();
1491 return PyInt_FromLong(the_fd);
1492}
1493
1494
1495static PyObject*
1496DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1497{
1498 int err, flags=0;
1499 PyObject* txnobj = NULL;
1500 PyObject* keyobj;
1501 PyObject* dfltobj = NULL;
1502 PyObject* retval = NULL;
1503 int dlen = -1;
1504 int doff = -1;
1505 DBT key, data;
1506 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001507 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001508 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001509
1510 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001511 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1512 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001513 return NULL;
1514
1515 CHECK_DB_NOT_CLOSED(self);
1516 if (!make_key_dbt(self, keyobj, &key, &flags))
1517 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001518 if (!checkTxnObj(txnobj, &txn)) {
1519 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001520 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001521 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522
1523 CLEAR_DBT(data);
1524 if (CHECK_DBFLAG(self, DB_THREAD)) {
1525 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1526 data.flags = DB_DBT_MALLOC;
1527 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001528 if (!add_partial_dbt(&data, dlen, doff)) {
1529 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001530 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532
1533 MYDB_BEGIN_ALLOW_THREADS;
1534 err = self->db->get(self->db, txn, &key, &data, flags);
1535 MYDB_END_ALLOW_THREADS;
1536
Gregory P. Smithe9477062005-06-04 06:46:59 +00001537 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001538 err = 0;
1539 Py_INCREF(dfltobj);
1540 retval = dfltobj;
1541 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001542 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1543 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001544 err = 0;
1545 Py_INCREF(Py_None);
1546 retval = Py_None;
1547 }
1548 else if (!err) {
1549 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001550 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001551 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001552 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001553 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554 FREE_DBT(data);
1555 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001556 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001557
1558 RETURN_IF_ERR();
1559 return retval;
1560}
1561
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001562#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001563static PyObject*
1564DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1565{
1566 int err, flags=0;
1567 PyObject* txnobj = NULL;
1568 PyObject* keyobj;
1569 PyObject* dfltobj = NULL;
1570 PyObject* retval = NULL;
1571 int dlen = -1;
1572 int doff = -1;
1573 DBT key, pkey, data;
1574 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001575 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001576 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001577
1578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1579 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1580 &doff))
1581 return NULL;
1582
1583 CHECK_DB_NOT_CLOSED(self);
1584 if (!make_key_dbt(self, keyobj, &key, &flags))
1585 return NULL;
1586 if (!checkTxnObj(txnobj, &txn)) {
1587 FREE_DBT(key);
1588 return NULL;
1589 }
1590
1591 CLEAR_DBT(data);
1592 if (CHECK_DBFLAG(self, DB_THREAD)) {
1593 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1594 data.flags = DB_DBT_MALLOC;
1595 }
1596 if (!add_partial_dbt(&data, dlen, doff)) {
1597 FREE_DBT(key);
1598 return NULL;
1599 }
1600
1601 CLEAR_DBT(pkey);
1602 pkey.flags = DB_DBT_MALLOC;
1603
1604 MYDB_BEGIN_ALLOW_THREADS;
1605 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1606 MYDB_END_ALLOW_THREADS;
1607
Gregory P. Smithe9477062005-06-04 06:46:59 +00001608 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001609 err = 0;
1610 Py_INCREF(dfltobj);
1611 retval = dfltobj;
1612 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001613 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1614 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001615 err = 0;
1616 Py_INCREF(Py_None);
1617 retval = Py_None;
1618 }
1619 else if (!err) {
1620 PyObject *pkeyObj;
1621 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001622 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001623
1624 if (self->primaryDBType == DB_RECNO ||
1625 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001626 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001627 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001628 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001629
1630 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1631 {
1632 PyObject *keyObj;
1633 int type = _DB_get_type(self);
1634 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001635 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001636 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001637 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001638#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001639 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001640#else
1641 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1642#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001643 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001644 }
1645 else /* return just the pkey and data */
1646 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001647#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001648 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001649#else
1650 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1651#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001652 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001653 Py_DECREF(dataObj);
1654 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001655 FREE_DBT(pkey);
1656 FREE_DBT(data);
1657 }
1658 FREE_DBT(key);
1659
1660 RETURN_IF_ERR();
1661 return retval;
1662}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001663#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001664
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001665
1666/* Return size of entry */
1667static PyObject*
1668DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1669{
1670 int err, flags=0;
1671 PyObject* txnobj = NULL;
1672 PyObject* keyobj;
1673 PyObject* retval = NULL;
1674 DBT key, data;
1675 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001676 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001677
1678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1679 &keyobj, &txnobj))
1680 return NULL;
1681 CHECK_DB_NOT_CLOSED(self);
1682 if (!make_key_dbt(self, keyobj, &key, &flags))
1683 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001684 if (!checkTxnObj(txnobj, &txn)) {
1685 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001687 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001688 CLEAR_DBT(data);
1689
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001690 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1691 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692 data.flags = DB_DBT_USERMEM;
1693 data.ulen = 0;
1694 MYDB_BEGIN_ALLOW_THREADS;
1695 err = self->db->get(self->db, txn, &key, &data, flags);
1696 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001697 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001698 retval = PyInt_FromLong((long)data.size);
1699 err = 0;
1700 }
1701
1702 FREE_DBT(key);
1703 FREE_DBT(data);
1704 RETURN_IF_ERR();
1705 return retval;
1706}
1707
1708
1709static PyObject*
1710DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1711{
1712 int err, flags=0;
1713 PyObject* txnobj = NULL;
1714 PyObject* keyobj;
1715 PyObject* dataobj;
1716 PyObject* retval = NULL;
1717 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001718 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001720 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721
1722
1723 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1724 &keyobj, &dataobj, &txnobj, &flags))
1725 return NULL;
1726
1727 CHECK_DB_NOT_CLOSED(self);
1728 if (!make_key_dbt(self, keyobj, &key, NULL))
1729 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001730 if ( !make_dbt(dataobj, &data) ||
1731 !checkTxnObj(txnobj, &txn) )
1732 {
1733 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001734 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001735 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001736
1737 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001738 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001739
1740 if (CHECK_DBFLAG(self, DB_THREAD)) {
1741 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001742 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001743 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001744 }
1745
1746 MYDB_BEGIN_ALLOW_THREADS;
1747 err = self->db->get(self->db, txn, &key, &data, flags);
1748 MYDB_END_ALLOW_THREADS;
1749
Gregory P. Smithe9477062005-06-04 06:46:59 +00001750 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1751 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001752 err = 0;
1753 Py_INCREF(Py_None);
1754 retval = Py_None;
1755 }
1756 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001757 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001758 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001759
1760 /* Even though the flags require DB_DBT_MALLOC, data is not always
1761 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1762 if (data.data != orig_data)
1763 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001764 }
1765
1766 FREE_DBT(key);
1767 RETURN_IF_ERR();
1768 return retval;
1769}
1770
1771
1772static PyObject*
1773DB_get_byteswapped(DBObject* self, PyObject* args)
1774{
1775#if (DBVER >= 33)
1776 int err = 0;
1777#endif
1778 int retval = -1;
1779
1780 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1781 return NULL;
1782 CHECK_DB_NOT_CLOSED(self);
1783
1784#if (DBVER >= 33)
1785 MYDB_BEGIN_ALLOW_THREADS;
1786 err = self->db->get_byteswapped(self->db, &retval);
1787 MYDB_END_ALLOW_THREADS;
1788 RETURN_IF_ERR();
1789#else
1790 MYDB_BEGIN_ALLOW_THREADS;
1791 retval = self->db->get_byteswapped(self->db);
1792 MYDB_END_ALLOW_THREADS;
1793#endif
1794 return PyInt_FromLong(retval);
1795}
1796
1797
1798static PyObject*
1799DB_get_type(DBObject* self, PyObject* args)
1800{
1801 int type;
1802
1803 if (!PyArg_ParseTuple(args,":get_type"))
1804 return NULL;
1805 CHECK_DB_NOT_CLOSED(self);
1806
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001807 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 if (type == -1)
1809 return NULL;
1810 return PyInt_FromLong(type);
1811}
1812
1813
1814static PyObject*
1815DB_join(DBObject* self, PyObject* args)
1816{
1817 int err, flags=0;
1818 int length, x;
1819 PyObject* cursorsObj;
1820 DBC** cursors;
1821 DBC* dbc;
1822
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1824 return NULL;
1825
1826 CHECK_DB_NOT_CLOSED(self);
1827
1828 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001829 PyErr_SetString(PyExc_TypeError,
1830 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 return NULL;
1832 }
1833
1834 length = PyObject_Length(cursorsObj);
1835 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001836 if (!cursors) {
1837 PyErr_NoMemory();
1838 return NULL;
1839 }
1840
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001841 cursors[length] = NULL;
1842 for (x=0; x<length; x++) {
1843 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001844 if (item == NULL) {
1845 free(cursors);
1846 return NULL;
1847 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001849 PyErr_SetString(PyExc_TypeError,
1850 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001851 free(cursors);
1852 return NULL;
1853 }
1854 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001855 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856 }
1857
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->join(self->db, cursors, &dbc, flags);
1860 MYDB_END_ALLOW_THREADS;
1861 free(cursors);
1862 RETURN_IF_ERR();
1863
Gregory P. Smith7441e652003-11-03 21:35:31 +00001864 /* FIXME: this is a buggy interface. The returned cursor
1865 contains internal references to the passed in cursors
1866 but does not hold python references to them or prevent
1867 them from being closed prematurely. This can cause
1868 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001869 return (PyObject*) newDBCursorObject(dbc, self);
1870}
1871
1872
1873static PyObject*
1874DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1875{
1876 int err, flags=0;
1877 PyObject* txnobj = NULL;
1878 PyObject* keyobj;
1879 DBT key;
1880 DB_TXN *txn = NULL;
1881 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001882 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001883
1884 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1885 &keyobj, &txnobj, &flags))
1886 return NULL;
1887 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001888 if (!make_dbt(keyobj, &key))
1889 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001890 return NULL;
1891 if (!checkTxnObj(txnobj, &txn))
1892 return NULL;
1893
1894 MYDB_BEGIN_ALLOW_THREADS;
1895 err = self->db->key_range(self->db, txn, &key, &range, flags);
1896 MYDB_END_ALLOW_THREADS;
1897
1898 RETURN_IF_ERR();
1899 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1900}
1901
1902
1903static PyObject*
1904DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1905{
1906 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1907 char* filename = NULL;
1908 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001909#if (DBVER >= 41)
1910 PyObject *txnobj = NULL;
1911 DB_TXN *txn = NULL;
1912 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001913 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001914 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1915 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001916 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001917 "filename", "dbtype", "flags", "mode", "txn", NULL};
1918#else
1919 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001920 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001921 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1922 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001923 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001924 "filename", "dbtype", "flags", "mode", NULL};
1925#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001926
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001927#if (DBVER >= 41)
1928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1929 &filename, &dbname, &type, &flags, &mode,
1930 &txnobj))
1931#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001933 &filename, &dbname, &type, &flags,
1934 &mode))
1935#endif
1936 {
1937 PyErr_Clear();
1938 type = DB_UNKNOWN; flags = 0; mode = 0660;
1939 filename = NULL; dbname = NULL;
1940#if (DBVER >= 41)
1941 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1942 kwnames_basic,
1943 &filename, &type, &flags, &mode,
1944 &txnobj))
1945 return NULL;
1946#else
1947 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1948 kwnames_basic,
1949 &filename, &type, &flags, &mode))
1950 return NULL;
1951#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 }
1953
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001954#if (DBVER >= 41)
1955 if (!checkTxnObj(txnobj, &txn)) return NULL;
1956#endif
1957
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001959 PyObject *t = Py_BuildValue("(is)", 0,
1960 "Cannot call open() twice for DB object");
1961 PyErr_SetObject(DBError, t);
1962 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001963 return NULL;
1964 }
1965
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001966#if 0 && (DBVER >= 41)
1967 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1968 && (self->myenvobj->flags & DB_INIT_TXN))
1969 {
1970 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1971 * explicitly passed) but we are in a transaction ready environment:
1972 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1973 * to work on BerkeleyDB 4.1 without needing to modify their
1974 * DBEnv or DB open calls.
1975 * TODO make this behaviour of the library configurable.
1976 */
1977 flags |= DB_AUTO_COMMIT;
1978 }
1979#endif
1980
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001981 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001982#if (DBVER >= 41)
1983 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1984#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001985 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001986#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001987 MYDB_END_ALLOW_THREADS;
1988 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001989 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001990 self->db = NULL;
1991 return NULL;
1992 }
1993
1994 self->flags = flags;
1995 RETURN_NONE();
1996}
1997
1998
1999static PyObject*
2000DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2001{
2002 int flags=0;
2003 PyObject* txnobj = NULL;
2004 int dlen = -1;
2005 int doff = -1;
2006 PyObject* keyobj, *dataobj, *retval;
2007 DBT key, data;
2008 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002009 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002010 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011
2012 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2013 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2014 return NULL;
2015
2016 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002017 if (!make_key_dbt(self, keyobj, &key, NULL))
2018 return NULL;
2019 if ( !make_dbt(dataobj, &data) ||
2020 !add_partial_dbt(&data, dlen, doff) ||
2021 !checkTxnObj(txnobj, &txn) )
2022 {
2023 FREE_DBT(key);
2024 return NULL;
2025 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002026
2027 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2028 FREE_DBT(key);
2029 return NULL;
2030 }
2031
2032 if (flags & DB_APPEND)
2033 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2034 else {
2035 retval = Py_None;
2036 Py_INCREF(retval);
2037 }
2038 FREE_DBT(key);
2039 return retval;
2040}
2041
2042
2043
2044static PyObject*
2045DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2046{
2047 char* filename;
2048 char* database = NULL;
2049 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002050 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051
2052 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2053 &filename, &database, &flags))
2054 return NULL;
2055 CHECK_DB_NOT_CLOSED(self);
2056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002057 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002058 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002059 RETURN_IF_ERR();
2060 RETURN_NONE();
2061}
2062
2063
2064
2065static PyObject*
2066DB_rename(DBObject* self, PyObject* args)
2067{
2068 char* filename;
2069 char* database;
2070 char* newname;
2071 int err, flags=0;
2072
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002073 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2074 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002075 return NULL;
2076 CHECK_DB_NOT_CLOSED(self);
2077
2078 MYDB_BEGIN_ALLOW_THREADS;
2079 err = self->db->rename(self->db, filename, database, newname, flags);
2080 MYDB_END_ALLOW_THREADS;
2081 RETURN_IF_ERR();
2082 RETURN_NONE();
2083}
2084
2085
2086static PyObject*
2087DB_set_bt_minkey(DBObject* self, PyObject* args)
2088{
2089 int err, minkey;
2090
2091 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2092 return NULL;
2093 CHECK_DB_NOT_CLOSED(self);
2094
2095 MYDB_BEGIN_ALLOW_THREADS;
2096 err = self->db->set_bt_minkey(self->db, minkey);
2097 MYDB_END_ALLOW_THREADS;
2098 RETURN_IF_ERR();
2099 RETURN_NONE();
2100}
2101
Neal Norwitz84562352005-10-20 04:30:15 +00002102#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002104_default_cmp(const DBT *leftKey,
2105 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002106{
2107 int res;
2108 int lsize = leftKey->size, rsize = rightKey->size;
2109
Georg Brandlef1701f2006-03-07 14:57:48 +00002110 res = memcmp(leftKey->data, rightKey->data,
2111 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002112
2113 if (res == 0) {
2114 if (lsize < rsize) {
2115 res = -1;
2116 }
2117 else if (lsize > rsize) {
2118 res = 1;
2119 }
2120 }
2121 return res;
2122}
2123
2124static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002125_db_compareCallback(DB* db,
2126 const DBT *leftKey,
2127 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002128{
2129 int res = 0;
2130 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002131 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002133
2134 if (self == NULL || self->btCompareCallback == NULL) {
2135 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002136 PyErr_SetString(PyExc_TypeError,
2137 (self == 0
2138 ? "DB_bt_compare db is NULL."
2139 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002140 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002141 PyErr_Print();
2142 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002143 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002144 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002145 MYDB_BEGIN_BLOCK_THREADS;
2146
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002147 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002148 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002149 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002150 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002151 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002152 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002153 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002154 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002156 PyErr_Print();
2157 res = _default_cmp(leftKey, rightKey);
2158 } else if (PyInt_Check(result)) {
2159 res = PyInt_AsLong(result);
2160 } else {
2161 PyErr_SetString(PyExc_TypeError,
2162 "DB_bt_compare callback MUST return an int.");
2163 /* we're in a callback within the DB code, we can't raise */
2164 PyErr_Print();
2165 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166 }
2167
Thomas Woutersb3153832006-03-08 01:47:19 +00002168 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002169 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002170
2171 MYDB_END_BLOCK_THREADS;
2172 }
2173 return res;
2174}
2175
2176static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002177DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178{
2179 int err;
2180 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002181 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184 return NULL;
2185
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187
Georg Brandlef1701f2006-03-07 14:57:48 +00002188 if (!PyCallable_Check(comparator)) {
2189 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002190 return NULL;
2191 }
2192
2193 /*
2194 * Perform a test call of the comparator function with two empty
2195 * string objects here. verify that it returns an int (0).
2196 * err if not.
2197 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002198 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002199 result = PyEval_CallObject(comparator, tuple);
2200 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002201 if (result == NULL)
2202 return NULL;
2203 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002204 PyErr_SetString(PyExc_TypeError,
2205 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002206 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002207 } else if (PyInt_AsLong(result) != 0) {
2208 PyErr_SetString(PyExc_TypeError,
2209 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002210 return NULL;
2211 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002212 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213
2214 /* We don't accept multiple set_bt_compare operations, in order to
2215 * simplify the code. This would have no real use, as one cannot
2216 * change the function once the db is opened anyway */
2217 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002218 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219 return NULL;
2220 }
2221
Georg Brandlef1701f2006-03-07 14:57:48 +00002222 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002223 self->btCompareCallback = comparator;
2224
2225 /* This is to workaround a problem with un-initialized threads (see
2226 comment in DB_associate) */
2227#ifdef WITH_THREAD
2228 PyEval_InitThreads();
2229#endif
2230
Thomas Woutersb3153832006-03-08 01:47:19 +00002231 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002232
2233 if (err) {
2234 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002235 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002236 self->btCompareCallback = NULL;
2237 }
2238
Georg Brandlef1701f2006-03-07 14:57:48 +00002239 RETURN_IF_ERR();
2240 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002241}
Neal Norwitz84562352005-10-20 04:30:15 +00002242#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002243
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002244
2245static PyObject*
2246DB_set_cachesize(DBObject* self, PyObject* args)
2247{
2248 int err;
2249 int gbytes = 0, bytes = 0, ncache = 0;
2250
2251 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2252 &gbytes,&bytes,&ncache))
2253 return NULL;
2254 CHECK_DB_NOT_CLOSED(self);
2255
2256 MYDB_BEGIN_ALLOW_THREADS;
2257 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2258 MYDB_END_ALLOW_THREADS;
2259 RETURN_IF_ERR();
2260 RETURN_NONE();
2261}
2262
2263
2264static PyObject*
2265DB_set_flags(DBObject* self, PyObject* args)
2266{
2267 int err, flags;
2268
2269 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2270 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2272
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_flags(self->db, flags);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277
2278 self->setflags |= flags;
2279 RETURN_NONE();
2280}
2281
2282
2283static PyObject*
2284DB_set_h_ffactor(DBObject* self, PyObject* args)
2285{
2286 int err, ffactor;
2287
2288 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2289 return NULL;
2290 CHECK_DB_NOT_CLOSED(self);
2291
2292 MYDB_BEGIN_ALLOW_THREADS;
2293 err = self->db->set_h_ffactor(self->db, ffactor);
2294 MYDB_END_ALLOW_THREADS;
2295 RETURN_IF_ERR();
2296 RETURN_NONE();
2297}
2298
2299
2300static PyObject*
2301DB_set_h_nelem(DBObject* self, PyObject* args)
2302{
2303 int err, nelem;
2304
2305 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2306 return NULL;
2307 CHECK_DB_NOT_CLOSED(self);
2308
2309 MYDB_BEGIN_ALLOW_THREADS;
2310 err = self->db->set_h_nelem(self->db, nelem);
2311 MYDB_END_ALLOW_THREADS;
2312 RETURN_IF_ERR();
2313 RETURN_NONE();
2314}
2315
2316
2317static PyObject*
2318DB_set_lorder(DBObject* self, PyObject* args)
2319{
2320 int err, lorder;
2321
2322 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2323 return NULL;
2324 CHECK_DB_NOT_CLOSED(self);
2325
2326 MYDB_BEGIN_ALLOW_THREADS;
2327 err = self->db->set_lorder(self->db, lorder);
2328 MYDB_END_ALLOW_THREADS;
2329 RETURN_IF_ERR();
2330 RETURN_NONE();
2331}
2332
2333
2334static PyObject*
2335DB_set_pagesize(DBObject* self, PyObject* args)
2336{
2337 int err, pagesize;
2338
2339 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2340 return NULL;
2341 CHECK_DB_NOT_CLOSED(self);
2342
2343 MYDB_BEGIN_ALLOW_THREADS;
2344 err = self->db->set_pagesize(self->db, pagesize);
2345 MYDB_END_ALLOW_THREADS;
2346 RETURN_IF_ERR();
2347 RETURN_NONE();
2348}
2349
2350
2351static PyObject*
2352DB_set_re_delim(DBObject* self, PyObject* args)
2353{
2354 int err;
2355 char delim;
2356
2357 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2358 PyErr_Clear();
2359 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2360 return NULL;
2361 }
2362
2363 CHECK_DB_NOT_CLOSED(self);
2364
2365 MYDB_BEGIN_ALLOW_THREADS;
2366 err = self->db->set_re_delim(self->db, delim);
2367 MYDB_END_ALLOW_THREADS;
2368 RETURN_IF_ERR();
2369 RETURN_NONE();
2370}
2371
2372static PyObject*
2373DB_set_re_len(DBObject* self, PyObject* args)
2374{
2375 int err, len;
2376
2377 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2378 return NULL;
2379 CHECK_DB_NOT_CLOSED(self);
2380
2381 MYDB_BEGIN_ALLOW_THREADS;
2382 err = self->db->set_re_len(self->db, len);
2383 MYDB_END_ALLOW_THREADS;
2384 RETURN_IF_ERR();
2385 RETURN_NONE();
2386}
2387
2388
2389static PyObject*
2390DB_set_re_pad(DBObject* self, PyObject* args)
2391{
2392 int err;
2393 char pad;
2394
2395 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2396 PyErr_Clear();
2397 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2398 return NULL;
2399 }
2400 CHECK_DB_NOT_CLOSED(self);
2401
2402 MYDB_BEGIN_ALLOW_THREADS;
2403 err = self->db->set_re_pad(self->db, pad);
2404 MYDB_END_ALLOW_THREADS;
2405 RETURN_IF_ERR();
2406 RETURN_NONE();
2407}
2408
2409
2410static PyObject*
2411DB_set_re_source(DBObject* self, PyObject* args)
2412{
2413 int err;
2414 char *re_source;
2415
2416 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2417 return NULL;
2418 CHECK_DB_NOT_CLOSED(self);
2419
2420 MYDB_BEGIN_ALLOW_THREADS;
2421 err = self->db->set_re_source(self->db, re_source);
2422 MYDB_END_ALLOW_THREADS;
2423 RETURN_IF_ERR();
2424 RETURN_NONE();
2425}
2426
2427
2428#if (DBVER >= 32)
2429static PyObject*
2430DB_set_q_extentsize(DBObject* self, PyObject* args)
2431{
2432 int err;
2433 int extentsize;
2434
2435 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2436 return NULL;
2437 CHECK_DB_NOT_CLOSED(self);
2438
2439 MYDB_BEGIN_ALLOW_THREADS;
2440 err = self->db->set_q_extentsize(self->db, extentsize);
2441 MYDB_END_ALLOW_THREADS;
2442 RETURN_IF_ERR();
2443 RETURN_NONE();
2444}
2445#endif
2446
2447static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002448DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002449{
2450 int err, flags = 0, type;
2451 void* sp;
2452 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002453#if (DBVER >= 43)
2454 PyObject* txnobj = NULL;
2455 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002456 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002457#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002458 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002459#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002460
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002461#if (DBVER >= 43)
2462 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2463 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002464 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002465 if (!checkTxnObj(txnobj, &txn))
2466 return NULL;
2467#else
2468 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2469 return NULL;
2470#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 CHECK_DB_NOT_CLOSED(self);
2472
2473 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002474#if (DBVER >= 43)
2475 err = self->db->stat(self->db, txn, &sp, flags);
2476#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002477 err = self->db->stat(self->db, &sp, flags);
2478#else
2479 err = self->db->stat(self->db, &sp, NULL, flags);
2480#endif
2481 MYDB_END_ALLOW_THREADS;
2482 RETURN_IF_ERR();
2483
2484 self->haveStat = 1;
2485
2486 /* Turn the stat structure into a dictionary */
2487 type = _DB_get_type(self);
2488 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2489 free(sp);
2490 return NULL;
2491 }
2492
2493#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2494#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2495#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2496
2497 switch (type) {
2498 case DB_HASH:
2499 MAKE_HASH_ENTRY(magic);
2500 MAKE_HASH_ENTRY(version);
2501 MAKE_HASH_ENTRY(nkeys);
2502 MAKE_HASH_ENTRY(ndata);
2503 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002504#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002505 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002506#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002507 MAKE_HASH_ENTRY(ffactor);
2508 MAKE_HASH_ENTRY(buckets);
2509 MAKE_HASH_ENTRY(free);
2510 MAKE_HASH_ENTRY(bfree);
2511 MAKE_HASH_ENTRY(bigpages);
2512 MAKE_HASH_ENTRY(big_bfree);
2513 MAKE_HASH_ENTRY(overflows);
2514 MAKE_HASH_ENTRY(ovfl_free);
2515 MAKE_HASH_ENTRY(dup);
2516 MAKE_HASH_ENTRY(dup_free);
2517 break;
2518
2519 case DB_BTREE:
2520 case DB_RECNO:
2521 MAKE_BT_ENTRY(magic);
2522 MAKE_BT_ENTRY(version);
2523 MAKE_BT_ENTRY(nkeys);
2524 MAKE_BT_ENTRY(ndata);
2525 MAKE_BT_ENTRY(pagesize);
2526 MAKE_BT_ENTRY(minkey);
2527 MAKE_BT_ENTRY(re_len);
2528 MAKE_BT_ENTRY(re_pad);
2529 MAKE_BT_ENTRY(levels);
2530 MAKE_BT_ENTRY(int_pg);
2531 MAKE_BT_ENTRY(leaf_pg);
2532 MAKE_BT_ENTRY(dup_pg);
2533 MAKE_BT_ENTRY(over_pg);
2534 MAKE_BT_ENTRY(free);
2535 MAKE_BT_ENTRY(int_pgfree);
2536 MAKE_BT_ENTRY(leaf_pgfree);
2537 MAKE_BT_ENTRY(dup_pgfree);
2538 MAKE_BT_ENTRY(over_pgfree);
2539 break;
2540
2541 case DB_QUEUE:
2542 MAKE_QUEUE_ENTRY(magic);
2543 MAKE_QUEUE_ENTRY(version);
2544 MAKE_QUEUE_ENTRY(nkeys);
2545 MAKE_QUEUE_ENTRY(ndata);
2546 MAKE_QUEUE_ENTRY(pagesize);
2547 MAKE_QUEUE_ENTRY(pages);
2548 MAKE_QUEUE_ENTRY(re_len);
2549 MAKE_QUEUE_ENTRY(re_pad);
2550 MAKE_QUEUE_ENTRY(pgfree);
2551#if (DBVER == 31)
2552 MAKE_QUEUE_ENTRY(start);
2553#endif
2554 MAKE_QUEUE_ENTRY(first_recno);
2555 MAKE_QUEUE_ENTRY(cur_recno);
2556 break;
2557
2558 default:
2559 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2560 Py_DECREF(d);
2561 d = NULL;
2562 }
2563
2564#undef MAKE_HASH_ENTRY
2565#undef MAKE_BT_ENTRY
2566#undef MAKE_QUEUE_ENTRY
2567
2568 free(sp);
2569 return d;
2570}
2571
2572static PyObject*
2573DB_sync(DBObject* self, PyObject* args)
2574{
2575 int err;
2576 int flags = 0;
2577
2578 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2579 return NULL;
2580 CHECK_DB_NOT_CLOSED(self);
2581
2582 MYDB_BEGIN_ALLOW_THREADS;
2583 err = self->db->sync(self->db, flags);
2584 MYDB_END_ALLOW_THREADS;
2585 RETURN_IF_ERR();
2586 RETURN_NONE();
2587}
2588
2589
2590#if (DBVER >= 33)
2591static PyObject*
2592DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2593{
2594 int err, flags=0;
2595 u_int32_t count=0;
2596 PyObject* txnobj = NULL;
2597 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002598 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002599
2600 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2601 &txnobj, &flags))
2602 return NULL;
2603 CHECK_DB_NOT_CLOSED(self);
2604 if (!checkTxnObj(txnobj, &txn))
2605 return NULL;
2606
2607 MYDB_BEGIN_ALLOW_THREADS;
2608 err = self->db->truncate(self->db, txn, &count, flags);
2609 MYDB_END_ALLOW_THREADS;
2610 RETURN_IF_ERR();
2611 return PyInt_FromLong(count);
2612}
2613#endif
2614
2615
2616static PyObject*
2617DB_upgrade(DBObject* self, PyObject* args)
2618{
2619 int err, flags=0;
2620 char *filename;
2621
2622 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2623 return NULL;
2624 CHECK_DB_NOT_CLOSED(self);
2625
2626 MYDB_BEGIN_ALLOW_THREADS;
2627 err = self->db->upgrade(self->db, filename, flags);
2628 MYDB_END_ALLOW_THREADS;
2629 RETURN_IF_ERR();
2630 RETURN_NONE();
2631}
2632
2633
2634static PyObject*
2635DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2636{
2637 int err, flags=0;
2638 char* fileName;
2639 char* dbName=NULL;
2640 char* outFileName=NULL;
2641 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002642 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002643 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644
2645 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2646 &fileName, &dbName, &outFileName, &flags))
2647 return NULL;
2648
2649 CHECK_DB_NOT_CLOSED(self);
2650 if (outFileName)
2651 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002652 /* XXX(nnorwitz): it should probably be an exception if outFile
2653 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654
2655 MYDB_BEGIN_ALLOW_THREADS;
2656 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2657 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002658 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002659 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002660
2661 /* DB.verify acts as a DB handle destructor (like close); this was
2662 * documented in BerkeleyDB 4.2 but had the undocumented effect
2663 * of not being safe in prior versions while still requiring an explicit
2664 * DB.close call afterwards. Lets call close for the user to emulate
2665 * the safe 4.2 behaviour. */
2666#if (DBVER <= 41)
2667 self->db->close(self->db, 0);
2668#endif
2669 self->db = NULL;
2670
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002671 RETURN_IF_ERR();
2672 RETURN_NONE();
2673}
2674
2675
2676static PyObject*
2677DB_set_get_returns_none(DBObject* self, PyObject* args)
2678{
2679 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002680 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002681
2682 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2683 return NULL;
2684 CHECK_DB_NOT_CLOSED(self);
2685
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002686 if (self->moduleFlags.getReturnsNone)
2687 ++oldValue;
2688 if (self->moduleFlags.cursorSetReturnsNone)
2689 ++oldValue;
2690 self->moduleFlags.getReturnsNone = (flags >= 1);
2691 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692 return PyInt_FromLong(oldValue);
2693}
2694
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002695#if (DBVER >= 41)
2696static PyObject*
2697DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2698{
2699 int err;
2700 u_int32_t flags=0;
2701 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002702 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002703
2704 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2705 &passwd, &flags)) {
2706 return NULL;
2707 }
2708
2709 MYDB_BEGIN_ALLOW_THREADS;
2710 err = self->db->set_encrypt(self->db, passwd, flags);
2711 MYDB_END_ALLOW_THREADS;
2712
2713 RETURN_IF_ERR();
2714 RETURN_NONE();
2715}
2716#endif /* DBVER >= 41 */
2717
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002718
2719/*-------------------------------------------------------------- */
2720/* Mapping and Dictionary-like access routines */
2721
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002722Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723{
2724 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002725 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726 int flags = 0;
2727 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002728 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002729
2730 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002731 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2732 PyErr_SetObject(DBError, t);
2733 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 return -1;
2735 }
2736
2737 if (self->haveStat) { /* Has the stat function been called recently? If
2738 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002739 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 }
2741
2742 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002743redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002744#if (DBVER >= 43)
2745 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2746#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 err = self->db->stat(self->db, &sp, flags);
2748#else
2749 err = self->db->stat(self->db, &sp, NULL, flags);
2750#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002751
2752 /* All the stat structures have matching fields upto the ndata field,
2753 so we can use any of them for the type cast */
2754 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2755
2756 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2757 * redo a full stat to make sure.
2758 * Fixes SF python bug 1493322, pybsddb bug 1184012
2759 */
2760 if (size == 0 && (flags & DB_FAST_STAT)) {
2761 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002762 if (!err)
2763 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002764 goto redo_stat_for_length;
2765 }
2766
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002767 MYDB_END_ALLOW_THREADS;
2768
2769 if (err)
2770 return -1;
2771
2772 self->haveStat = 1;
2773
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002774 free(sp);
2775 return size;
2776}
2777
2778
2779PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2780{
2781 int err;
2782 PyObject* retval;
2783 DBT key;
2784 DBT data;
2785
2786 CHECK_DB_NOT_CLOSED(self);
2787 if (!make_key_dbt(self, keyobj, &key, NULL))
2788 return NULL;
2789
2790 CLEAR_DBT(data);
2791 if (CHECK_DBFLAG(self, DB_THREAD)) {
2792 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2793 data.flags = DB_DBT_MALLOC;
2794 }
2795 MYDB_BEGIN_ALLOW_THREADS;
2796 err = self->db->get(self->db, NULL, &key, &data, 0);
2797 MYDB_END_ALLOW_THREADS;
2798 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2799 PyErr_SetObject(PyExc_KeyError, keyobj);
2800 retval = NULL;
2801 }
2802 else if (makeDBError(err)) {
2803 retval = NULL;
2804 }
2805 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002806 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002807 FREE_DBT(data);
2808 }
2809
2810 FREE_DBT(key);
2811 return retval;
2812}
2813
2814
2815static int
2816DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2817{
2818 DBT key, data;
2819 int retval;
2820 int flags = 0;
2821
2822 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002823 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2824 PyErr_SetObject(DBError, t);
2825 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002826 return -1;
2827 }
2828
2829 if (!make_key_dbt(self, keyobj, &key, NULL))
2830 return -1;
2831
2832 if (dataobj != NULL) {
2833 if (!make_dbt(dataobj, &data))
2834 retval = -1;
2835 else {
2836 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002837 /* dictionaries shouldn't have duplicate keys */
2838 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 retval = _DB_put(self, NULL, &key, &data, flags);
2840
2841 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002842 /* try deleting any old record that matches and then PUT it
2843 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002844 _DB_delete(self, NULL, &key, 0);
2845 PyErr_Clear();
2846 retval = _DB_put(self, NULL, &key, &data, flags);
2847 }
2848 }
2849 }
2850 else {
2851 /* dataobj == NULL, so delete the key */
2852 retval = _DB_delete(self, NULL, &key, 0);
2853 }
2854 FREE_DBT(key);
2855 return retval;
2856}
2857
2858
2859static PyObject*
2860DB_has_key(DBObject* self, PyObject* args)
2861{
2862 int err;
2863 PyObject* keyobj;
2864 DBT key, data;
2865 PyObject* txnobj = NULL;
2866 DB_TXN *txn = NULL;
2867
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002868 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 return NULL;
2870 CHECK_DB_NOT_CLOSED(self);
2871 if (!make_key_dbt(self, keyobj, &key, NULL))
2872 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002873 if (!checkTxnObj(txnobj, &txn)) {
2874 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002876 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002877
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002878 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879 it has a record but can't allocate a buffer for the data. This saves
2880 having to deal with data we won't be using.
2881 */
2882 CLEAR_DBT(data);
2883 data.flags = DB_DBT_USERMEM;
2884
2885 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002886 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002887 MYDB_END_ALLOW_THREADS;
2888 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002889
2890 if (err == DB_BUFFER_SMALL || err == 0) {
2891 return PyInt_FromLong(1);
2892 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2893 return PyInt_FromLong(0);
2894 }
2895
2896 makeDBError(err);
2897 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002898}
2899
2900
2901#define _KEYS_LIST 1
2902#define _VALUES_LIST 2
2903#define _ITEMS_LIST 3
2904
2905static PyObject*
2906_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2907{
2908 int err, dbtype;
2909 DBT key;
2910 DBT data;
2911 DBC *cursor;
2912 PyObject* list;
2913 PyObject* item = NULL;
2914
2915 CHECK_DB_NOT_CLOSED(self);
2916 CLEAR_DBT(key);
2917 CLEAR_DBT(data);
2918
2919 dbtype = _DB_get_type(self);
2920 if (dbtype == -1)
2921 return NULL;
2922
2923 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002924 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002926
2927 /* get a cursor */
2928 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002929 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002930 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002931 if (makeDBError(err)) {
2932 Py_DECREF(list);
2933 return NULL;
2934 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002935
2936 if (CHECK_DBFLAG(self, DB_THREAD)) {
2937 key.flags = DB_DBT_REALLOC;
2938 data.flags = DB_DBT_REALLOC;
2939 }
2940
2941 while (1) { /* use the cursor to traverse the DB, collecting items */
2942 MYDB_BEGIN_ALLOW_THREADS;
2943 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2944 MYDB_END_ALLOW_THREADS;
2945
2946 if (err) {
2947 /* for any error, break out of the loop */
2948 break;
2949 }
2950
2951 switch (type) {
2952 case _KEYS_LIST:
2953 switch(dbtype) {
2954 case DB_BTREE:
2955 case DB_HASH:
2956 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002957 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002958 break;
2959 case DB_RECNO:
2960 case DB_QUEUE:
2961 item = PyInt_FromLong(*((db_recno_t*)key.data));
2962 break;
2963 }
2964 break;
2965
2966 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002967 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002968 break;
2969
2970 case _ITEMS_LIST:
2971 switch(dbtype) {
2972 case DB_BTREE:
2973 case DB_HASH:
2974 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002975 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002976 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002977 break;
2978 case DB_RECNO:
2979 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002980 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002981 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 break;
2983 }
2984 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002985 default:
2986 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2987 item = NULL;
2988 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002989 }
2990 if (item == NULL) {
2991 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002992 list = NULL;
2993 goto done;
2994 }
2995 PyList_Append(list, item);
2996 Py_DECREF(item);
2997 }
2998
Gregory P. Smithe9477062005-06-04 06:46:59 +00002999 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3000 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003001 Py_DECREF(list);
3002 list = NULL;
3003 }
3004
3005 done:
3006 FREE_DBT(key);
3007 FREE_DBT(data);
3008 MYDB_BEGIN_ALLOW_THREADS;
3009 cursor->c_close(cursor);
3010 MYDB_END_ALLOW_THREADS;
3011 return list;
3012}
3013
3014
3015static PyObject*
3016DB_keys(DBObject* self, PyObject* args)
3017{
3018 PyObject* txnobj = NULL;
3019 DB_TXN *txn = NULL;
3020
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003021 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003022 return NULL;
3023 if (!checkTxnObj(txnobj, &txn))
3024 return NULL;
3025 return _DB_make_list(self, txn, _KEYS_LIST);
3026}
3027
3028
3029static PyObject*
3030DB_items(DBObject* self, PyObject* args)
3031{
3032 PyObject* txnobj = NULL;
3033 DB_TXN *txn = NULL;
3034
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003035 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036 return NULL;
3037 if (!checkTxnObj(txnobj, &txn))
3038 return NULL;
3039 return _DB_make_list(self, txn, _ITEMS_LIST);
3040}
3041
3042
3043static PyObject*
3044DB_values(DBObject* self, PyObject* args)
3045{
3046 PyObject* txnobj = NULL;
3047 DB_TXN *txn = NULL;
3048
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003049 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 return NULL;
3051 if (!checkTxnObj(txnobj, &txn))
3052 return NULL;
3053 return _DB_make_list(self, txn, _VALUES_LIST);
3054}
3055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003056/* --------------------------------------------------------------------- */
3057/* DBCursor methods */
3058
3059
3060static PyObject*
3061DBC_close(DBCursorObject* self, PyObject* args)
3062{
3063 int err = 0;
3064
3065 if (!PyArg_ParseTuple(args, ":close"))
3066 return NULL;
3067
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068 if (self->dbc != NULL) {
3069 MYDB_BEGIN_ALLOW_THREADS;
3070 err = self->dbc->c_close(self->dbc);
3071 self->dbc = NULL;
3072 MYDB_END_ALLOW_THREADS;
3073 }
3074 RETURN_IF_ERR();
3075 RETURN_NONE();
3076}
3077
3078
3079static PyObject*
3080DBC_count(DBCursorObject* self, PyObject* args)
3081{
3082 int err = 0;
3083 db_recno_t count;
3084 int flags = 0;
3085
3086 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3087 return NULL;
3088
3089 CHECK_CURSOR_NOT_CLOSED(self);
3090
3091 MYDB_BEGIN_ALLOW_THREADS;
3092 err = self->dbc->c_count(self->dbc, &count, flags);
3093 MYDB_END_ALLOW_THREADS;
3094 RETURN_IF_ERR();
3095
3096 return PyInt_FromLong(count);
3097}
3098
3099
3100static PyObject*
3101DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3102{
3103 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3104}
3105
3106
3107static PyObject*
3108DBC_delete(DBCursorObject* self, PyObject* args)
3109{
3110 int err, flags=0;
3111
3112 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3113 return NULL;
3114
3115 CHECK_CURSOR_NOT_CLOSED(self);
3116
3117 MYDB_BEGIN_ALLOW_THREADS;
3118 err = self->dbc->c_del(self->dbc, flags);
3119 MYDB_END_ALLOW_THREADS;
3120 RETURN_IF_ERR();
3121
3122 self->mydb->haveStat = 0;
3123 RETURN_NONE();
3124}
3125
3126
3127static PyObject*
3128DBC_dup(DBCursorObject* self, PyObject* args)
3129{
3130 int err, flags =0;
3131 DBC* dbc = NULL;
3132
3133 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3134 return NULL;
3135
3136 CHECK_CURSOR_NOT_CLOSED(self);
3137
3138 MYDB_BEGIN_ALLOW_THREADS;
3139 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3140 MYDB_END_ALLOW_THREADS;
3141 RETURN_IF_ERR();
3142
3143 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3144}
3145
3146static PyObject*
3147DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3148{
3149 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3150}
3151
3152
3153static PyObject*
3154DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3155{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003156 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157 PyObject* keyobj = NULL;
3158 PyObject* dataobj = NULL;
3159 PyObject* retval = NULL;
3160 int dlen = -1;
3161 int doff = -1;
3162 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003163 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003164 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165
3166 CLEAR_DBT(key);
3167 CLEAR_DBT(data);
3168 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003169 &flags, &dlen, &doff))
3170 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003171 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003172 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3173 &kwnames[1],
3174 &keyobj, &flags, &dlen, &doff))
3175 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003177 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3178 kwnames, &keyobj, &dataobj,
3179 &flags, &dlen, &doff))
3180 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003181 return NULL;
3182 }
3183 }
3184 }
3185
3186 CHECK_CURSOR_NOT_CLOSED(self);
3187
3188 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3189 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003190 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3191 (!add_partial_dbt(&data, dlen, doff)) )
3192 {
3193 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196
3197 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3198 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003199 if (!(key.flags & DB_DBT_REALLOC)) {
3200 key.flags |= DB_DBT_MALLOC;
3201 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003202 }
3203
3204 MYDB_BEGIN_ALLOW_THREADS;
3205 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3206 MYDB_END_ALLOW_THREADS;
3207
Gregory P. Smithe9477062005-06-04 06:46:59 +00003208 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3209 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 Py_INCREF(Py_None);
3211 retval = Py_None;
3212 }
3213 else if (makeDBError(err)) {
3214 retval = NULL;
3215 }
3216 else {
3217 switch (_DB_get_type(self->mydb)) {
3218 case -1:
3219 retval = NULL;
3220 break;
3221 case DB_BTREE:
3222 case DB_HASH:
3223 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003224 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225 data.data, data.size);
3226 break;
3227 case DB_RECNO:
3228 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003229 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003230 data.data, data.size);
3231 break;
3232 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003233 FREE_DBT(data);
3234 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003235 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003236 return retval;
3237}
3238
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003239#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003240static PyObject*
3241DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3242{
3243 int err, flags=0;
3244 PyObject* keyobj = NULL;
3245 PyObject* dataobj = NULL;
3246 PyObject* retval = NULL;
3247 int dlen = -1;
3248 int doff = -1;
3249 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003250 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3251 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003252
3253 CLEAR_DBT(key);
3254 CLEAR_DBT(data);
3255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3256 &flags, &dlen, &doff))
3257 {
3258 PyErr_Clear();
3259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003260 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003261 &keyobj, &flags, &dlen, &doff))
3262 {
3263 PyErr_Clear();
3264 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3265 kwnames, &keyobj, &dataobj,
3266 &flags, &dlen, &doff))
3267 {
3268 return NULL;
3269 }
3270 }
3271 }
3272
3273 CHECK_CURSOR_NOT_CLOSED(self);
3274
3275 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3276 return NULL;
3277 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3278 (!add_partial_dbt(&data, dlen, doff)) ) {
3279 FREE_DBT(key);
3280 return NULL;
3281 }
3282
3283 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3284 data.flags = DB_DBT_MALLOC;
3285 if (!(key.flags & DB_DBT_REALLOC)) {
3286 key.flags |= DB_DBT_MALLOC;
3287 }
3288 }
3289
3290 CLEAR_DBT(pkey);
3291 pkey.flags = DB_DBT_MALLOC;
3292
3293 MYDB_BEGIN_ALLOW_THREADS;
3294 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3295 MYDB_END_ALLOW_THREADS;
3296
Gregory P. Smithe9477062005-06-04 06:46:59 +00003297 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3298 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 Py_INCREF(Py_None);
3300 retval = Py_None;
3301 }
3302 else if (makeDBError(err)) {
3303 retval = NULL;
3304 }
3305 else {
3306 PyObject *pkeyObj;
3307 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003308 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003309
3310 if (self->mydb->primaryDBType == DB_RECNO ||
3311 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003312 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003314 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003316 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003317 {
3318 PyObject *keyObj;
3319 int type = _DB_get_type(self->mydb);
3320 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003321 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003322 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003323 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003324#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003325 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003326#else
3327 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3328#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003329 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003330 FREE_DBT(key);
3331 }
3332 else /* return just the pkey and data */
3333 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003334#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003335 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003336#else
3337 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3338#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003339 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003340 Py_DECREF(dataObj);
3341 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003342 FREE_DBT(pkey);
3343 FREE_DBT(data);
3344 }
3345 /* the only time REALLOC should be set is if we used an integer
3346 * key that make_key_dbt malloc'd for us. always free these. */
3347 if (key.flags & DB_DBT_REALLOC) {
3348 FREE_DBT(key);
3349 }
3350 return retval;
3351}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003352#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003353
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354
3355static PyObject*
3356DBC_get_recno(DBCursorObject* self, PyObject* args)
3357{
3358 int err;
3359 db_recno_t recno;
3360 DBT key;
3361 DBT data;
3362
3363 if (!PyArg_ParseTuple(args, ":get_recno"))
3364 return NULL;
3365
3366 CHECK_CURSOR_NOT_CLOSED(self);
3367
3368 CLEAR_DBT(key);
3369 CLEAR_DBT(data);
3370 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3371 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3372 data.flags = DB_DBT_MALLOC;
3373 key.flags = DB_DBT_MALLOC;
3374 }
3375
3376 MYDB_BEGIN_ALLOW_THREADS;
3377 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3378 MYDB_END_ALLOW_THREADS;
3379 RETURN_IF_ERR();
3380
3381 recno = *((db_recno_t*)data.data);
3382 FREE_DBT(key);
3383 FREE_DBT(data);
3384 return PyInt_FromLong(recno);
3385}
3386
3387
3388static PyObject*
3389DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3390{
3391 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3392}
3393
3394
3395static PyObject*
3396DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3397{
3398 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3399}
3400
3401
3402static PyObject*
3403DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3404{
3405 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3406}
3407
3408
3409static PyObject*
3410DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3411{
3412 int err, flags = 0;
3413 PyObject* keyobj, *dataobj;
3414 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003415 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003416 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 int dlen = -1;
3418 int doff = -1;
3419
3420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3421 &keyobj, &dataobj, &flags, &dlen, &doff))
3422 return NULL;
3423
3424 CHECK_CURSOR_NOT_CLOSED(self);
3425
3426 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3427 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003428 if (!make_dbt(dataobj, &data) ||
3429 !add_partial_dbt(&data, dlen, doff) )
3430 {
3431 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003433 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003434
3435 MYDB_BEGIN_ALLOW_THREADS;
3436 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3437 MYDB_END_ALLOW_THREADS;
3438 FREE_DBT(key);
3439 RETURN_IF_ERR();
3440 self->mydb->haveStat = 0;
3441 RETURN_NONE();
3442}
3443
3444
3445static PyObject*
3446DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3447{
3448 int err, flags = 0;
3449 DBT key, data;
3450 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003451 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452 int dlen = -1;
3453 int doff = -1;
3454
3455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3456 &keyobj, &flags, &dlen, &doff))
3457 return NULL;
3458
3459 CHECK_CURSOR_NOT_CLOSED(self);
3460
3461 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3462 return NULL;
3463
3464 CLEAR_DBT(data);
3465 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3466 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3467 data.flags = DB_DBT_MALLOC;
3468 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003469 if (!add_partial_dbt(&data, dlen, doff)) {
3470 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003472 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473
3474 MYDB_BEGIN_ALLOW_THREADS;
3475 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3476 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003477 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3478 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003479 Py_INCREF(Py_None);
3480 retval = Py_None;
3481 }
3482 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003483 retval = NULL;
3484 }
3485 else {
3486 switch (_DB_get_type(self->mydb)) {
3487 case -1:
3488 retval = NULL;
3489 break;
3490 case DB_BTREE:
3491 case DB_HASH:
3492 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003493 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494 data.data, data.size);
3495 break;
3496 case DB_RECNO:
3497 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003498 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003499 data.data, data.size);
3500 break;
3501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003502 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003503 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003504 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003505 /* the only time REALLOC should be set is if we used an integer
3506 * key that make_key_dbt malloc'd for us. always free these. */
3507 if (key.flags & DB_DBT_REALLOC) {
3508 FREE_DBT(key);
3509 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003510
3511 return retval;
3512}
3513
3514
3515static PyObject*
3516DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3517{
3518 int err, flags = 0;
3519 DBT key, data;
3520 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003521 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003522 int dlen = -1;
3523 int doff = -1;
3524
3525 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3526 &keyobj, &flags, &dlen, &doff))
3527 return NULL;
3528
3529 CHECK_CURSOR_NOT_CLOSED(self);
3530
3531 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3532 return NULL;
3533
3534 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003535 if (!add_partial_dbt(&data, dlen, doff)) {
3536 FREE_DBT(key);
3537 return NULL;
3538 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003539 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3540 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003541 data.flags |= DB_DBT_MALLOC;
3542 /* only BTREE databases will return anything in the key */
3543 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3544 key.flags |= DB_DBT_MALLOC;
3545 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003546 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 MYDB_BEGIN_ALLOW_THREADS;
3548 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3549 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003550 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3551 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003552 Py_INCREF(Py_None);
3553 retval = Py_None;
3554 }
3555 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556 retval = NULL;
3557 }
3558 else {
3559 switch (_DB_get_type(self->mydb)) {
3560 case -1:
3561 retval = NULL;
3562 break;
3563 case DB_BTREE:
3564 case DB_HASH:
3565 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003566 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567 data.data, data.size);
3568 break;
3569 case DB_RECNO:
3570 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003571 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572 data.data, data.size);
3573 break;
3574 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003575 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576 FREE_DBT(data);
3577 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003578 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003579 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003580 if (key.flags & DB_DBT_REALLOC) {
3581 FREE_DBT(key);
3582 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583
3584 return retval;
3585}
3586
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003588_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3589 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003591 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003593 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594
Gregory P. Smith7441e652003-11-03 21:35:31 +00003595 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3597 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003598 if (!make_dbt(dataobj, &data)) {
3599 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003601 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602
3603 MYDB_BEGIN_ALLOW_THREADS;
3604 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3605 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003606 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003607 Py_INCREF(Py_None);
3608 retval = Py_None;
3609 }
3610 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611 retval = NULL;
3612 }
3613 else {
3614 switch (_DB_get_type(self->mydb)) {
3615 case -1:
3616 retval = NULL;
3617 break;
3618 case DB_BTREE:
3619 case DB_HASH:
3620 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003621 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003622 data.data, data.size);
3623 break;
3624 case DB_RECNO:
3625 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003626 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003627 data.data, data.size);
3628 break;
3629 }
3630 }
3631
3632 FREE_DBT(key);
3633 return retval;
3634}
3635
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003636static PyObject*
3637DBC_get_both(DBCursorObject* self, PyObject* args)
3638{
3639 int flags=0;
3640 PyObject *keyobj, *dataobj;
3641
3642 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3643 return NULL;
3644
Gregory P. Smith7441e652003-11-03 21:35:31 +00003645 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003646 CHECK_CURSOR_NOT_CLOSED(self);
3647
3648 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3649 self->mydb->moduleFlags.getReturnsNone);
3650}
3651
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003652/* Return size of entry */
3653static PyObject*
3654DBC_get_current_size(DBCursorObject* self, PyObject* args)
3655{
3656 int err, flags=DB_CURRENT;
3657 PyObject* retval = NULL;
3658 DBT key, data;
3659
3660 if (!PyArg_ParseTuple(args, ":get_current_size"))
3661 return NULL;
3662 CHECK_CURSOR_NOT_CLOSED(self);
3663 CLEAR_DBT(key);
3664 CLEAR_DBT(data);
3665
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003666 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003667 getting the record size. */
3668 data.flags = DB_DBT_USERMEM;
3669 data.ulen = 0;
3670 MYDB_BEGIN_ALLOW_THREADS;
3671 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3672 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003673 if (err == DB_BUFFER_SMALL || !err) {
3674 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003675 retval = PyInt_FromLong((long)data.size);
3676 err = 0;
3677 }
3678
3679 FREE_DBT(key);
3680 FREE_DBT(data);
3681 RETURN_IF_ERR();
3682 return retval;
3683}
3684
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003685static PyObject*
3686DBC_set_both(DBCursorObject* self, PyObject* args)
3687{
3688 int flags=0;
3689 PyObject *keyobj, *dataobj;
3690
3691 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3692 return NULL;
3693
Gregory P. Smith7441e652003-11-03 21:35:31 +00003694 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003695 CHECK_CURSOR_NOT_CLOSED(self);
3696
3697 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3698 self->mydb->moduleFlags.cursorSetReturnsNone);
3699}
3700
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701
3702static PyObject*
3703DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3704{
3705 int err, irecno, flags=0;
3706 db_recno_t recno;
3707 DBT key, data;
3708 PyObject* retval;
3709 int dlen = -1;
3710 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003711 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712
3713 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3714 &irecno, &flags, &dlen, &doff))
3715 return NULL;
3716
3717 CHECK_CURSOR_NOT_CLOSED(self);
3718
3719 CLEAR_DBT(key);
3720 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003721 /* use allocated space so DB will be able to realloc room for the real
3722 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003723 key.data = malloc(sizeof(db_recno_t));
3724 if (key.data == NULL) {
3725 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3726 return NULL;
3727 }
3728 key.size = sizeof(db_recno_t);
3729 key.ulen = key.size;
3730 memcpy(key.data, &recno, sizeof(db_recno_t));
3731 key.flags = DB_DBT_REALLOC;
3732
3733 CLEAR_DBT(data);
3734 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3735 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3736 data.flags = DB_DBT_MALLOC;
3737 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003738 if (!add_partial_dbt(&data, dlen, doff)) {
3739 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003740 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003741 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003742
3743 MYDB_BEGIN_ALLOW_THREADS;
3744 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3745 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003746 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3747 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003748 Py_INCREF(Py_None);
3749 retval = Py_None;
3750 }
3751 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003752 retval = NULL;
3753 }
3754 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003755 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003756 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757 FREE_DBT(data);
3758 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003759 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003760
3761 return retval;
3762}
3763
3764
3765static PyObject*
3766DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3767{
3768 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3769}
3770
3771
3772static PyObject*
3773DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3774{
3775 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3776}
3777
3778
3779static PyObject*
3780DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3781{
3782 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3783}
3784
3785
3786static PyObject*
3787DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3788{
3789 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3790}
3791
3792
3793static PyObject*
3794DBC_join_item(DBCursorObject* self, PyObject* args)
3795{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003796 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003797 DBT key, data;
3798 PyObject* retval;
3799
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003800 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003801 return NULL;
3802
3803 CHECK_CURSOR_NOT_CLOSED(self);
3804
3805 CLEAR_DBT(key);
3806 CLEAR_DBT(data);
3807 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3808 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3809 key.flags = DB_DBT_MALLOC;
3810 }
3811
3812 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003813 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003814 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003815 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3816 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003817 Py_INCREF(Py_None);
3818 retval = Py_None;
3819 }
3820 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003821 retval = NULL;
3822 }
3823 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003824 retval = Py_BuildValue("y#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003825 FREE_DBT(key);
3826 }
3827
3828 return retval;
3829}
3830
3831
3832
3833/* --------------------------------------------------------------------- */
3834/* DBEnv methods */
3835
3836
3837static PyObject*
3838DBEnv_close(DBEnvObject* self, PyObject* args)
3839{
3840 int err, flags = 0;
3841
3842 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3843 return NULL;
3844 if (!self->closed) { /* Don't close more than once */
3845 MYDB_BEGIN_ALLOW_THREADS;
3846 err = self->db_env->close(self->db_env, flags);
3847 MYDB_END_ALLOW_THREADS;
3848 /* after calling DBEnv->close, regardless of error, this DBEnv
3849 * may not be accessed again (BerkeleyDB docs). */
3850 self->closed = 1;
3851 self->db_env = NULL;
3852 RETURN_IF_ERR();
3853 }
3854 RETURN_NONE();
3855}
3856
3857
3858static PyObject*
3859DBEnv_open(DBEnvObject* self, PyObject* args)
3860{
3861 int err, flags=0, mode=0660;
3862 char *db_home;
3863
3864 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3865 return NULL;
3866
3867 CHECK_ENV_NOT_CLOSED(self);
3868
3869 MYDB_BEGIN_ALLOW_THREADS;
3870 err = self->db_env->open(self->db_env, db_home, flags, mode);
3871 MYDB_END_ALLOW_THREADS;
3872 RETURN_IF_ERR();
3873 self->closed = 0;
3874 self->flags = flags;
3875 RETURN_NONE();
3876}
3877
3878
3879static PyObject*
3880DBEnv_remove(DBEnvObject* self, PyObject* args)
3881{
3882 int err, flags=0;
3883 char *db_home;
3884
3885 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3886 return NULL;
3887 CHECK_ENV_NOT_CLOSED(self);
3888 MYDB_BEGIN_ALLOW_THREADS;
3889 err = self->db_env->remove(self->db_env, db_home, flags);
3890 MYDB_END_ALLOW_THREADS;
3891 RETURN_IF_ERR();
3892 RETURN_NONE();
3893}
3894
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003895#if (DBVER >= 41)
3896static PyObject*
3897DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3898{
3899 int err;
3900 u_int32_t flags=0;
3901 char *file = NULL;
3902 char *database = NULL;
3903 PyObject *txnobj = NULL;
3904 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003905 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003906 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003907
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003908 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003909 &file, &database, &txnobj, &flags)) {
3910 return NULL;
3911 }
3912 if (!checkTxnObj(txnobj, &txn)) {
3913 return NULL;
3914 }
3915 CHECK_ENV_NOT_CLOSED(self);
3916 MYDB_BEGIN_ALLOW_THREADS;
3917 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3918 MYDB_END_ALLOW_THREADS;
3919 RETURN_IF_ERR();
3920 RETURN_NONE();
3921}
3922
3923static PyObject*
3924DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3925{
3926 int err;
3927 u_int32_t flags=0;
3928 char *file = NULL;
3929 char *database = NULL;
3930 char *newname = NULL;
3931 PyObject *txnobj = NULL;
3932 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003933 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003934 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003935
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003936 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003937 &file, &database, &newname, &txnobj, &flags)) {
3938 return NULL;
3939 }
3940 if (!checkTxnObj(txnobj, &txn)) {
3941 return NULL;
3942 }
3943 CHECK_ENV_NOT_CLOSED(self);
3944 MYDB_BEGIN_ALLOW_THREADS;
3945 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3946 flags);
3947 MYDB_END_ALLOW_THREADS;
3948 RETURN_IF_ERR();
3949 RETURN_NONE();
3950}
3951
3952static PyObject*
3953DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3954{
3955 int err;
3956 u_int32_t flags=0;
3957 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003958 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003959
3960 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3961 &passwd, &flags)) {
3962 return NULL;
3963 }
3964
3965 MYDB_BEGIN_ALLOW_THREADS;
3966 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3967 MYDB_END_ALLOW_THREADS;
3968
3969 RETURN_IF_ERR();
3970 RETURN_NONE();
3971}
3972#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003973
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003974#if (DBVER >= 40)
3975static PyObject*
3976DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3977{
3978 int err;
3979 u_int32_t flags=0;
3980 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003981 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003982
3983 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3984 &timeout, &flags)) {
3985 return NULL;
3986 }
3987
3988 MYDB_BEGIN_ALLOW_THREADS;
3989 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3990 MYDB_END_ALLOW_THREADS;
3991
3992 RETURN_IF_ERR();
3993 RETURN_NONE();
3994}
3995#endif /* DBVER >= 40 */
3996
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003997static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003998DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3999{
4000 int err;
4001 long shm_key = 0;
4002
4003 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4004 return NULL;
4005 CHECK_ENV_NOT_CLOSED(self);
4006
4007 err = self->db_env->set_shm_key(self->db_env, shm_key);
4008 RETURN_IF_ERR();
4009 RETURN_NONE();
4010}
4011
4012static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004013DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4014{
4015 int err, gbytes=0, bytes=0, ncache=0;
4016
4017 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4018 &gbytes, &bytes, &ncache))
4019 return NULL;
4020 CHECK_ENV_NOT_CLOSED(self);
4021
4022 MYDB_BEGIN_ALLOW_THREADS;
4023 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4024 MYDB_END_ALLOW_THREADS;
4025 RETURN_IF_ERR();
4026 RETURN_NONE();
4027}
4028
4029
4030#if (DBVER >= 32)
4031static PyObject*
4032DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4033{
4034 int err, flags=0, onoff=0;
4035
4036 if (!PyArg_ParseTuple(args, "ii:set_flags",
4037 &flags, &onoff))
4038 return NULL;
4039 CHECK_ENV_NOT_CLOSED(self);
4040
4041 MYDB_BEGIN_ALLOW_THREADS;
4042 err = self->db_env->set_flags(self->db_env, flags, onoff);
4043 MYDB_END_ALLOW_THREADS;
4044 RETURN_IF_ERR();
4045 RETURN_NONE();
4046}
4047#endif
4048
4049
4050static PyObject*
4051DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4052{
4053 int err;
4054 char *dir;
4055
4056 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4057 return NULL;
4058 CHECK_ENV_NOT_CLOSED(self);
4059
4060 MYDB_BEGIN_ALLOW_THREADS;
4061 err = self->db_env->set_data_dir(self->db_env, dir);
4062 MYDB_END_ALLOW_THREADS;
4063 RETURN_IF_ERR();
4064 RETURN_NONE();
4065}
4066
4067
4068static PyObject*
4069DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4070{
4071 int err, lg_bsize;
4072
4073 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4074 return NULL;
4075 CHECK_ENV_NOT_CLOSED(self);
4076
4077 MYDB_BEGIN_ALLOW_THREADS;
4078 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4079 MYDB_END_ALLOW_THREADS;
4080 RETURN_IF_ERR();
4081 RETURN_NONE();
4082}
4083
4084
4085static PyObject*
4086DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4087{
4088 int err;
4089 char *dir;
4090
4091 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4092 return NULL;
4093 CHECK_ENV_NOT_CLOSED(self);
4094
4095 MYDB_BEGIN_ALLOW_THREADS;
4096 err = self->db_env->set_lg_dir(self->db_env, dir);
4097 MYDB_END_ALLOW_THREADS;
4098 RETURN_IF_ERR();
4099 RETURN_NONE();
4100}
4101
4102static PyObject*
4103DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4104{
4105 int err, lg_max;
4106
4107 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4108 return NULL;
4109 CHECK_ENV_NOT_CLOSED(self);
4110
4111 MYDB_BEGIN_ALLOW_THREADS;
4112 err = self->db_env->set_lg_max(self->db_env, lg_max);
4113 MYDB_END_ALLOW_THREADS;
4114 RETURN_IF_ERR();
4115 RETURN_NONE();
4116}
4117
4118
Neal Norwitz84562352005-10-20 04:30:15 +00004119#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004120static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004121DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4122{
4123 int err, lg_max;
4124
4125 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4126 return NULL;
4127 CHECK_ENV_NOT_CLOSED(self);
4128
4129 MYDB_BEGIN_ALLOW_THREADS;
4130 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4131 MYDB_END_ALLOW_THREADS;
4132 RETURN_IF_ERR();
4133 RETURN_NONE();
4134}
Neal Norwitz84562352005-10-20 04:30:15 +00004135#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004136
4137
4138static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004139DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4140{
4141 int err, lk_detect;
4142
4143 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4144 return NULL;
4145 CHECK_ENV_NOT_CLOSED(self);
4146
4147 MYDB_BEGIN_ALLOW_THREADS;
4148 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4149 MYDB_END_ALLOW_THREADS;
4150 RETURN_IF_ERR();
4151 RETURN_NONE();
4152}
4153
4154
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004155#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004156static PyObject*
4157DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4158{
4159 int err, max;
4160
4161 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4162 return NULL;
4163 CHECK_ENV_NOT_CLOSED(self);
4164
4165 MYDB_BEGIN_ALLOW_THREADS;
4166 err = self->db_env->set_lk_max(self->db_env, max);
4167 MYDB_END_ALLOW_THREADS;
4168 RETURN_IF_ERR();
4169 RETURN_NONE();
4170}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004171#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004172
4173
4174#if (DBVER >= 32)
4175
4176static PyObject*
4177DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4178{
4179 int err, max;
4180
4181 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4182 return NULL;
4183 CHECK_ENV_NOT_CLOSED(self);
4184
4185 MYDB_BEGIN_ALLOW_THREADS;
4186 err = self->db_env->set_lk_max_locks(self->db_env, max);
4187 MYDB_END_ALLOW_THREADS;
4188 RETURN_IF_ERR();
4189 RETURN_NONE();
4190}
4191
4192
4193static PyObject*
4194DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4195{
4196 int err, max;
4197
4198 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4199 return NULL;
4200 CHECK_ENV_NOT_CLOSED(self);
4201
4202 MYDB_BEGIN_ALLOW_THREADS;
4203 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4204 MYDB_END_ALLOW_THREADS;
4205 RETURN_IF_ERR();
4206 RETURN_NONE();
4207}
4208
4209
4210static PyObject*
4211DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4212{
4213 int err, max;
4214
4215 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4216 return NULL;
4217 CHECK_ENV_NOT_CLOSED(self);
4218
4219 MYDB_BEGIN_ALLOW_THREADS;
4220 err = self->db_env->set_lk_max_objects(self->db_env, max);
4221 MYDB_END_ALLOW_THREADS;
4222 RETURN_IF_ERR();
4223 RETURN_NONE();
4224}
4225
4226#endif
4227
4228
4229static PyObject*
4230DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4231{
4232 int err, mp_mmapsize;
4233
4234 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4235 return NULL;
4236 CHECK_ENV_NOT_CLOSED(self);
4237
4238 MYDB_BEGIN_ALLOW_THREADS;
4239 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4240 MYDB_END_ALLOW_THREADS;
4241 RETURN_IF_ERR();
4242 RETURN_NONE();
4243}
4244
4245
4246static PyObject*
4247DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4248{
4249 int err;
4250 char *dir;
4251
4252 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4253 return NULL;
4254 CHECK_ENV_NOT_CLOSED(self);
4255
4256 MYDB_BEGIN_ALLOW_THREADS;
4257 err = self->db_env->set_tmp_dir(self->db_env, dir);
4258 MYDB_END_ALLOW_THREADS;
4259 RETURN_IF_ERR();
4260 RETURN_NONE();
4261}
4262
4263
4264static PyObject*
4265DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4266{
4267 int flags = 0;
4268 PyObject* txnobj = NULL;
4269 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004270 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004271
4272 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4273 &txnobj, &flags))
4274 return NULL;
4275
4276 if (!checkTxnObj(txnobj, &txn))
4277 return NULL;
4278 CHECK_ENV_NOT_CLOSED(self);
4279
4280 return (PyObject*)newDBTxnObject(self, txn, flags);
4281}
4282
4283
4284static PyObject*
4285DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4286{
4287 int err, kbyte=0, min=0, flags=0;
4288
4289 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4290 return NULL;
4291 CHECK_ENV_NOT_CLOSED(self);
4292
4293 MYDB_BEGIN_ALLOW_THREADS;
4294#if (DBVER >= 40)
4295 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4296#else
4297 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4298#endif
4299 MYDB_END_ALLOW_THREADS;
4300 RETURN_IF_ERR();
4301 RETURN_NONE();
4302}
4303
4304
4305static PyObject*
4306DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4307{
4308 int err, max;
4309
4310 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4313
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004314 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004315 RETURN_IF_ERR();
4316 RETURN_NONE();
4317}
4318
4319
4320static PyObject*
4321DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4322{
4323 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004324 long stamp;
4325 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004326
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004327 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004328 return NULL;
4329 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004330 timestamp = (time_t)stamp;
4331 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004332 RETURN_IF_ERR();
4333 RETURN_NONE();
4334}
4335
4336
4337static PyObject*
4338DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4339{
4340 int err, atype, flags=0;
4341 int aborted = 0;
4342
4343 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4344 return NULL;
4345 CHECK_ENV_NOT_CLOSED(self);
4346
4347 MYDB_BEGIN_ALLOW_THREADS;
4348#if (DBVER >= 40)
4349 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4350#else
4351 err = lock_detect(self->db_env, flags, atype, &aborted);
4352#endif
4353 MYDB_END_ALLOW_THREADS;
4354 RETURN_IF_ERR();
4355 return PyInt_FromLong(aborted);
4356}
4357
4358
4359static PyObject*
4360DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4361{
4362 int flags=0;
4363 int locker, lock_mode;
4364 DBT obj;
4365 PyObject* objobj;
4366
4367 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4368 return NULL;
4369
4370
4371 if (!make_dbt(objobj, &obj))
4372 return NULL;
4373
4374 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4375}
4376
4377
4378static PyObject*
4379DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4380{
4381 int err;
4382 u_int32_t theID;
4383
4384 if (!PyArg_ParseTuple(args, ":lock_id"))
4385 return NULL;
4386
4387 CHECK_ENV_NOT_CLOSED(self);
4388 MYDB_BEGIN_ALLOW_THREADS;
4389#if (DBVER >= 40)
4390 err = self->db_env->lock_id(self->db_env, &theID);
4391#else
4392 err = lock_id(self->db_env, &theID);
4393#endif
4394 MYDB_END_ALLOW_THREADS;
4395 RETURN_IF_ERR();
4396
4397 return PyInt_FromLong((long)theID);
4398}
4399
4400
4401static PyObject*
4402DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4403{
4404 int err;
4405 DBLockObject* dblockobj;
4406
4407 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4408 return NULL;
4409
4410 CHECK_ENV_NOT_CLOSED(self);
4411 MYDB_BEGIN_ALLOW_THREADS;
4412#if (DBVER >= 40)
4413 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4414#else
4415 err = lock_put(self->db_env, &dblockobj->lock);
4416#endif
4417 MYDB_END_ALLOW_THREADS;
4418 RETURN_IF_ERR();
4419 RETURN_NONE();
4420}
4421
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004422#if (DBVER >= 44)
4423static PyObject*
4424DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4425{
4426 int err;
4427 char *file;
4428 u_int32_t flags = 0;
4429 static char* kwnames[] = { "file", "flags", NULL};
4430
4431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4432 &file, &flags))
4433 return NULL;
4434 CHECK_ENV_NOT_CLOSED(self);
4435
4436 MYDB_BEGIN_ALLOW_THREADS;
4437 err = self->db_env->lsn_reset(self->db_env, file, flags);
4438 MYDB_END_ALLOW_THREADS;
4439 RETURN_IF_ERR();
4440 RETURN_NONE();
4441}
4442#endif /* DBVER >= 4.4 */
4443
4444#if (DBVER >= 40)
4445static PyObject*
4446DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4447{
4448 int err;
4449 DB_LOG_STAT* statp = NULL;
4450 PyObject* d = NULL;
4451 u_int32_t flags = 0;
4452
4453 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4454 return NULL;
4455 CHECK_ENV_NOT_CLOSED(self);
4456
4457 MYDB_BEGIN_ALLOW_THREADS;
4458 err = self->db_env->log_stat(self->db_env, &statp, flags);
4459 MYDB_END_ALLOW_THREADS;
4460 RETURN_IF_ERR();
4461
4462 /* Turn the stat structure into a dictionary */
4463 d = PyDict_New();
4464 if (d == NULL) {
4465 if (statp)
4466 free(statp);
4467 return NULL;
4468 }
4469
4470#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4471
4472 MAKE_ENTRY(magic);
4473 MAKE_ENTRY(version);
4474 MAKE_ENTRY(mode);
4475 MAKE_ENTRY(lg_bsize);
4476#if (DBVER >= 44)
4477 MAKE_ENTRY(lg_size);
4478 MAKE_ENTRY(record);
4479#endif
4480#if (DBVER <= 40)
4481 MAKE_ENTRY(lg_max);
4482#endif
4483 MAKE_ENTRY(w_mbytes);
4484 MAKE_ENTRY(w_bytes);
4485 MAKE_ENTRY(wc_mbytes);
4486 MAKE_ENTRY(wc_bytes);
4487 MAKE_ENTRY(wcount);
4488 MAKE_ENTRY(wcount_fill);
4489#if (DBVER >= 44)
4490 MAKE_ENTRY(rcount);
4491#endif
4492 MAKE_ENTRY(scount);
4493 MAKE_ENTRY(cur_file);
4494 MAKE_ENTRY(cur_offset);
4495 MAKE_ENTRY(disk_file);
4496 MAKE_ENTRY(disk_offset);
4497 MAKE_ENTRY(maxcommitperflush);
4498 MAKE_ENTRY(mincommitperflush);
4499 MAKE_ENTRY(regsize);
4500 MAKE_ENTRY(region_wait);
4501 MAKE_ENTRY(region_nowait);
4502
4503#undef MAKE_ENTRY
4504 free(statp);
4505 return d;
4506} /* DBEnv_log_stat */
4507#endif /* DBVER >= 4.0 for log_stat method */
4508
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004509
4510static PyObject*
4511DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4512{
4513 int err;
4514 DB_LOCK_STAT* sp;
4515 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004516 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004517
4518 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4519 return NULL;
4520 CHECK_ENV_NOT_CLOSED(self);
4521
4522 MYDB_BEGIN_ALLOW_THREADS;
4523#if (DBVER >= 40)
4524 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4525#else
4526#if (DBVER >= 33)
4527 err = lock_stat(self->db_env, &sp);
4528#else
4529 err = lock_stat(self->db_env, &sp, NULL);
4530#endif
4531#endif
4532 MYDB_END_ALLOW_THREADS;
4533 RETURN_IF_ERR();
4534
4535 /* Turn the stat structure into a dictionary */
4536 d = PyDict_New();
4537 if (d == NULL) {
4538 free(sp);
4539 return NULL;
4540 }
4541
4542#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4543
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004544#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004546#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547 MAKE_ENTRY(nmodes);
4548#if (DBVER >= 32)
4549 MAKE_ENTRY(maxlocks);
4550 MAKE_ENTRY(maxlockers);
4551 MAKE_ENTRY(maxobjects);
4552 MAKE_ENTRY(nlocks);
4553 MAKE_ENTRY(maxnlocks);
4554#endif
4555 MAKE_ENTRY(nlockers);
4556 MAKE_ENTRY(maxnlockers);
4557#if (DBVER >= 32)
4558 MAKE_ENTRY(nobjects);
4559 MAKE_ENTRY(maxnobjects);
4560#endif
4561 MAKE_ENTRY(nrequests);
4562 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004563#if (DBVER < 44)
4564 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004565 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004566#else
4567 MAKE_ENTRY(lock_nowait);
4568 MAKE_ENTRY(lock_wait);
4569#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004570 MAKE_ENTRY(ndeadlocks);
4571 MAKE_ENTRY(regsize);
4572 MAKE_ENTRY(region_wait);
4573 MAKE_ENTRY(region_nowait);
4574
4575#undef MAKE_ENTRY
4576 free(sp);
4577 return d;
4578}
4579
4580
4581static PyObject*
4582DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4583{
4584 int flags=0;
4585 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004586 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 PyObject* list;
4588 PyObject* item = NULL;
4589
4590 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4591 return NULL;
4592
4593 CHECK_ENV_NOT_CLOSED(self);
4594 MYDB_BEGIN_ALLOW_THREADS;
4595#if (DBVER >= 40)
4596 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4597#elif (DBVER == 33)
4598 err = log_archive(self->db_env, &log_list, flags);
4599#else
4600 err = log_archive(self->db_env, &log_list, flags, NULL);
4601#endif
4602 MYDB_END_ALLOW_THREADS;
4603 RETURN_IF_ERR();
4604
4605 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004606 if (list == NULL) {
4607 if (log_list)
4608 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004609 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004611
4612 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004613 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004615 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004616 if (item == NULL) {
4617 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004618 list = NULL;
4619 break;
4620 }
4621 PyList_Append(list, item);
4622 Py_DECREF(item);
4623 }
4624 free(log_list_start);
4625 }
4626 return list;
4627}
4628
4629
4630static PyObject*
4631DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4632{
4633 int err;
4634 DB_TXN_STAT* sp;
4635 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004636 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004637
4638 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4639 return NULL;
4640 CHECK_ENV_NOT_CLOSED(self);
4641
4642 MYDB_BEGIN_ALLOW_THREADS;
4643#if (DBVER >= 40)
4644 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4645#elif (DBVER == 33)
4646 err = txn_stat(self->db_env, &sp);
4647#else
4648 err = txn_stat(self->db_env, &sp, NULL);
4649#endif
4650 MYDB_END_ALLOW_THREADS;
4651 RETURN_IF_ERR();
4652
4653 /* Turn the stat structure into a dictionary */
4654 d = PyDict_New();
4655 if (d == NULL) {
4656 free(sp);
4657 return NULL;
4658 }
4659
4660#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004661#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004662
Guido van Rossumd8faa362007-04-27 19:54:29 +00004663 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 MAKE_ENTRY(last_txnid);
4665 MAKE_ENTRY(maxtxns);
4666 MAKE_ENTRY(nactive);
4667 MAKE_ENTRY(maxnactive);
4668 MAKE_ENTRY(nbegins);
4669 MAKE_ENTRY(naborts);
4670 MAKE_ENTRY(ncommits);
4671 MAKE_ENTRY(regsize);
4672 MAKE_ENTRY(region_wait);
4673 MAKE_ENTRY(region_nowait);
4674
4675#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004676#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004677 free(sp);
4678 return d;
4679}
4680
4681
4682static PyObject*
4683DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4684{
4685 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004686 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687
4688 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4689 return NULL;
4690 CHECK_ENV_NOT_CLOSED(self);
4691
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004692 if (self->moduleFlags.getReturnsNone)
4693 ++oldValue;
4694 if (self->moduleFlags.cursorSetReturnsNone)
4695 ++oldValue;
4696 self->moduleFlags.getReturnsNone = (flags >= 1);
4697 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004698 return PyInt_FromLong(oldValue);
4699}
4700
4701
4702/* --------------------------------------------------------------------- */
4703/* DBTxn methods */
4704
4705
4706static PyObject*
4707DBTxn_commit(DBTxnObject* self, PyObject* args)
4708{
4709 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004710 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004711
4712 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4713 return NULL;
4714
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004715 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004716 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4717 "after txn_commit or txn_abort");
4718 PyErr_SetObject(DBError, t);
4719 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004720 return NULL;
4721 }
4722 txn = self->txn;
4723 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724 MYDB_BEGIN_ALLOW_THREADS;
4725#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004726 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004727#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004728 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004729#endif
4730 MYDB_END_ALLOW_THREADS;
4731 RETURN_IF_ERR();
4732 RETURN_NONE();
4733}
4734
4735static PyObject*
4736DBTxn_prepare(DBTxnObject* self, PyObject* args)
4737{
4738#if (DBVER >= 33)
4739 int err;
4740 char* gid=NULL;
4741 int gid_size=0;
4742
Gregory P. Smith361ed152007-08-23 07:32:27 +00004743 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004744 return NULL;
4745
4746 if (gid_size != DB_XIDDATASIZE) {
4747 PyErr_SetString(PyExc_TypeError,
4748 "gid must be DB_XIDDATASIZE bytes long");
4749 return NULL;
4750 }
4751
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004752 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004753 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4754 "after txn_commit or txn_abort");
4755 PyErr_SetObject(DBError, t);
4756 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004757 return NULL;
4758 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004759 MYDB_BEGIN_ALLOW_THREADS;
4760#if (DBVER >= 40)
4761 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4762#else
4763 err = txn_prepare(self->txn, (u_int8_t*)gid);
4764#endif
4765 MYDB_END_ALLOW_THREADS;
4766 RETURN_IF_ERR();
4767 RETURN_NONE();
4768#else
4769 int err;
4770
4771 if (!PyArg_ParseTuple(args, ":prepare"))
4772 return NULL;
4773
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004774 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004775 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4776 "after txn_commit or txn_abort");
4777 PyErr_SetObject(DBError, t);
4778 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004779 return NULL;
4780 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004781 MYDB_BEGIN_ALLOW_THREADS;
4782 err = txn_prepare(self->txn);
4783 MYDB_END_ALLOW_THREADS;
4784 RETURN_IF_ERR();
4785 RETURN_NONE();
4786#endif
4787}
4788
4789
4790static PyObject*
4791DBTxn_abort(DBTxnObject* self, PyObject* args)
4792{
4793 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004794 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004795
4796 if (!PyArg_ParseTuple(args, ":abort"))
4797 return NULL;
4798
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004799 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004800 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4801 "after txn_commit or txn_abort");
4802 PyErr_SetObject(DBError, t);
4803 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 return NULL;
4805 }
4806 txn = self->txn;
4807 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808 MYDB_BEGIN_ALLOW_THREADS;
4809#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004810 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004811#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004812 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813#endif
4814 MYDB_END_ALLOW_THREADS;
4815 RETURN_IF_ERR();
4816 RETURN_NONE();
4817}
4818
4819
4820static PyObject*
4821DBTxn_id(DBTxnObject* self, PyObject* args)
4822{
4823 int id;
4824
4825 if (!PyArg_ParseTuple(args, ":id"))
4826 return NULL;
4827
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004828 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004829 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4830 "after txn_commit or txn_abort");
4831 PyErr_SetObject(DBError, t);
4832 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004833 return NULL;
4834 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004835 MYDB_BEGIN_ALLOW_THREADS;
4836#if (DBVER >= 40)
4837 id = self->txn->id(self->txn);
4838#else
4839 id = txn_id(self->txn);
4840#endif
4841 MYDB_END_ALLOW_THREADS;
4842 return PyInt_FromLong(id);
4843}
4844
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004845#if (DBVER >= 43)
4846/* --------------------------------------------------------------------- */
4847/* DBSequence methods */
4848
4849
4850static PyObject*
4851DBSequence_close(DBSequenceObject* self, PyObject* args)
4852{
4853 int err, flags=0;
4854 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4855 return NULL;
4856 CHECK_SEQUENCE_NOT_CLOSED(self)
4857
4858 MYDB_BEGIN_ALLOW_THREADS
4859 err = self->sequence->close(self->sequence, flags);
4860 self->sequence = NULL;
4861 MYDB_END_ALLOW_THREADS
4862
4863 RETURN_IF_ERR();
4864
4865 RETURN_NONE();
4866}
4867
4868static PyObject*
4869DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4870{
4871 int err, flags = 0;
4872 int delta = 1;
4873 db_seq_t value;
4874 PyObject *txnobj = NULL;
4875 DB_TXN *txn = NULL;
4876 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4877 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4878 return NULL;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880
4881 if (!checkTxnObj(txnobj, &txn))
4882 return NULL;
4883
4884 MYDB_BEGIN_ALLOW_THREADS
4885 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4886 MYDB_END_ALLOW_THREADS
4887
4888 RETURN_IF_ERR();
4889 return PyLong_FromLongLong(value);
4890
4891}
4892
4893static PyObject*
4894DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4895{
4896 if (!PyArg_ParseTuple(args,":get_dbp"))
4897 return NULL;
4898 CHECK_SEQUENCE_NOT_CLOSED(self)
4899 Py_INCREF(self->mydb);
4900 return (PyObject* )self->mydb;
4901}
4902
4903static PyObject*
4904DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4905{
4906 int err;
4907 DBT key;
4908 CHECK_SEQUENCE_NOT_CLOSED(self)
4909 MYDB_BEGIN_ALLOW_THREADS
4910 err = self->sequence->get_key(self->sequence, &key);
4911 MYDB_END_ALLOW_THREADS
4912
4913 RETURN_IF_ERR();
4914
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004915 return PyBytes_FromStringAndSize(key.data, key.size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004916}
4917
4918static PyObject*
4919DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4920{
4921 int err;
4922 db_seq_t value;
4923 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4924 return NULL;
4925 CHECK_SEQUENCE_NOT_CLOSED(self)
4926
4927 MYDB_BEGIN_ALLOW_THREADS
4928 err = self->sequence->initial_value(self->sequence, value);
4929 MYDB_END_ALLOW_THREADS
4930
4931 RETURN_IF_ERR();
4932
4933 RETURN_NONE();
4934}
4935
4936static PyObject*
4937DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4938{
4939 int err, flags = 0;
4940 PyObject* keyobj;
4941 PyObject *txnobj = NULL;
4942 DB_TXN *txn = NULL;
4943 DBT key;
4944
4945 static char* kwnames[] = {"key", "txn", "flags", NULL };
4946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4947 return NULL;
4948
4949 if (!checkTxnObj(txnobj, &txn))
4950 return NULL;
4951
4952 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4953 return NULL;
4954
4955 MYDB_BEGIN_ALLOW_THREADS
4956 err = self->sequence->open(self->sequence, txn, &key, flags);
4957 MYDB_END_ALLOW_THREADS
4958
4959 CLEAR_DBT(key);
4960 RETURN_IF_ERR();
4961
4962 RETURN_NONE();
4963}
4964
4965static PyObject*
4966DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4967{
4968 int err, flags = 0;
4969 PyObject *txnobj = NULL;
4970 DB_TXN *txn = NULL;
4971
4972 static char* kwnames[] = {"txn", "flags", NULL };
4973 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4974 return NULL;
4975
4976 if (!checkTxnObj(txnobj, &txn))
4977 return NULL;
4978
4979 CHECK_SEQUENCE_NOT_CLOSED(self)
4980
4981 MYDB_BEGIN_ALLOW_THREADS
4982 err = self->sequence->remove(self->sequence, txn, flags);
4983 MYDB_END_ALLOW_THREADS
4984
4985 RETURN_IF_ERR();
4986 RETURN_NONE();
4987}
4988
4989static PyObject*
4990DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4991{
4992 int err, size;
4993 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4994 return NULL;
4995 CHECK_SEQUENCE_NOT_CLOSED(self)
4996
4997 MYDB_BEGIN_ALLOW_THREADS
4998 err = self->sequence->set_cachesize(self->sequence, size);
4999 MYDB_END_ALLOW_THREADS
5000
5001 RETURN_IF_ERR();
5002 RETURN_NONE();
5003}
5004
5005static PyObject*
5006DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5007{
5008 int err, size;
5009 if (!PyArg_ParseTuple(args,":get_cachesize"))
5010 return NULL;
5011 CHECK_SEQUENCE_NOT_CLOSED(self)
5012
5013 MYDB_BEGIN_ALLOW_THREADS
5014 err = self->sequence->get_cachesize(self->sequence, &size);
5015 MYDB_END_ALLOW_THREADS
5016
5017 RETURN_IF_ERR();
5018 return PyInt_FromLong(size);
5019}
5020
5021static PyObject*
5022DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5023{
5024 int err, flags = 0;
5025 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5026 return NULL;
5027 CHECK_SEQUENCE_NOT_CLOSED(self)
5028
5029 MYDB_BEGIN_ALLOW_THREADS
5030 err = self->sequence->set_flags(self->sequence, flags);
5031 MYDB_END_ALLOW_THREADS
5032
5033 RETURN_IF_ERR();
5034 RETURN_NONE();
5035
5036}
5037
5038static PyObject*
5039DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5040{
5041 unsigned int flags;
5042 int err;
5043 if (!PyArg_ParseTuple(args,":get_flags"))
5044 return NULL;
5045 CHECK_SEQUENCE_NOT_CLOSED(self)
5046
5047 MYDB_BEGIN_ALLOW_THREADS
5048 err = self->sequence->get_flags(self->sequence, &flags);
5049 MYDB_END_ALLOW_THREADS
5050
5051 RETURN_IF_ERR();
5052 return PyInt_FromLong((int)flags);
5053}
5054
5055static PyObject*
5056DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5057{
5058 int err;
5059 db_seq_t min, max;
5060 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5061 return NULL;
5062 CHECK_SEQUENCE_NOT_CLOSED(self)
5063
5064 MYDB_BEGIN_ALLOW_THREADS
5065 err = self->sequence->set_range(self->sequence, min, max);
5066 MYDB_END_ALLOW_THREADS
5067
5068 RETURN_IF_ERR();
5069 RETURN_NONE();
5070}
5071
5072static PyObject*
5073DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5074{
5075 int err;
5076 db_seq_t min, max;
5077 if (!PyArg_ParseTuple(args,":get_range"))
5078 return NULL;
5079 CHECK_SEQUENCE_NOT_CLOSED(self)
5080
5081 MYDB_BEGIN_ALLOW_THREADS
5082 err = self->sequence->get_range(self->sequence, &min, &max);
5083 MYDB_END_ALLOW_THREADS
5084
5085 RETURN_IF_ERR();
5086 return Py_BuildValue("(LL)", min, max);
5087}
5088
5089static PyObject*
5090DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5091{
5092 int err, flags = 0;
5093 DB_SEQUENCE_STAT* sp = NULL;
5094 PyObject* dict_stat;
5095 static char* kwnames[] = {"flags", NULL };
5096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5097 return NULL;
5098 CHECK_SEQUENCE_NOT_CLOSED(self);
5099
5100 MYDB_BEGIN_ALLOW_THREADS;
5101 err = self->sequence->stat(self->sequence, &sp, flags);
5102 MYDB_END_ALLOW_THREADS;
5103 RETURN_IF_ERR();
5104
5105 if ((dict_stat = PyDict_New()) == NULL) {
5106 free(sp);
5107 return NULL;
5108 }
5109
5110
5111#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5112#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5113
5114 MAKE_INT_ENTRY(wait);
5115 MAKE_INT_ENTRY(nowait);
5116 MAKE_LONG_LONG_ENTRY(current);
5117 MAKE_LONG_LONG_ENTRY(value);
5118 MAKE_LONG_LONG_ENTRY(last_value);
5119 MAKE_LONG_LONG_ENTRY(min);
5120 MAKE_LONG_LONG_ENTRY(max);
5121 MAKE_INT_ENTRY(cache_size);
5122 MAKE_INT_ENTRY(flags);
5123
5124#undef MAKE_INT_ENTRY
5125#undef MAKE_LONG_LONG_ENTRY
5126
5127 free(sp);
5128 return dict_stat;
5129}
5130#endif
5131
5132
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005133/* --------------------------------------------------------------------- */
5134/* Method definition tables and type objects */
5135
5136static PyMethodDef DB_methods[] = {
5137 {"append", (PyCFunction)DB_append, METH_VARARGS},
5138#if (DBVER >= 33)
5139 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5140#endif
5141 {"close", (PyCFunction)DB_close, METH_VARARGS},
5142#if (DBVER >= 32)
5143 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5144 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5145#endif
5146 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5147 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5148 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5149 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005150#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005151 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005152#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005153 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5154 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5155 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5156 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5157 {"join", (PyCFunction)DB_join, METH_VARARGS},
5158 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5159 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5160 {"items", (PyCFunction)DB_items, METH_VARARGS},
5161 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5162 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5163 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5164 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5165 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5166 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005167#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005168 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005170 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005171#if (DBVER >= 41)
5172 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5173#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005174 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5175 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5176 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5177 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5178 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5179 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5180 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5181 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5182 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5183#if (DBVER >= 32)
5184 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5185#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005186 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005187 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5188#if (DBVER >= 33)
5189 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5190#endif
5191 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5192 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5193 {"values", (PyCFunction)DB_values, METH_VARARGS},
5194 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5195 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5196 {NULL, NULL} /* sentinel */
5197};
5198
5199
5200static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005201 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005202 (binaryfunc)DB_subscript, /*mp_subscript*/
5203 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5204};
5205
5206
5207static PyMethodDef DBCursor_methods[] = {
5208 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5209 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5210 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5211 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5212 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5213 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5214 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005215#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005216 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005217#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5219 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5220 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5221 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5222 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5223 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5224 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5225 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005226 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005227 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005228 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5229 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5230 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5231 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5232 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5233 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5234 {NULL, NULL} /* sentinel */
5235};
5236
5237
5238static PyMethodDef DBEnv_methods[] = {
5239 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5240 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5241 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005242#if (DBVER >= 41)
5243 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5244 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5245 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5246#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005247#if (DBVER >= 40)
5248 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5249#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005250 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005251 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5252 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5253#if (DBVER >= 32)
5254 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5255#endif
5256 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5257 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5258 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005259#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005260 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005263#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005265#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266#if (DBVER >= 32)
5267 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5268 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5269 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5270#endif
5271 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5272 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5273 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5274 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5275 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5276 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005277 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005278 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5279 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5280 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5281 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5282 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5283 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005284#if (DBVER >= 40)
5285 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5286#endif
5287#if (DBVER >= 44)
5288 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5289#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005290 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5291 {NULL, NULL} /* sentinel */
5292};
5293
5294
5295static PyMethodDef DBTxn_methods[] = {
5296 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5297 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5298 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5299 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5300 {NULL, NULL} /* sentinel */
5301};
5302
5303
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005304#if (DBVER >= 43)
5305static PyMethodDef DBSequence_methods[] = {
5306 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5307 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5308 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5309 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5310 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5311 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5312 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5313 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5314 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5315 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5316 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5317 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5318 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5319 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5320 {NULL, NULL} /* sentinel */
5321};
5322#endif
5323
5324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005325static PyObject*
5326DB_getattr(DBObject* self, char *name)
5327{
5328 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5329}
5330
5331
5332static PyObject*
5333DBEnv_getattr(DBEnvObject* self, char *name)
5334{
5335 if (!strcmp(name, "db_home")) {
5336 CHECK_ENV_NOT_CLOSED(self);
5337 if (self->db_env->db_home == NULL) {
5338 RETURN_NONE();
5339 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005340 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005341 }
5342
5343 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5344}
5345
5346
5347static PyObject*
5348DBCursor_getattr(DBCursorObject* self, char *name)
5349{
5350 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5351}
5352
5353static PyObject*
5354DBTxn_getattr(DBTxnObject* self, char *name)
5355{
5356 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5357}
5358
5359static PyObject*
5360DBLock_getattr(DBLockObject* self, char *name)
5361{
5362 return NULL;
5363}
5364
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005365#if (DBVER >= 43)
5366static PyObject*
5367DBSequence_getattr(DBSequenceObject* self, char *name)
5368{
5369 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5370}
5371#endif
5372
Neal Norwitz227b5332006-03-22 09:28:35 +00005373static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005374 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005375 "DB", /*tp_name*/
5376 sizeof(DBObject), /*tp_basicsize*/
5377 0, /*tp_itemsize*/
5378 /* methods */
5379 (destructor)DB_dealloc, /*tp_dealloc*/
5380 0, /*tp_print*/
5381 (getattrfunc)DB_getattr, /*tp_getattr*/
5382 0, /*tp_setattr*/
5383 0, /*tp_compare*/
5384 0, /*tp_repr*/
5385 0, /*tp_as_number*/
5386 0, /*tp_as_sequence*/
5387 &DB_mapping,/*tp_as_mapping*/
5388 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005389#ifdef HAVE_WEAKREF
5390 0, /* tp_call */
5391 0, /* tp_str */
5392 0, /* tp_getattro */
5393 0, /* tp_setattro */
5394 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005395 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005396 0, /* tp_doc */
5397 0, /* tp_traverse */
5398 0, /* tp_clear */
5399 0, /* tp_richcompare */
5400 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5401#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005402};
5403
5404
Neal Norwitz227b5332006-03-22 09:28:35 +00005405static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005406 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005407 "DBCursor", /*tp_name*/
5408 sizeof(DBCursorObject), /*tp_basicsize*/
5409 0, /*tp_itemsize*/
5410 /* methods */
5411 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5412 0, /*tp_print*/
5413 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5414 0, /*tp_setattr*/
5415 0, /*tp_compare*/
5416 0, /*tp_repr*/
5417 0, /*tp_as_number*/
5418 0, /*tp_as_sequence*/
5419 0, /*tp_as_mapping*/
5420 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005421#ifdef HAVE_WEAKREF
5422 0, /* tp_call */
5423 0, /* tp_str */
5424 0, /* tp_getattro */
5425 0, /* tp_setattro */
5426 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005427 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005428 0, /* tp_doc */
5429 0, /* tp_traverse */
5430 0, /* tp_clear */
5431 0, /* tp_richcompare */
5432 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5433#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434};
5435
5436
Neal Norwitz227b5332006-03-22 09:28:35 +00005437static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005438 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005439 "DBEnv", /*tp_name*/
5440 sizeof(DBEnvObject), /*tp_basicsize*/
5441 0, /*tp_itemsize*/
5442 /* methods */
5443 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5444 0, /*tp_print*/
5445 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5446 0, /*tp_setattr*/
5447 0, /*tp_compare*/
5448 0, /*tp_repr*/
5449 0, /*tp_as_number*/
5450 0, /*tp_as_sequence*/
5451 0, /*tp_as_mapping*/
5452 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005453#ifdef HAVE_WEAKREF
5454 0, /* tp_call */
5455 0, /* tp_str */
5456 0, /* tp_getattro */
5457 0, /* tp_setattro */
5458 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005459 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005460 0, /* tp_doc */
5461 0, /* tp_traverse */
5462 0, /* tp_clear */
5463 0, /* tp_richcompare */
5464 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5465#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005466};
5467
Neal Norwitz227b5332006-03-22 09:28:35 +00005468static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005469 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005470 "DBTxn", /*tp_name*/
5471 sizeof(DBTxnObject), /*tp_basicsize*/
5472 0, /*tp_itemsize*/
5473 /* methods */
5474 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5475 0, /*tp_print*/
5476 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5477 0, /*tp_setattr*/
5478 0, /*tp_compare*/
5479 0, /*tp_repr*/
5480 0, /*tp_as_number*/
5481 0, /*tp_as_sequence*/
5482 0, /*tp_as_mapping*/
5483 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005484#ifdef HAVE_WEAKREF
5485 0, /* tp_call */
5486 0, /* tp_str */
5487 0, /* tp_getattro */
5488 0, /* tp_setattro */
5489 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005490 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005491 0, /* tp_doc */
5492 0, /* tp_traverse */
5493 0, /* tp_clear */
5494 0, /* tp_richcompare */
5495 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5496#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005497};
5498
5499
Neal Norwitz227b5332006-03-22 09:28:35 +00005500static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005501 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005502 "DBLock", /*tp_name*/
5503 sizeof(DBLockObject), /*tp_basicsize*/
5504 0, /*tp_itemsize*/
5505 /* methods */
5506 (destructor)DBLock_dealloc, /*tp_dealloc*/
5507 0, /*tp_print*/
5508 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5509 0, /*tp_setattr*/
5510 0, /*tp_compare*/
5511 0, /*tp_repr*/
5512 0, /*tp_as_number*/
5513 0, /*tp_as_sequence*/
5514 0, /*tp_as_mapping*/
5515 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005516#ifdef HAVE_WEAKREF
5517 0, /* tp_call */
5518 0, /* tp_str */
5519 0, /* tp_getattro */
5520 0, /* tp_setattro */
5521 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005522 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005523 0, /* tp_doc */
5524 0, /* tp_traverse */
5525 0, /* tp_clear */
5526 0, /* tp_richcompare */
5527 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5528#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005529};
5530
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005531#if (DBVER >= 43)
5532static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005533 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005534 "DBSequence", /*tp_name*/
5535 sizeof(DBSequenceObject), /*tp_basicsize*/
5536 0, /*tp_itemsize*/
5537 /* methods */
5538 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5539 0, /*tp_print*/
5540 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5541 0, /*tp_setattr*/
5542 0, /*tp_compare*/
5543 0, /*tp_repr*/
5544 0, /*tp_as_number*/
5545 0, /*tp_as_sequence*/
5546 0, /*tp_as_mapping*/
5547 0, /*tp_hash*/
5548#ifdef HAVE_WEAKREF
5549 0, /* tp_call */
5550 0, /* tp_str */
5551 0, /* tp_getattro */
5552 0, /* tp_setattro */
5553 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005554 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005555 0, /* tp_doc */
5556 0, /* tp_traverse */
5557 0, /* tp_clear */
5558 0, /* tp_richcompare */
5559 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5560#endif
5561};
5562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563
5564/* --------------------------------------------------------------------- */
5565/* Module-level functions */
5566
5567static PyObject*
5568DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5569{
5570 PyObject* dbenvobj = NULL;
5571 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005572 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005573
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5575 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005576 return NULL;
5577 if (dbenvobj == Py_None)
5578 dbenvobj = NULL;
5579 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5580 makeTypeError("DBEnv", dbenvobj);
5581 return NULL;
5582 }
5583
5584 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5585}
5586
5587
5588static PyObject*
5589DBEnv_construct(PyObject* self, PyObject* args)
5590{
5591 int flags = 0;
5592 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5593 return (PyObject* )newDBEnvObject(flags);
5594}
5595
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005596#if (DBVER >= 43)
5597static PyObject*
5598DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5599{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005600 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005601 int flags = 0;
5602 static char* kwnames[] = { "db", "flags", NULL};
5603
5604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5605 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005606 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005607 makeTypeError("DB", dbobj);
5608 return NULL;
5609 }
5610 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5611}
5612#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005613
5614static char bsddb_version_doc[] =
5615"Returns a tuple of major, minor, and patch release numbers of the\n\
5616underlying DB library.";
5617
5618static PyObject*
5619bsddb_version(PyObject* self, PyObject* args)
5620{
5621 int major, minor, patch;
5622
5623 if (!PyArg_ParseTuple(args, ":version"))
5624 return NULL;
5625 db_version(&major, &minor, &patch);
5626 return Py_BuildValue("(iii)", major, minor, patch);
5627}
5628
5629
5630/* List of functions defined in the module */
5631
5632static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005633 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5634 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5635#if (DBVER >= 43)
5636 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5637#endif
5638 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005639 {NULL, NULL} /* sentinel */
5640};
5641
5642
5643/* --------------------------------------------------------------------- */
5644/* Module initialization */
5645
5646
5647/* Convenience routine to export an integer value.
5648 * Errors are silently ignored, for better or for worse...
5649 */
5650#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5651
Gregory P. Smith41631e82003-09-21 00:08:14 +00005652#define MODULE_NAME_MAX_LEN 11
5653static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005654
Neal Norwitzf6657e62006-12-28 04:47:50 +00005655PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656{
5657 PyObject* m;
5658 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005659 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5660 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5661 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005662
5663 /* Initialize the type of the new type objects here; doing it here
5664 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005665 Py_Type(&DB_Type) = &PyType_Type;
5666 Py_Type(&DBCursor_Type) = &PyType_Type;
5667 Py_Type(&DBEnv_Type) = &PyType_Type;
5668 Py_Type(&DBTxn_Type) = &PyType_Type;
5669 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005670#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005671 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005672#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673
5674
Mark Hammonda69d4092003-04-22 23:13:27 +00005675#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005676 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005677 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678#endif
5679
5680 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005681 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005682 if (m == NULL)
5683 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684
5685 /* Add some symbolic constants to the module */
5686 d = PyModule_GetDict(m);
5687 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005688 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005689 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5690 Py_DECREF(pybsddb_version_s);
5691 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005692 Py_DECREF(svnid_s);
5693 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005694 Py_DECREF(db_version_s);
5695 db_version_s = NULL;
5696
5697 ADD_INT(d, DB_VERSION_MAJOR);
5698 ADD_INT(d, DB_VERSION_MINOR);
5699 ADD_INT(d, DB_VERSION_PATCH);
5700
5701 ADD_INT(d, DB_MAX_PAGES);
5702 ADD_INT(d, DB_MAX_RECORDS);
5703
Gregory P. Smith41631e82003-09-21 00:08:14 +00005704#if (DBVER >= 42)
5705 ADD_INT(d, DB_RPCCLIENT);
5706#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005707 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005708 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5709 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711 ADD_INT(d, DB_XA_CREATE);
5712
5713 ADD_INT(d, DB_CREATE);
5714 ADD_INT(d, DB_NOMMAP);
5715 ADD_INT(d, DB_THREAD);
5716
5717 ADD_INT(d, DB_FORCE);
5718 ADD_INT(d, DB_INIT_CDB);
5719 ADD_INT(d, DB_INIT_LOCK);
5720 ADD_INT(d, DB_INIT_LOG);
5721 ADD_INT(d, DB_INIT_MPOOL);
5722 ADD_INT(d, DB_INIT_TXN);
5723#if (DBVER >= 32)
5724 ADD_INT(d, DB_JOINENV);
5725#endif
5726
5727 ADD_INT(d, DB_RECOVER);
5728 ADD_INT(d, DB_RECOVER_FATAL);
5729 ADD_INT(d, DB_TXN_NOSYNC);
5730 ADD_INT(d, DB_USE_ENVIRON);
5731 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5732
5733 ADD_INT(d, DB_LOCKDOWN);
5734 ADD_INT(d, DB_PRIVATE);
5735 ADD_INT(d, DB_SYSTEM_MEM);
5736
5737 ADD_INT(d, DB_TXN_SYNC);
5738 ADD_INT(d, DB_TXN_NOWAIT);
5739
5740 ADD_INT(d, DB_EXCL);
5741 ADD_INT(d, DB_FCNTL_LOCKING);
5742 ADD_INT(d, DB_ODDFILESIZE);
5743 ADD_INT(d, DB_RDWRMASTER);
5744 ADD_INT(d, DB_RDONLY);
5745 ADD_INT(d, DB_TRUNCATE);
5746#if (DBVER >= 32)
5747 ADD_INT(d, DB_EXTENT);
5748 ADD_INT(d, DB_CDB_ALLDB);
5749 ADD_INT(d, DB_VERIFY);
5750#endif
5751 ADD_INT(d, DB_UPGRADE);
5752
5753 ADD_INT(d, DB_AGGRESSIVE);
5754 ADD_INT(d, DB_NOORDERCHK);
5755 ADD_INT(d, DB_ORDERCHKONLY);
5756 ADD_INT(d, DB_PR_PAGE);
5757#if ! (DBVER >= 33)
5758 ADD_INT(d, DB_VRFY_FLAGMASK);
5759 ADD_INT(d, DB_PR_HEADERS);
5760#endif
5761 ADD_INT(d, DB_PR_RECOVERYTEST);
5762 ADD_INT(d, DB_SALVAGE);
5763
5764 ADD_INT(d, DB_LOCK_NORUN);
5765 ADD_INT(d, DB_LOCK_DEFAULT);
5766 ADD_INT(d, DB_LOCK_OLDEST);
5767 ADD_INT(d, DB_LOCK_RANDOM);
5768 ADD_INT(d, DB_LOCK_YOUNGEST);
5769#if (DBVER >= 33)
5770 ADD_INT(d, DB_LOCK_MAXLOCKS);
5771 ADD_INT(d, DB_LOCK_MINLOCKS);
5772 ADD_INT(d, DB_LOCK_MINWRITE);
5773#endif
5774
5775
5776#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005777 /* docs say to use zero instead */
5778 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005779#else
5780 ADD_INT(d, DB_LOCK_CONFLICT);
5781#endif
5782
5783 ADD_INT(d, DB_LOCK_DUMP);
5784 ADD_INT(d, DB_LOCK_GET);
5785 ADD_INT(d, DB_LOCK_INHERIT);
5786 ADD_INT(d, DB_LOCK_PUT);
5787 ADD_INT(d, DB_LOCK_PUT_ALL);
5788 ADD_INT(d, DB_LOCK_PUT_OBJ);
5789
5790 ADD_INT(d, DB_LOCK_NG);
5791 ADD_INT(d, DB_LOCK_READ);
5792 ADD_INT(d, DB_LOCK_WRITE);
5793 ADD_INT(d, DB_LOCK_NOWAIT);
5794#if (DBVER >= 32)
5795 ADD_INT(d, DB_LOCK_WAIT);
5796#endif
5797 ADD_INT(d, DB_LOCK_IWRITE);
5798 ADD_INT(d, DB_LOCK_IREAD);
5799 ADD_INT(d, DB_LOCK_IWR);
5800#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005801#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005803#else
5804 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5805#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005806 ADD_INT(d, DB_LOCK_WWRITE);
5807#endif
5808
5809 ADD_INT(d, DB_LOCK_RECORD);
5810 ADD_INT(d, DB_LOCK_UPGRADE);
5811#if (DBVER >= 32)
5812 ADD_INT(d, DB_LOCK_SWITCH);
5813#endif
5814#if (DBVER >= 33)
5815 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5816#endif
5817
5818 ADD_INT(d, DB_LOCK_NOWAIT);
5819 ADD_INT(d, DB_LOCK_RECORD);
5820 ADD_INT(d, DB_LOCK_UPGRADE);
5821
5822#if (DBVER >= 33)
5823 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005824#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005826#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005827 ADD_INT(d, DB_LSTAT_FREE);
5828 ADD_INT(d, DB_LSTAT_HELD);
5829#if (DBVER == 33)
5830 ADD_INT(d, DB_LSTAT_NOGRANT);
5831#endif
5832 ADD_INT(d, DB_LSTAT_PENDING);
5833 ADD_INT(d, DB_LSTAT_WAITING);
5834#endif
5835
5836 ADD_INT(d, DB_ARCH_ABS);
5837 ADD_INT(d, DB_ARCH_DATA);
5838 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005839#if (DBVER >= 42)
5840 ADD_INT(d, DB_ARCH_REMOVE);
5841#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005842
5843 ADD_INT(d, DB_BTREE);
5844 ADD_INT(d, DB_HASH);
5845 ADD_INT(d, DB_RECNO);
5846 ADD_INT(d, DB_QUEUE);
5847 ADD_INT(d, DB_UNKNOWN);
5848
5849 ADD_INT(d, DB_DUP);
5850 ADD_INT(d, DB_DUPSORT);
5851 ADD_INT(d, DB_RECNUM);
5852 ADD_INT(d, DB_RENUMBER);
5853 ADD_INT(d, DB_REVSPLITOFF);
5854 ADD_INT(d, DB_SNAPSHOT);
5855
5856 ADD_INT(d, DB_JOIN_NOSORT);
5857
5858 ADD_INT(d, DB_AFTER);
5859 ADD_INT(d, DB_APPEND);
5860 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005861#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005862 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005863#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005864#if (DBVER >= 41)
5865 _addIntToDict(d, "DB_CHECKPOINT", 0);
5866#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005867 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005868 ADD_INT(d, DB_CURLSN);
5869#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005870#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005871 ADD_INT(d, DB_COMMIT);
5872#endif
5873 ADD_INT(d, DB_CONSUME);
5874#if (DBVER >= 32)
5875 ADD_INT(d, DB_CONSUME_WAIT);
5876#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877 ADD_INT(d, DB_CURRENT);
5878#if (DBVER >= 33)
5879 ADD_INT(d, DB_FAST_STAT);
5880#endif
5881 ADD_INT(d, DB_FIRST);
5882 ADD_INT(d, DB_FLUSH);
5883 ADD_INT(d, DB_GET_BOTH);
5884 ADD_INT(d, DB_GET_RECNO);
5885 ADD_INT(d, DB_JOIN_ITEM);
5886 ADD_INT(d, DB_KEYFIRST);
5887 ADD_INT(d, DB_KEYLAST);
5888 ADD_INT(d, DB_LAST);
5889 ADD_INT(d, DB_NEXT);
5890 ADD_INT(d, DB_NEXT_DUP);
5891 ADD_INT(d, DB_NEXT_NODUP);
5892 ADD_INT(d, DB_NODUPDATA);
5893 ADD_INT(d, DB_NOOVERWRITE);
5894 ADD_INT(d, DB_NOSYNC);
5895 ADD_INT(d, DB_POSITION);
5896 ADD_INT(d, DB_PREV);
5897 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005898#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005900#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005901 ADD_INT(d, DB_SET);
5902 ADD_INT(d, DB_SET_RANGE);
5903 ADD_INT(d, DB_SET_RECNO);
5904 ADD_INT(d, DB_WRITECURSOR);
5905
5906 ADD_INT(d, DB_OPFLAGS_MASK);
5907 ADD_INT(d, DB_RMW);
5908#if (DBVER >= 33)
5909 ADD_INT(d, DB_DIRTY_READ);
5910 ADD_INT(d, DB_MULTIPLE);
5911 ADD_INT(d, DB_MULTIPLE_KEY);
5912#endif
5913
Gregory P. Smith29602d22006-01-24 09:46:48 +00005914#if (DBVER >= 44)
5915 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5916 ADD_INT(d, DB_READ_COMMITTED);
5917#endif
5918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005919#if (DBVER >= 33)
5920 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005921 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005922#endif
5923
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005924#if (DBVER >= 41)
5925 _addIntToDict(d, "DB_INCOMPLETE", 0);
5926#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005927 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005928#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005929 ADD_INT(d, DB_KEYEMPTY);
5930 ADD_INT(d, DB_KEYEXIST);
5931 ADD_INT(d, DB_LOCK_DEADLOCK);
5932 ADD_INT(d, DB_LOCK_NOTGRANTED);
5933 ADD_INT(d, DB_NOSERVER);
5934 ADD_INT(d, DB_NOSERVER_HOME);
5935 ADD_INT(d, DB_NOSERVER_ID);
5936 ADD_INT(d, DB_NOTFOUND);
5937 ADD_INT(d, DB_OLD_VERSION);
5938 ADD_INT(d, DB_RUNRECOVERY);
5939 ADD_INT(d, DB_VERIFY_BAD);
5940#if (DBVER >= 33)
5941 ADD_INT(d, DB_PAGE_NOTFOUND);
5942 ADD_INT(d, DB_SECONDARY_BAD);
5943#endif
5944#if (DBVER >= 40)
5945 ADD_INT(d, DB_STAT_CLEAR);
5946 ADD_INT(d, DB_REGION_INIT);
5947 ADD_INT(d, DB_NOLOCKING);
5948 ADD_INT(d, DB_YIELDCPU);
5949 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5950 ADD_INT(d, DB_NOPANIC);
5951#endif
5952
Gregory P. Smith41631e82003-09-21 00:08:14 +00005953#if (DBVER >= 42)
5954 ADD_INT(d, DB_TIME_NOTGRANTED);
5955 ADD_INT(d, DB_TXN_NOT_DURABLE);
5956 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5957 ADD_INT(d, DB_LOG_AUTOREMOVE);
5958 ADD_INT(d, DB_DIRECT_LOG);
5959 ADD_INT(d, DB_DIRECT_DB);
5960 ADD_INT(d, DB_INIT_REP);
5961 ADD_INT(d, DB_ENCRYPT);
5962 ADD_INT(d, DB_CHKSUM);
5963#endif
5964
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005965#if (DBVER >= 43)
5966 ADD_INT(d, DB_LOG_INMEMORY);
5967 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005968 ADD_INT(d, DB_SEQ_DEC);
5969 ADD_INT(d, DB_SEQ_INC);
5970 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005971#endif
5972
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005973#if (DBVER >= 41)
5974 ADD_INT(d, DB_ENCRYPT_AES);
5975 ADD_INT(d, DB_AUTO_COMMIT);
5976#else
5977 /* allow berkeleydb 4.1 aware apps to run on older versions */
5978 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5979#endif
5980
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981 ADD_INT(d, EINVAL);
5982 ADD_INT(d, EACCES);
5983 ADD_INT(d, ENOSPC);
5984 ADD_INT(d, ENOMEM);
5985 ADD_INT(d, EAGAIN);
5986 ADD_INT(d, EBUSY);
5987 ADD_INT(d, EEXIST);
5988 ADD_INT(d, ENOENT);
5989 ADD_INT(d, EPERM);
5990
Barry Warsaw1baa9822003-03-31 19:51:29 +00005991#if (DBVER >= 40)
5992 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5993 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5994#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005995
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005996 /* The exception name must be correct for pickled exception *
5997 * objects to unpickle properly. */
5998#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5999#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6000#else
6001#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6002#endif
6003
6004 /* All the rest of the exceptions derive only from DBError */
6005#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6006 PyDict_SetItemString(d, #name, name)
6007
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006008 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006009 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6010 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006011
Gregory P. Smithe9477062005-06-04 06:46:59 +00006012 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6013 * from both DBError and KeyError, since the API only supports
6014 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006015 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006016 {
6017 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6018 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6019 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006020 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6021 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006022 Py_file_input, d, d);
6023 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006024 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006025 PyDict_DelItemString(d, "KeyError");
6026
6027
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006028#if !INCOMPLETE_IS_WARNING
6029 MAKE_EX(DBIncompleteError);
6030#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006031 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006032 MAKE_EX(DBKeyEmptyError);
6033 MAKE_EX(DBKeyExistError);
6034 MAKE_EX(DBLockDeadlockError);
6035 MAKE_EX(DBLockNotGrantedError);
6036 MAKE_EX(DBOldVersionError);
6037 MAKE_EX(DBRunRecoveryError);
6038 MAKE_EX(DBVerifyBadError);
6039 MAKE_EX(DBNoServerError);
6040 MAKE_EX(DBNoServerHomeError);
6041 MAKE_EX(DBNoServerIDError);
6042#if (DBVER >= 33)
6043 MAKE_EX(DBPageNotFoundError);
6044 MAKE_EX(DBSecondaryBadError);
6045#endif
6046
6047 MAKE_EX(DBInvalidArgError);
6048 MAKE_EX(DBAccessError);
6049 MAKE_EX(DBNoSpaceError);
6050 MAKE_EX(DBNoMemoryError);
6051 MAKE_EX(DBAgainError);
6052 MAKE_EX(DBBusyError);
6053 MAKE_EX(DBFileExistsError);
6054 MAKE_EX(DBNoSuchFileError);
6055 MAKE_EX(DBPermissionsError);
6056
6057#undef MAKE_EX
6058
6059 /* Check for errors */
6060 if (PyErr_Occurred()) {
6061 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006062 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006063 }
6064}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006065
6066/* allow this module to be named _pybsddb so that it can be installed
6067 * and imported on top of python >= 2.3 that includes its own older
6068 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006069PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006070{
6071 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6072 init_bsddb();
6073}