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