blob: 6fef6c2e65e8cb4dab93ed418238bf2b1316fb90 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith641cddf2006-07-28 01:35:25 +0000101#define PY_BSDDB_VERSION "4.4.5"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
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;
Neal Norwitzdce937f2006-07-23 08:01:43 +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
Neal Norwitzdce937f2006-07-23 08:01:43 +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, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Neal Norwitzdce937f2006-07-23 08:01:43 +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) {
Neal Norwitzdce937f2006-07-23 08:01:43 +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, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Neal Norwitzdce937f2006-07-23 08:01:43 +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}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000752#if (DBVER >= 43)
753/* add an db_seq_t to a dictionary using the given name as a key */
754static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
755{
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000760 Py_XDECREF(v);
761}
762#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763
764
765
766/* --------------------------------------------------------------------- */
767/* Allocators and deallocators */
768
769static DBObject*
770newDBObject(DBEnvObject* arg, int flags)
771{
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
775
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (self == NULL)
778 return NULL;
779
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784#if (DBVER >= 33)
785 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000786 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 self->primaryDBType = 0;
788#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000789#ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
798 }
799
800 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000801 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000811 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000813 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000817 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
822 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000823 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824 self = NULL;
825 }
826 return self;
827}
828
829
830static void
831DB_dealloc(DBObject* self)
832{
833 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000837 (self->myenvobj && self->myenvobj->db_env))
838 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000842#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846#endif
847 }
848 self->db = NULL;
849 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000850#ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
853 }
854#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
858 }
859#if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
863 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
867 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870}
871
872
873static DBCursorObject*
874newDBCursorObject(DBC* dbc, DBObject* db)
875{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 if (self == NULL)
878 return NULL;
879
880 self->dbc = dbc;
881 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000882#ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 Py_INCREF(self->mydb);
886 return self;
887}
888
889
890static void
891DBCursor_dealloc(DBCursorObject* self)
892{
893 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000894
895#ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
898 }
899#endif
900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000911 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
914 }
915 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917}
918
919
920static DBEnvObject*
921newDBEnvObject(int flags)
922{
923 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925 if (self == NULL)
926 return NULL;
927
928 self->closed = 1;
929 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000932#ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000940 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 self = NULL;
942 }
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
945 }
946 return self;
947}
948
949
950static void
951DBEnv_dealloc(DBEnvObject* self)
952{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953#ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
956 }
957#endif
958
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000959 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
963 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965}
966
967
968static DBTxnObject*
969newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
970{
971 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000973 if (self == NULL)
974 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000977#ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980
981 MYDB_BEGIN_ALLOW_THREADS;
982#if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984#else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000989 Py_DECREF(self->env);
990 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 self = NULL;
992 }
993 return self;
994}
995
996
997static void
998DBTxn_dealloc(DBTxnObject* self)
999{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000#ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1003 }
1004#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005
Gregory P. Smith31c50652004-06-28 01:20:40 +00001006#ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010#if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012#else
1013 txn_abort(self->txn);
1014#endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1018 }
1019#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020
Neal Norwitz62a21122006-01-25 05:21:55 +00001021 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023}
1024
1025
1026static DBLockObject*
1027newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1029{
1030 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032 if (self == NULL)
1033 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001034#ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037
1038 MYDB_BEGIN_ALLOW_THREADS;
1039#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001042#else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044#endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001047 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001048 self = NULL;
1049 }
1050
1051 return self;
1052}
1053
1054
1055static void
1056DBLock_dealloc(DBLockObject* self)
1057{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001058#ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1061 }
1062#endif
1063 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001066}
1067
1068
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001069#if (DBVER >= 43)
1070static DBSequenceObject*
1071newDBSequenceObject(DBObject* mydb, int flags)
1072{
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079#ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081#endif
1082
1083
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1091 }
1092
1093 return self;
1094}
1095
1096
1097static void
1098DBSequence_dealloc(DBSequenceObject* self)
1099{
1100#ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1103 }
1104#endif
1105
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108}
1109#endif
1110
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111/* --------------------------------------------------------------------- */
1112/* DB methods */
1113
1114static PyObject*
1115DB_append(DBObject* self, PyObject* args)
1116{
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1122
Georg Brandl96a8c392006-05-29 21:04:52 +00001123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001124 return NULL;
1125
1126 CHECK_DB_NOT_CLOSED(self);
1127
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1135
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1138
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1141
1142 return PyInt_FromLong(recno);
1143}
1144
1145
1146#if (DBVER >= 33)
1147
1148static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151{
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001156 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001157 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001158
1159
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1162
Thomas Woutersb3153832006-03-08 01:47:19 +00001163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001169 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001170 result = PyEval_CallObject(callback, args);
1171 }
1172 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 PyErr_Print();
1174 }
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1177 }
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1180 }
1181 else if (PyString_Check(result)) {
1182 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001183 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184
1185 CLEAR_DBT(*secKey);
1186#if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190#else
1191 PyString_AsStringAndSize(result, &data, &size);
1192#endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1199 }
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1204 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 }
1206 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 PyErr_Print();
1211 }
1212
Thomas Woutersb3153832006-03-08 01:47:19 +00001213 Py_XDECREF(args);
1214 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001215
1216 MYDB_END_BLOCK_THREADS;
1217 }
1218 return retval;
1219}
1220
1221
1222static PyObject*
1223DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1224{
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001232 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001233#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237#if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001243 &secondaryDB, &callback, &flags)) {
1244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246 }
1247
1248#if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1256 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001257 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 if (callback == Py_None) {
1259 callback = NULL;
1260 }
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1264 }
1265
1266 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001267 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001268 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1271
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1281 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001282#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001283 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001284#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001286#if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001297#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 MYDB_END_ALLOW_THREADS;
1299
1300 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 secondaryDB->primaryDBType = 0;
1304 }
1305
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1308}
1309
1310
1311#endif
1312
1313
1314static PyObject*
1315DB_close(DBObject* self, PyObject* args)
1316{
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001324 self->db = NULL;
1325 RETURN_IF_ERR();
1326 }
1327 RETURN_NONE();
1328}
1329
1330
1331#if (DBVER >= 32)
1332static PyObject*
1333_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1334{
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001340 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1345
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001353 return NULL;
1354 }
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1357
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1364 }
1365
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1369
Gregory P. Smithe9477062005-06-04 06:46:59 +00001370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1375 }
1376 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001379 FREE_DBT(key);
1380 FREE_DBT(data);
1381 }
1382
1383 RETURN_IF_ERR();
1384 return retval;
1385}
1386
1387static PyObject*
1388DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1389{
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1391}
1392
1393static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001394DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396{
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1398}
1399#endif
1400
1401
1402
1403static PyObject*
1404DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1405{
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001410 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1418
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1424}
1425
1426
1427static PyObject*
1428DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1429{
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001435 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001446 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001447
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001452
1453 FREE_DBT(key);
1454 RETURN_NONE();
1455}
1456
1457
1458static PyObject*
1459DB_fd(DBObject* self, PyObject* args)
1460{
1461 int err, the_fd;
1462
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1472}
1473
1474
1475static PyObject*
1476DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1477{
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001488 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493 return NULL;
1494
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001500 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1507 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001511 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1516
Gregory P. Smithe9477062005-06-04 06:46:59 +00001517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1521 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1527 }
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 FREE_DBT(data);
1535 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001536 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001537
1538 RETURN_IF_ERR();
1539 return retval;
1540}
1541
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001542#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001543static PyObject*
1544DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1545{
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001556 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001557
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1562
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1569 }
1570
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1575 }
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1579 }
1580
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1583
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1587
Gregory P. Smithe9477062005-06-04 06:46:59 +00001588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1592 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1598 }
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1603
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1609
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1611 {
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001615 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001623 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 }
1625 else /* return just the pkey and data */
1626 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001627#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001629#else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1637 }
1638 FREE_DBT(key);
1639
1640 RETURN_IF_ERR();
1641 return retval;
1642}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001643#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001644
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645
1646/* Return size of entry */
1647static PyObject*
1648DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1649{
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001656 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001667 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668 CLEAR_DBT(data);
1669
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001677 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1680 }
1681
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1686}
1687
1688
1689static PyObject*
1690DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1691{
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700
1701
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1705
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001709 if ( !make_dbt(dataobj, &data) ||
1710 !checkTxnObj(txnobj, &txn) )
1711 {
1712 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001714 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715
1716 flags |= DB_GET_BOTH;
1717
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1720 data.flags = DB_DBT_MALLOC;
1721 /* TODO: Is this flag needed? We're passing a data object that should
1722 match what's in the DB, so there should be no need to malloc.
1723 We run the risk of freeing something twice! Check this. */
1724 }
1725
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1729
Gregory P. Smithe9477062005-06-04 06:46:59 +00001730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1735 }
1736 else if (!err) {
1737 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1738 FREE_DBT(data); /* Only if retrieval was successful */
1739 }
1740
1741 FREE_DBT(key);
1742 RETURN_IF_ERR();
1743 return retval;
1744}
1745
1746
1747static PyObject*
1748DB_get_byteswapped(DBObject* self, PyObject* args)
1749{
1750#if (DBVER >= 33)
1751 int err = 0;
1752#endif
1753 int retval = -1;
1754
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1758
1759#if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764#else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768#endif
1769 return PyInt_FromLong(retval);
1770}
1771
1772
1773static PyObject*
1774DB_get_type(DBObject* self, PyObject* args)
1775{
1776 int type;
1777
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 type = _DB_get_type(self);
1784 MYDB_END_ALLOW_THREADS;
1785 if (type == -1)
1786 return NULL;
1787 return PyInt_FromLong(type);
1788}
1789
1790
1791static PyObject*
1792DB_join(DBObject* self, PyObject* args)
1793{
1794 int err, flags=0;
1795 int length, x;
1796 PyObject* cursorsObj;
1797 DBC** cursors;
1798 DBC* dbc;
1799
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001800 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1801 return NULL;
1802
1803 CHECK_DB_NOT_CLOSED(self);
1804
1805 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001806 PyErr_SetString(PyExc_TypeError,
1807 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 return NULL;
1809 }
1810
1811 length = PyObject_Length(cursorsObj);
1812 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001813 if (!cursors) {
1814 PyErr_NoMemory();
1815 return NULL;
1816 }
1817
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001818 cursors[length] = NULL;
1819 for (x=0; x<length; x++) {
1820 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001821 if (item == NULL) {
1822 free(cursors);
1823 return NULL;
1824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001826 PyErr_SetString(PyExc_TypeError,
1827 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 free(cursors);
1829 return NULL;
1830 }
1831 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001832 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 }
1834
1835 MYDB_BEGIN_ALLOW_THREADS;
1836 err = self->db->join(self->db, cursors, &dbc, flags);
1837 MYDB_END_ALLOW_THREADS;
1838 free(cursors);
1839 RETURN_IF_ERR();
1840
Gregory P. Smith7441e652003-11-03 21:35:31 +00001841 /* FIXME: this is a buggy interface. The returned cursor
1842 contains internal references to the passed in cursors
1843 but does not hold python references to them or prevent
1844 them from being closed prematurely. This can cause
1845 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846 return (PyObject*) newDBCursorObject(dbc, self);
1847}
1848
1849
1850static PyObject*
1851DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1852{
1853 int err, flags=0;
1854 PyObject* txnobj = NULL;
1855 PyObject* keyobj;
1856 DBT key;
1857 DB_TXN *txn = NULL;
1858 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001859 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860
1861 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1862 &keyobj, &txnobj, &flags))
1863 return NULL;
1864 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001865 if (!make_dbt(keyobj, &key))
1866 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001867 return NULL;
1868 if (!checkTxnObj(txnobj, &txn))
1869 return NULL;
1870
1871 MYDB_BEGIN_ALLOW_THREADS;
1872 err = self->db->key_range(self->db, txn, &key, &range, flags);
1873 MYDB_END_ALLOW_THREADS;
1874
1875 RETURN_IF_ERR();
1876 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1877}
1878
1879
1880static PyObject*
1881DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1882{
1883 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1884 char* filename = NULL;
1885 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001886#if (DBVER >= 41)
1887 PyObject *txnobj = NULL;
1888 DB_TXN *txn = NULL;
1889 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001890 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001891 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1892 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001893 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001894 "filename", "dbtype", "flags", "mode", "txn", NULL};
1895#else
1896 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001897 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001898 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1899 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001900 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001901 "filename", "dbtype", "flags", "mode", NULL};
1902#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001903
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001904#if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1906 &filename, &dbname, &type, &flags, &mode,
1907 &txnobj))
1908#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001909 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001910 &filename, &dbname, &type, &flags,
1911 &mode))
1912#endif
1913 {
1914 PyErr_Clear();
1915 type = DB_UNKNOWN; flags = 0; mode = 0660;
1916 filename = NULL; dbname = NULL;
1917#if (DBVER >= 41)
1918 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1919 kwnames_basic,
1920 &filename, &type, &flags, &mode,
1921 &txnobj))
1922 return NULL;
1923#else
1924 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1925 kwnames_basic,
1926 &filename, &type, &flags, &mode))
1927 return NULL;
1928#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001929 }
1930
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001931#if (DBVER >= 41)
1932 if (!checkTxnObj(txnobj, &txn)) return NULL;
1933#endif
1934
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001935 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001936 PyObject *t = Py_BuildValue("(is)", 0,
1937 "Cannot call open() twice for DB object");
1938 PyErr_SetObject(DBError, t);
1939 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 return NULL;
1941 }
1942
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001943#if 0 && (DBVER >= 41)
1944 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1945 && (self->myenvobj->flags & DB_INIT_TXN))
1946 {
1947 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1948 * explicitly passed) but we are in a transaction ready environment:
1949 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1950 * to work on BerkeleyDB 4.1 without needing to modify their
1951 * DBEnv or DB open calls.
1952 * TODO make this behaviour of the library configurable.
1953 */
1954 flags |= DB_AUTO_COMMIT;
1955 }
1956#endif
1957
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959#if (DBVER >= 41)
1960 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1961#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001963#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001964 MYDB_END_ALLOW_THREADS;
1965 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001966 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 self->db = NULL;
1968 return NULL;
1969 }
1970
1971 self->flags = flags;
1972 RETURN_NONE();
1973}
1974
1975
1976static PyObject*
1977DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1978{
1979 int flags=0;
1980 PyObject* txnobj = NULL;
1981 int dlen = -1;
1982 int doff = -1;
1983 PyObject* keyobj, *dataobj, *retval;
1984 DBT key, data;
1985 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001986 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001987 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001988
1989 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1990 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1991 return NULL;
1992
1993 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001994 if (!make_key_dbt(self, keyobj, &key, NULL))
1995 return NULL;
1996 if ( !make_dbt(dataobj, &data) ||
1997 !add_partial_dbt(&data, dlen, doff) ||
1998 !checkTxnObj(txnobj, &txn) )
1999 {
2000 FREE_DBT(key);
2001 return NULL;
2002 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002003
2004 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2005 FREE_DBT(key);
2006 return NULL;
2007 }
2008
2009 if (flags & DB_APPEND)
2010 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2011 else {
2012 retval = Py_None;
2013 Py_INCREF(retval);
2014 }
2015 FREE_DBT(key);
2016 return retval;
2017}
2018
2019
2020
2021static PyObject*
2022DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2023{
2024 char* filename;
2025 char* database = NULL;
2026 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002027 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002028
2029 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2030 &filename, &database, &flags))
2031 return NULL;
2032 CHECK_DB_NOT_CLOSED(self);
2033
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002034 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002035 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002036 RETURN_IF_ERR();
2037 RETURN_NONE();
2038}
2039
2040
2041
2042static PyObject*
2043DB_rename(DBObject* self, PyObject* args)
2044{
2045 char* filename;
2046 char* database;
2047 char* newname;
2048 int err, flags=0;
2049
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002050 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2051 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002052 return NULL;
2053 CHECK_DB_NOT_CLOSED(self);
2054
2055 MYDB_BEGIN_ALLOW_THREADS;
2056 err = self->db->rename(self->db, filename, database, newname, flags);
2057 MYDB_END_ALLOW_THREADS;
2058 RETURN_IF_ERR();
2059 RETURN_NONE();
2060}
2061
2062
2063static PyObject*
2064DB_set_bt_minkey(DBObject* self, PyObject* args)
2065{
2066 int err, minkey;
2067
2068 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2069 return NULL;
2070 CHECK_DB_NOT_CLOSED(self);
2071
2072 MYDB_BEGIN_ALLOW_THREADS;
2073 err = self->db->set_bt_minkey(self->db, minkey);
2074 MYDB_END_ALLOW_THREADS;
2075 RETURN_IF_ERR();
2076 RETURN_NONE();
2077}
2078
Neal Norwitz84562352005-10-20 04:30:15 +00002079#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002081_default_cmp(const DBT *leftKey,
2082 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002083{
2084 int res;
2085 int lsize = leftKey->size, rsize = rightKey->size;
2086
Georg Brandlef1701f2006-03-07 14:57:48 +00002087 res = memcmp(leftKey->data, rightKey->data,
2088 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002089
2090 if (res == 0) {
2091 if (lsize < rsize) {
2092 res = -1;
2093 }
2094 else if (lsize > rsize) {
2095 res = 1;
2096 }
2097 }
2098 return res;
2099}
2100
2101static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002102_db_compareCallback(DB* db,
2103 const DBT *leftKey,
2104 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002105{
2106 int res = 0;
2107 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002108 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002109 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002110
2111 if (self == NULL || self->btCompareCallback == NULL) {
2112 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002113 PyErr_SetString(PyExc_TypeError,
2114 (self == 0
2115 ? "DB_bt_compare db is NULL."
2116 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002117 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002118 PyErr_Print();
2119 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002121 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122 MYDB_BEGIN_BLOCK_THREADS;
2123
Thomas Woutersb3153832006-03-08 01:47:19 +00002124 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2125 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002127 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002132 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 PyErr_Print();
2134 res = _default_cmp(leftKey, rightKey);
2135 } else if (PyInt_Check(result)) {
2136 res = PyInt_AsLong(result);
2137 } else {
2138 PyErr_SetString(PyExc_TypeError,
2139 "DB_bt_compare callback MUST return an int.");
2140 /* we're in a callback within the DB code, we can't raise */
2141 PyErr_Print();
2142 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002143 }
2144
Thomas Woutersb3153832006-03-08 01:47:19 +00002145 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002146 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002147
2148 MYDB_END_BLOCK_THREADS;
2149 }
2150 return res;
2151}
2152
2153static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002154DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155{
2156 int err;
2157 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002158 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002159
Georg Brandlef1701f2006-03-07 14:57:48 +00002160 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002161 return NULL;
2162
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164
Georg Brandlef1701f2006-03-07 14:57:48 +00002165 if (!PyCallable_Check(comparator)) {
2166 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002167 return NULL;
2168 }
2169
2170 /*
2171 * Perform a test call of the comparator function with two empty
2172 * string objects here. verify that it returns an int (0).
2173 * err if not.
2174 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002175 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002176 result = PyEval_CallObject(comparator, tuple);
2177 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002178 if (result == NULL)
2179 return NULL;
2180 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002181 PyErr_SetString(PyExc_TypeError,
2182 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002184 } else if (PyInt_AsLong(result) != 0) {
2185 PyErr_SetString(PyExc_TypeError,
2186 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187 return NULL;
2188 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002189 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002190
2191 /* We don't accept multiple set_bt_compare operations, in order to
2192 * simplify the code. This would have no real use, as one cannot
2193 * change the function once the db is opened anyway */
2194 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002195 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002196 return NULL;
2197 }
2198
Georg Brandlef1701f2006-03-07 14:57:48 +00002199 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200 self->btCompareCallback = comparator;
2201
2202 /* This is to workaround a problem with un-initialized threads (see
2203 comment in DB_associate) */
2204#ifdef WITH_THREAD
2205 PyEval_InitThreads();
2206#endif
2207
Thomas Woutersb3153832006-03-08 01:47:19 +00002208 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002209
2210 if (err) {
2211 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002212 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213 self->btCompareCallback = NULL;
2214 }
2215
Georg Brandlef1701f2006-03-07 14:57:48 +00002216 RETURN_IF_ERR();
2217 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002218}
Neal Norwitz84562352005-10-20 04:30:15 +00002219#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002220
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002221
2222static PyObject*
2223DB_set_cachesize(DBObject* self, PyObject* args)
2224{
2225 int err;
2226 int gbytes = 0, bytes = 0, ncache = 0;
2227
2228 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2229 &gbytes,&bytes,&ncache))
2230 return NULL;
2231 CHECK_DB_NOT_CLOSED(self);
2232
2233 MYDB_BEGIN_ALLOW_THREADS;
2234 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2235 MYDB_END_ALLOW_THREADS;
2236 RETURN_IF_ERR();
2237 RETURN_NONE();
2238}
2239
2240
2241static PyObject*
2242DB_set_flags(DBObject* self, PyObject* args)
2243{
2244 int err, flags;
2245
2246 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2247 return NULL;
2248 CHECK_DB_NOT_CLOSED(self);
2249
2250 MYDB_BEGIN_ALLOW_THREADS;
2251 err = self->db->set_flags(self->db, flags);
2252 MYDB_END_ALLOW_THREADS;
2253 RETURN_IF_ERR();
2254
2255 self->setflags |= flags;
2256 RETURN_NONE();
2257}
2258
2259
2260static PyObject*
2261DB_set_h_ffactor(DBObject* self, PyObject* args)
2262{
2263 int err, ffactor;
2264
2265 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2266 return NULL;
2267 CHECK_DB_NOT_CLOSED(self);
2268
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->set_h_ffactor(self->db, ffactor);
2271 MYDB_END_ALLOW_THREADS;
2272 RETURN_IF_ERR();
2273 RETURN_NONE();
2274}
2275
2276
2277static PyObject*
2278DB_set_h_nelem(DBObject* self, PyObject* args)
2279{
2280 int err, nelem;
2281
2282 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2283 return NULL;
2284 CHECK_DB_NOT_CLOSED(self);
2285
2286 MYDB_BEGIN_ALLOW_THREADS;
2287 err = self->db->set_h_nelem(self->db, nelem);
2288 MYDB_END_ALLOW_THREADS;
2289 RETURN_IF_ERR();
2290 RETURN_NONE();
2291}
2292
2293
2294static PyObject*
2295DB_set_lorder(DBObject* self, PyObject* args)
2296{
2297 int err, lorder;
2298
2299 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2300 return NULL;
2301 CHECK_DB_NOT_CLOSED(self);
2302
2303 MYDB_BEGIN_ALLOW_THREADS;
2304 err = self->db->set_lorder(self->db, lorder);
2305 MYDB_END_ALLOW_THREADS;
2306 RETURN_IF_ERR();
2307 RETURN_NONE();
2308}
2309
2310
2311static PyObject*
2312DB_set_pagesize(DBObject* self, PyObject* args)
2313{
2314 int err, pagesize;
2315
2316 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319
2320 MYDB_BEGIN_ALLOW_THREADS;
2321 err = self->db->set_pagesize(self->db, pagesize);
2322 MYDB_END_ALLOW_THREADS;
2323 RETURN_IF_ERR();
2324 RETURN_NONE();
2325}
2326
2327
2328static PyObject*
2329DB_set_re_delim(DBObject* self, PyObject* args)
2330{
2331 int err;
2332 char delim;
2333
2334 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2335 PyErr_Clear();
2336 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2337 return NULL;
2338 }
2339
2340 CHECK_DB_NOT_CLOSED(self);
2341
2342 MYDB_BEGIN_ALLOW_THREADS;
2343 err = self->db->set_re_delim(self->db, delim);
2344 MYDB_END_ALLOW_THREADS;
2345 RETURN_IF_ERR();
2346 RETURN_NONE();
2347}
2348
2349static PyObject*
2350DB_set_re_len(DBObject* self, PyObject* args)
2351{
2352 int err, len;
2353
2354 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2355 return NULL;
2356 CHECK_DB_NOT_CLOSED(self);
2357
2358 MYDB_BEGIN_ALLOW_THREADS;
2359 err = self->db->set_re_len(self->db, len);
2360 MYDB_END_ALLOW_THREADS;
2361 RETURN_IF_ERR();
2362 RETURN_NONE();
2363}
2364
2365
2366static PyObject*
2367DB_set_re_pad(DBObject* self, PyObject* args)
2368{
2369 int err;
2370 char pad;
2371
2372 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2373 PyErr_Clear();
2374 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2375 return NULL;
2376 }
2377 CHECK_DB_NOT_CLOSED(self);
2378
2379 MYDB_BEGIN_ALLOW_THREADS;
2380 err = self->db->set_re_pad(self->db, pad);
2381 MYDB_END_ALLOW_THREADS;
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2384}
2385
2386
2387static PyObject*
2388DB_set_re_source(DBObject* self, PyObject* args)
2389{
2390 int err;
2391 char *re_source;
2392
2393 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2394 return NULL;
2395 CHECK_DB_NOT_CLOSED(self);
2396
2397 MYDB_BEGIN_ALLOW_THREADS;
2398 err = self->db->set_re_source(self->db, re_source);
2399 MYDB_END_ALLOW_THREADS;
2400 RETURN_IF_ERR();
2401 RETURN_NONE();
2402}
2403
2404
2405#if (DBVER >= 32)
2406static PyObject*
2407DB_set_q_extentsize(DBObject* self, PyObject* args)
2408{
2409 int err;
2410 int extentsize;
2411
2412 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2413 return NULL;
2414 CHECK_DB_NOT_CLOSED(self);
2415
2416 MYDB_BEGIN_ALLOW_THREADS;
2417 err = self->db->set_q_extentsize(self->db, extentsize);
2418 MYDB_END_ALLOW_THREADS;
2419 RETURN_IF_ERR();
2420 RETURN_NONE();
2421}
2422#endif
2423
2424static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002425DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426{
2427 int err, flags = 0, type;
2428 void* sp;
2429 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430#if (DBVER >= 43)
2431 PyObject* txnobj = NULL;
2432 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002433 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002435 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002436#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002437
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438#if (DBVER >= 43)
2439 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2440 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002442 if (!checkTxnObj(txnobj, &txn))
2443 return NULL;
2444#else
2445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2446 return NULL;
2447#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002448 CHECK_DB_NOT_CLOSED(self);
2449
2450 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#if (DBVER >= 43)
2452 err = self->db->stat(self->db, txn, &sp, flags);
2453#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002454 err = self->db->stat(self->db, &sp, flags);
2455#else
2456 err = self->db->stat(self->db, &sp, NULL, flags);
2457#endif
2458 MYDB_END_ALLOW_THREADS;
2459 RETURN_IF_ERR();
2460
2461 self->haveStat = 1;
2462
2463 /* Turn the stat structure into a dictionary */
2464 type = _DB_get_type(self);
2465 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2466 free(sp);
2467 return NULL;
2468 }
2469
2470#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2471#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2472#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2473
2474 switch (type) {
2475 case DB_HASH:
2476 MAKE_HASH_ENTRY(magic);
2477 MAKE_HASH_ENTRY(version);
2478 MAKE_HASH_ENTRY(nkeys);
2479 MAKE_HASH_ENTRY(ndata);
2480 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002481#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002482 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002483#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002484 MAKE_HASH_ENTRY(ffactor);
2485 MAKE_HASH_ENTRY(buckets);
2486 MAKE_HASH_ENTRY(free);
2487 MAKE_HASH_ENTRY(bfree);
2488 MAKE_HASH_ENTRY(bigpages);
2489 MAKE_HASH_ENTRY(big_bfree);
2490 MAKE_HASH_ENTRY(overflows);
2491 MAKE_HASH_ENTRY(ovfl_free);
2492 MAKE_HASH_ENTRY(dup);
2493 MAKE_HASH_ENTRY(dup_free);
2494 break;
2495
2496 case DB_BTREE:
2497 case DB_RECNO:
2498 MAKE_BT_ENTRY(magic);
2499 MAKE_BT_ENTRY(version);
2500 MAKE_BT_ENTRY(nkeys);
2501 MAKE_BT_ENTRY(ndata);
2502 MAKE_BT_ENTRY(pagesize);
2503 MAKE_BT_ENTRY(minkey);
2504 MAKE_BT_ENTRY(re_len);
2505 MAKE_BT_ENTRY(re_pad);
2506 MAKE_BT_ENTRY(levels);
2507 MAKE_BT_ENTRY(int_pg);
2508 MAKE_BT_ENTRY(leaf_pg);
2509 MAKE_BT_ENTRY(dup_pg);
2510 MAKE_BT_ENTRY(over_pg);
2511 MAKE_BT_ENTRY(free);
2512 MAKE_BT_ENTRY(int_pgfree);
2513 MAKE_BT_ENTRY(leaf_pgfree);
2514 MAKE_BT_ENTRY(dup_pgfree);
2515 MAKE_BT_ENTRY(over_pgfree);
2516 break;
2517
2518 case DB_QUEUE:
2519 MAKE_QUEUE_ENTRY(magic);
2520 MAKE_QUEUE_ENTRY(version);
2521 MAKE_QUEUE_ENTRY(nkeys);
2522 MAKE_QUEUE_ENTRY(ndata);
2523 MAKE_QUEUE_ENTRY(pagesize);
2524 MAKE_QUEUE_ENTRY(pages);
2525 MAKE_QUEUE_ENTRY(re_len);
2526 MAKE_QUEUE_ENTRY(re_pad);
2527 MAKE_QUEUE_ENTRY(pgfree);
2528#if (DBVER == 31)
2529 MAKE_QUEUE_ENTRY(start);
2530#endif
2531 MAKE_QUEUE_ENTRY(first_recno);
2532 MAKE_QUEUE_ENTRY(cur_recno);
2533 break;
2534
2535 default:
2536 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2537 Py_DECREF(d);
2538 d = NULL;
2539 }
2540
2541#undef MAKE_HASH_ENTRY
2542#undef MAKE_BT_ENTRY
2543#undef MAKE_QUEUE_ENTRY
2544
2545 free(sp);
2546 return d;
2547}
2548
2549static PyObject*
2550DB_sync(DBObject* self, PyObject* args)
2551{
2552 int err;
2553 int flags = 0;
2554
2555 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2556 return NULL;
2557 CHECK_DB_NOT_CLOSED(self);
2558
2559 MYDB_BEGIN_ALLOW_THREADS;
2560 err = self->db->sync(self->db, flags);
2561 MYDB_END_ALLOW_THREADS;
2562 RETURN_IF_ERR();
2563 RETURN_NONE();
2564}
2565
2566
2567#if (DBVER >= 33)
2568static PyObject*
2569DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2570{
2571 int err, flags=0;
2572 u_int32_t count=0;
2573 PyObject* txnobj = NULL;
2574 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002575 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002576
2577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2578 &txnobj, &flags))
2579 return NULL;
2580 CHECK_DB_NOT_CLOSED(self);
2581 if (!checkTxnObj(txnobj, &txn))
2582 return NULL;
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->truncate(self->db, txn, &count, flags);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
2588 return PyInt_FromLong(count);
2589}
2590#endif
2591
2592
2593static PyObject*
2594DB_upgrade(DBObject* self, PyObject* args)
2595{
2596 int err, flags=0;
2597 char *filename;
2598
2599 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2600 return NULL;
2601 CHECK_DB_NOT_CLOSED(self);
2602
2603 MYDB_BEGIN_ALLOW_THREADS;
2604 err = self->db->upgrade(self->db, filename, flags);
2605 MYDB_END_ALLOW_THREADS;
2606 RETURN_IF_ERR();
2607 RETURN_NONE();
2608}
2609
2610
2611static PyObject*
2612DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2613{
2614 int err, flags=0;
2615 char* fileName;
2616 char* dbName=NULL;
2617 char* outFileName=NULL;
2618 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002619 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002620 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002621
2622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2623 &fileName, &dbName, &outFileName, &flags))
2624 return NULL;
2625
2626 CHECK_DB_NOT_CLOSED(self);
2627 if (outFileName)
2628 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002629 /* XXX(nnorwitz): it should probably be an exception if outFile
2630 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002631
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2634 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002635 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002637
2638 /* DB.verify acts as a DB handle destructor (like close); this was
2639 * documented in BerkeleyDB 4.2 but had the undocumented effect
2640 * of not being safe in prior versions while still requiring an explicit
2641 * DB.close call afterwards. Lets call close for the user to emulate
2642 * the safe 4.2 behaviour. */
2643#if (DBVER <= 41)
2644 self->db->close(self->db, 0);
2645#endif
2646 self->db = NULL;
2647
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002648 RETURN_IF_ERR();
2649 RETURN_NONE();
2650}
2651
2652
2653static PyObject*
2654DB_set_get_returns_none(DBObject* self, PyObject* args)
2655{
2656 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002657 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658
2659 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2660 return NULL;
2661 CHECK_DB_NOT_CLOSED(self);
2662
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002663 if (self->moduleFlags.getReturnsNone)
2664 ++oldValue;
2665 if (self->moduleFlags.cursorSetReturnsNone)
2666 ++oldValue;
2667 self->moduleFlags.getReturnsNone = (flags >= 1);
2668 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002669 return PyInt_FromLong(oldValue);
2670}
2671
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002672#if (DBVER >= 41)
2673static PyObject*
2674DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2675{
2676 int err;
2677 u_int32_t flags=0;
2678 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002679 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002680
2681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2682 &passwd, &flags)) {
2683 return NULL;
2684 }
2685
2686 MYDB_BEGIN_ALLOW_THREADS;
2687 err = self->db->set_encrypt(self->db, passwd, flags);
2688 MYDB_END_ALLOW_THREADS;
2689
2690 RETURN_IF_ERR();
2691 RETURN_NONE();
2692}
2693#endif /* DBVER >= 41 */
2694
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695
2696/*-------------------------------------------------------------- */
2697/* Mapping and Dictionary-like access routines */
2698
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002699Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700{
2701 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002702 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703 int flags = 0;
2704 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002705 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706
2707 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002708 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2709 PyErr_SetObject(DBError, t);
2710 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002711 return -1;
2712 }
2713
2714 if (self->haveStat) { /* Has the stat function been called recently? If
2715 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002716 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717 }
2718
2719 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002720redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002721#if (DBVER >= 43)
2722 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2723#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002724 err = self->db->stat(self->db, &sp, flags);
2725#else
2726 err = self->db->stat(self->db, &sp, NULL, flags);
2727#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002728
2729 /* All the stat structures have matching fields upto the ndata field,
2730 so we can use any of them for the type cast */
2731 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2732
2733 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2734 * redo a full stat to make sure.
2735 * Fixes SF python bug 1493322, pybsddb bug 1184012
2736 */
2737 if (size == 0 && (flags & DB_FAST_STAT)) {
2738 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002739 if (!err)
2740 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002741 goto redo_stat_for_length;
2742 }
2743
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 MYDB_END_ALLOW_THREADS;
2745
2746 if (err)
2747 return -1;
2748
2749 self->haveStat = 1;
2750
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002751 free(sp);
2752 return size;
2753}
2754
2755
2756PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2757{
2758 int err;
2759 PyObject* retval;
2760 DBT key;
2761 DBT data;
2762
2763 CHECK_DB_NOT_CLOSED(self);
2764 if (!make_key_dbt(self, keyobj, &key, NULL))
2765 return NULL;
2766
2767 CLEAR_DBT(data);
2768 if (CHECK_DBFLAG(self, DB_THREAD)) {
2769 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2770 data.flags = DB_DBT_MALLOC;
2771 }
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->get(self->db, NULL, &key, &data, 0);
2774 MYDB_END_ALLOW_THREADS;
2775 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2776 PyErr_SetObject(PyExc_KeyError, keyobj);
2777 retval = NULL;
2778 }
2779 else if (makeDBError(err)) {
2780 retval = NULL;
2781 }
2782 else {
2783 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2784 FREE_DBT(data);
2785 }
2786
2787 FREE_DBT(key);
2788 return retval;
2789}
2790
2791
2792static int
2793DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2794{
2795 DBT key, data;
2796 int retval;
2797 int flags = 0;
2798
2799 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002800 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2801 PyErr_SetObject(DBError, t);
2802 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 return -1;
2804 }
2805
2806 if (!make_key_dbt(self, keyobj, &key, NULL))
2807 return -1;
2808
2809 if (dataobj != NULL) {
2810 if (!make_dbt(dataobj, &data))
2811 retval = -1;
2812 else {
2813 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002814 /* dictionaries shouldn't have duplicate keys */
2815 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002816 retval = _DB_put(self, NULL, &key, &data, flags);
2817
2818 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002819 /* try deleting any old record that matches and then PUT it
2820 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002821 _DB_delete(self, NULL, &key, 0);
2822 PyErr_Clear();
2823 retval = _DB_put(self, NULL, &key, &data, flags);
2824 }
2825 }
2826 }
2827 else {
2828 /* dataobj == NULL, so delete the key */
2829 retval = _DB_delete(self, NULL, &key, 0);
2830 }
2831 FREE_DBT(key);
2832 return retval;
2833}
2834
2835
2836static PyObject*
2837DB_has_key(DBObject* self, PyObject* args)
2838{
2839 int err;
2840 PyObject* keyobj;
2841 DBT key, data;
2842 PyObject* txnobj = NULL;
2843 DB_TXN *txn = NULL;
2844
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002845 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 return NULL;
2847 CHECK_DB_NOT_CLOSED(self);
2848 if (!make_key_dbt(self, keyobj, &key, NULL))
2849 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002850 if (!checkTxnObj(txnobj, &txn)) {
2851 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002852 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002853 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002855 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002856 it has a record but can't allocate a buffer for the data. This saves
2857 having to deal with data we won't be using.
2858 */
2859 CLEAR_DBT(data);
2860 data.flags = DB_DBT_USERMEM;
2861
2862 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002863 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002864 MYDB_END_ALLOW_THREADS;
2865 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002866
2867 if (err == DB_BUFFER_SMALL || err == 0) {
2868 return PyInt_FromLong(1);
2869 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2870 return PyInt_FromLong(0);
2871 }
2872
2873 makeDBError(err);
2874 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875}
2876
2877
2878#define _KEYS_LIST 1
2879#define _VALUES_LIST 2
2880#define _ITEMS_LIST 3
2881
2882static PyObject*
2883_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2884{
2885 int err, dbtype;
2886 DBT key;
2887 DBT data;
2888 DBC *cursor;
2889 PyObject* list;
2890 PyObject* item = NULL;
2891
2892 CHECK_DB_NOT_CLOSED(self);
2893 CLEAR_DBT(key);
2894 CLEAR_DBT(data);
2895
2896 dbtype = _DB_get_type(self);
2897 if (dbtype == -1)
2898 return NULL;
2899
2900 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002901 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002902 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002903
2904 /* get a cursor */
2905 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002906 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002908 if (makeDBError(err)) {
2909 Py_DECREF(list);
2910 return NULL;
2911 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002912
2913 if (CHECK_DBFLAG(self, DB_THREAD)) {
2914 key.flags = DB_DBT_REALLOC;
2915 data.flags = DB_DBT_REALLOC;
2916 }
2917
2918 while (1) { /* use the cursor to traverse the DB, collecting items */
2919 MYDB_BEGIN_ALLOW_THREADS;
2920 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2921 MYDB_END_ALLOW_THREADS;
2922
2923 if (err) {
2924 /* for any error, break out of the loop */
2925 break;
2926 }
2927
2928 switch (type) {
2929 case _KEYS_LIST:
2930 switch(dbtype) {
2931 case DB_BTREE:
2932 case DB_HASH:
2933 default:
2934 item = PyString_FromStringAndSize((char*)key.data, key.size);
2935 break;
2936 case DB_RECNO:
2937 case DB_QUEUE:
2938 item = PyInt_FromLong(*((db_recno_t*)key.data));
2939 break;
2940 }
2941 break;
2942
2943 case _VALUES_LIST:
2944 item = PyString_FromStringAndSize((char*)data.data, data.size);
2945 break;
2946
2947 case _ITEMS_LIST:
2948 switch(dbtype) {
2949 case DB_BTREE:
2950 case DB_HASH:
2951 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002952 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2953 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002954 break;
2955 case DB_RECNO:
2956 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002957 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2958 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002959 break;
2960 }
2961 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002962 default:
2963 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2964 item = NULL;
2965 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002966 }
2967 if (item == NULL) {
2968 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002969 list = NULL;
2970 goto done;
2971 }
2972 PyList_Append(list, item);
2973 Py_DECREF(item);
2974 }
2975
Gregory P. Smithe9477062005-06-04 06:46:59 +00002976 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2977 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002978 Py_DECREF(list);
2979 list = NULL;
2980 }
2981
2982 done:
2983 FREE_DBT(key);
2984 FREE_DBT(data);
2985 MYDB_BEGIN_ALLOW_THREADS;
2986 cursor->c_close(cursor);
2987 MYDB_END_ALLOW_THREADS;
2988 return list;
2989}
2990
2991
2992static PyObject*
2993DB_keys(DBObject* self, PyObject* args)
2994{
2995 PyObject* txnobj = NULL;
2996 DB_TXN *txn = NULL;
2997
Georg Brandl96a8c392006-05-29 21:04:52 +00002998 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002999 return NULL;
3000 if (!checkTxnObj(txnobj, &txn))
3001 return NULL;
3002 return _DB_make_list(self, txn, _KEYS_LIST);
3003}
3004
3005
3006static PyObject*
3007DB_items(DBObject* self, PyObject* args)
3008{
3009 PyObject* txnobj = NULL;
3010 DB_TXN *txn = NULL;
3011
Georg Brandl96a8c392006-05-29 21:04:52 +00003012 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003013 return NULL;
3014 if (!checkTxnObj(txnobj, &txn))
3015 return NULL;
3016 return _DB_make_list(self, txn, _ITEMS_LIST);
3017}
3018
3019
3020static PyObject*
3021DB_values(DBObject* self, PyObject* args)
3022{
3023 PyObject* txnobj = NULL;
3024 DB_TXN *txn = NULL;
3025
Georg Brandl96a8c392006-05-29 21:04:52 +00003026 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003027 return NULL;
3028 if (!checkTxnObj(txnobj, &txn))
3029 return NULL;
3030 return _DB_make_list(self, txn, _VALUES_LIST);
3031}
3032
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033/* --------------------------------------------------------------------- */
3034/* DBCursor methods */
3035
3036
3037static PyObject*
3038DBC_close(DBCursorObject* self, PyObject* args)
3039{
3040 int err = 0;
3041
3042 if (!PyArg_ParseTuple(args, ":close"))
3043 return NULL;
3044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 if (self->dbc != NULL) {
3046 MYDB_BEGIN_ALLOW_THREADS;
3047 err = self->dbc->c_close(self->dbc);
3048 self->dbc = NULL;
3049 MYDB_END_ALLOW_THREADS;
3050 }
3051 RETURN_IF_ERR();
3052 RETURN_NONE();
3053}
3054
3055
3056static PyObject*
3057DBC_count(DBCursorObject* self, PyObject* args)
3058{
3059 int err = 0;
3060 db_recno_t count;
3061 int flags = 0;
3062
3063 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3064 return NULL;
3065
3066 CHECK_CURSOR_NOT_CLOSED(self);
3067
3068 MYDB_BEGIN_ALLOW_THREADS;
3069 err = self->dbc->c_count(self->dbc, &count, flags);
3070 MYDB_END_ALLOW_THREADS;
3071 RETURN_IF_ERR();
3072
3073 return PyInt_FromLong(count);
3074}
3075
3076
3077static PyObject*
3078DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3079{
3080 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3081}
3082
3083
3084static PyObject*
3085DBC_delete(DBCursorObject* self, PyObject* args)
3086{
3087 int err, flags=0;
3088
3089 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3090 return NULL;
3091
3092 CHECK_CURSOR_NOT_CLOSED(self);
3093
3094 MYDB_BEGIN_ALLOW_THREADS;
3095 err = self->dbc->c_del(self->dbc, flags);
3096 MYDB_END_ALLOW_THREADS;
3097 RETURN_IF_ERR();
3098
3099 self->mydb->haveStat = 0;
3100 RETURN_NONE();
3101}
3102
3103
3104static PyObject*
3105DBC_dup(DBCursorObject* self, PyObject* args)
3106{
3107 int err, flags =0;
3108 DBC* dbc = NULL;
3109
3110 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3111 return NULL;
3112
3113 CHECK_CURSOR_NOT_CLOSED(self);
3114
3115 MYDB_BEGIN_ALLOW_THREADS;
3116 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3117 MYDB_END_ALLOW_THREADS;
3118 RETURN_IF_ERR();
3119
3120 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3121}
3122
3123static PyObject*
3124DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3125{
3126 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3127}
3128
3129
3130static PyObject*
3131DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3132{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003133 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003134 PyObject* keyobj = NULL;
3135 PyObject* dataobj = NULL;
3136 PyObject* retval = NULL;
3137 int dlen = -1;
3138 int doff = -1;
3139 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003140 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003141 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142
3143 CLEAR_DBT(key);
3144 CLEAR_DBT(data);
3145 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003146 &flags, &dlen, &doff))
3147 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003148 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003149 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3150 &kwnames[1],
3151 &keyobj, &flags, &dlen, &doff))
3152 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003153 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3155 kwnames, &keyobj, &dataobj,
3156 &flags, &dlen, &doff))
3157 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158 return NULL;
3159 }
3160 }
3161 }
3162
3163 CHECK_CURSOR_NOT_CLOSED(self);
3164
3165 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3166 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003167 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3168 (!add_partial_dbt(&data, dlen, doff)) )
3169 {
3170 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003171 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003172 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173
3174 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3175 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003176 if (!(key.flags & DB_DBT_REALLOC)) {
3177 key.flags |= DB_DBT_MALLOC;
3178 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 }
3180
3181 MYDB_BEGIN_ALLOW_THREADS;
3182 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3183 MYDB_END_ALLOW_THREADS;
3184
Gregory P. Smithe9477062005-06-04 06:46:59 +00003185 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3186 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003187 Py_INCREF(Py_None);
3188 retval = Py_None;
3189 }
3190 else if (makeDBError(err)) {
3191 retval = NULL;
3192 }
3193 else {
3194 switch (_DB_get_type(self->mydb)) {
3195 case -1:
3196 retval = NULL;
3197 break;
3198 case DB_BTREE:
3199 case DB_HASH:
3200 default:
3201 retval = Py_BuildValue("s#s#", key.data, key.size,
3202 data.data, data.size);
3203 break;
3204 case DB_RECNO:
3205 case DB_QUEUE:
3206 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3207 data.data, data.size);
3208 break;
3209 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 FREE_DBT(data);
3211 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003212 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003213 return retval;
3214}
3215
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003216#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003217static PyObject*
3218DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3219{
3220 int err, flags=0;
3221 PyObject* keyobj = NULL;
3222 PyObject* dataobj = NULL;
3223 PyObject* retval = NULL;
3224 int dlen = -1;
3225 int doff = -1;
3226 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003227 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3228 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003229
3230 CLEAR_DBT(key);
3231 CLEAR_DBT(data);
3232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3233 &flags, &dlen, &doff))
3234 {
3235 PyErr_Clear();
3236 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003237 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003238 &keyobj, &flags, &dlen, &doff))
3239 {
3240 PyErr_Clear();
3241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3242 kwnames, &keyobj, &dataobj,
3243 &flags, &dlen, &doff))
3244 {
3245 return NULL;
3246 }
3247 }
3248 }
3249
3250 CHECK_CURSOR_NOT_CLOSED(self);
3251
3252 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3253 return NULL;
3254 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3255 (!add_partial_dbt(&data, dlen, doff)) ) {
3256 FREE_DBT(key);
3257 return NULL;
3258 }
3259
3260 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3261 data.flags = DB_DBT_MALLOC;
3262 if (!(key.flags & DB_DBT_REALLOC)) {
3263 key.flags |= DB_DBT_MALLOC;
3264 }
3265 }
3266
3267 CLEAR_DBT(pkey);
3268 pkey.flags = DB_DBT_MALLOC;
3269
3270 MYDB_BEGIN_ALLOW_THREADS;
3271 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3272 MYDB_END_ALLOW_THREADS;
3273
Gregory P. Smithe9477062005-06-04 06:46:59 +00003274 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3275 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003276 Py_INCREF(Py_None);
3277 retval = Py_None;
3278 }
3279 else if (makeDBError(err)) {
3280 retval = NULL;
3281 }
3282 else {
3283 PyObject *pkeyObj;
3284 PyObject *dataObj;
3285 dataObj = PyString_FromStringAndSize(data.data, data.size);
3286
3287 if (self->mydb->primaryDBType == DB_RECNO ||
3288 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003289 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003290 else
3291 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3292
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003293 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003294 {
3295 PyObject *keyObj;
3296 int type = _DB_get_type(self->mydb);
3297 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003298 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 else
3300 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003301#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003302 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003303#else
3304 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3305#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003306 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307 FREE_DBT(key);
3308 }
3309 else /* return just the pkey and data */
3310 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003311#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003312 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003313#else
3314 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3315#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003316 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003317 Py_DECREF(dataObj);
3318 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003319 FREE_DBT(pkey);
3320 FREE_DBT(data);
3321 }
3322 /* the only time REALLOC should be set is if we used an integer
3323 * key that make_key_dbt malloc'd for us. always free these. */
3324 if (key.flags & DB_DBT_REALLOC) {
3325 FREE_DBT(key);
3326 }
3327 return retval;
3328}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003329#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003330
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003331
3332static PyObject*
3333DBC_get_recno(DBCursorObject* self, PyObject* args)
3334{
3335 int err;
3336 db_recno_t recno;
3337 DBT key;
3338 DBT data;
3339
3340 if (!PyArg_ParseTuple(args, ":get_recno"))
3341 return NULL;
3342
3343 CHECK_CURSOR_NOT_CLOSED(self);
3344
3345 CLEAR_DBT(key);
3346 CLEAR_DBT(data);
3347 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3348 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3349 data.flags = DB_DBT_MALLOC;
3350 key.flags = DB_DBT_MALLOC;
3351 }
3352
3353 MYDB_BEGIN_ALLOW_THREADS;
3354 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3355 MYDB_END_ALLOW_THREADS;
3356 RETURN_IF_ERR();
3357
3358 recno = *((db_recno_t*)data.data);
3359 FREE_DBT(key);
3360 FREE_DBT(data);
3361 return PyInt_FromLong(recno);
3362}
3363
3364
3365static PyObject*
3366DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3367{
3368 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3369}
3370
3371
3372static PyObject*
3373DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3374{
3375 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3376}
3377
3378
3379static PyObject*
3380DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3381{
3382 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3383}
3384
3385
3386static PyObject*
3387DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3388{
3389 int err, flags = 0;
3390 PyObject* keyobj, *dataobj;
3391 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003392 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003393 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 int dlen = -1;
3395 int doff = -1;
3396
3397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3398 &keyobj, &dataobj, &flags, &dlen, &doff))
3399 return NULL;
3400
3401 CHECK_CURSOR_NOT_CLOSED(self);
3402
3403 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3404 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003405 if (!make_dbt(dataobj, &data) ||
3406 !add_partial_dbt(&data, dlen, doff) )
3407 {
3408 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003410 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411
3412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3414 MYDB_END_ALLOW_THREADS;
3415 FREE_DBT(key);
3416 RETURN_IF_ERR();
3417 self->mydb->haveStat = 0;
3418 RETURN_NONE();
3419}
3420
3421
3422static PyObject*
3423DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3424{
3425 int err, flags = 0;
3426 DBT key, data;
3427 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003428 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003429 int dlen = -1;
3430 int doff = -1;
3431
3432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3433 &keyobj, &flags, &dlen, &doff))
3434 return NULL;
3435
3436 CHECK_CURSOR_NOT_CLOSED(self);
3437
3438 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3439 return NULL;
3440
3441 CLEAR_DBT(data);
3442 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3443 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3444 data.flags = DB_DBT_MALLOC;
3445 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003446 if (!add_partial_dbt(&data, dlen, doff)) {
3447 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003450
3451 MYDB_BEGIN_ALLOW_THREADS;
3452 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3453 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003454 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3455 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003456 Py_INCREF(Py_None);
3457 retval = Py_None;
3458 }
3459 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460 retval = NULL;
3461 }
3462 else {
3463 switch (_DB_get_type(self->mydb)) {
3464 case -1:
3465 retval = NULL;
3466 break;
3467 case DB_BTREE:
3468 case DB_HASH:
3469 default:
3470 retval = Py_BuildValue("s#s#", key.data, key.size,
3471 data.data, data.size);
3472 break;
3473 case DB_RECNO:
3474 case DB_QUEUE:
3475 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3476 data.data, data.size);
3477 break;
3478 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003480 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003482 /* the only time REALLOC should be set is if we used an integer
3483 * key that make_key_dbt malloc'd for us. always free these. */
3484 if (key.flags & DB_DBT_REALLOC) {
3485 FREE_DBT(key);
3486 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003487
3488 return retval;
3489}
3490
3491
3492static PyObject*
3493DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3494{
3495 int err, flags = 0;
3496 DBT key, data;
3497 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003498 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003499 int dlen = -1;
3500 int doff = -1;
3501
3502 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3503 &keyobj, &flags, &dlen, &doff))
3504 return NULL;
3505
3506 CHECK_CURSOR_NOT_CLOSED(self);
3507
3508 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3509 return NULL;
3510
3511 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003512 if (!add_partial_dbt(&data, dlen, doff)) {
3513 FREE_DBT(key);
3514 return NULL;
3515 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3517 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003518 data.flags |= DB_DBT_MALLOC;
3519 /* only BTREE databases will return anything in the key */
3520 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3521 key.flags |= DB_DBT_MALLOC;
3522 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003523 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003524 MYDB_BEGIN_ALLOW_THREADS;
3525 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3526 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3528 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003529 Py_INCREF(Py_None);
3530 retval = Py_None;
3531 }
3532 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533 retval = NULL;
3534 }
3535 else {
3536 switch (_DB_get_type(self->mydb)) {
3537 case -1:
3538 retval = NULL;
3539 break;
3540 case DB_BTREE:
3541 case DB_HASH:
3542 default:
3543 retval = Py_BuildValue("s#s#", key.data, key.size,
3544 data.data, data.size);
3545 break;
3546 case DB_RECNO:
3547 case DB_QUEUE:
3548 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3549 data.data, data.size);
3550 break;
3551 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003552 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553 FREE_DBT(data);
3554 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003555 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003556 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003557 if (key.flags & DB_DBT_REALLOC) {
3558 FREE_DBT(key);
3559 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003560
3561 return retval;
3562}
3563
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003564static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003565_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3566 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003568 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003570 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571
Gregory P. Smith7441e652003-11-03 21:35:31 +00003572 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3574 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003575 if (!make_dbt(dataobj, &data)) {
3576 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003578 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579
3580 MYDB_BEGIN_ALLOW_THREADS;
3581 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3582 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003583 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003584 Py_INCREF(Py_None);
3585 retval = Py_None;
3586 }
3587 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 retval = NULL;
3589 }
3590 else {
3591 switch (_DB_get_type(self->mydb)) {
3592 case -1:
3593 retval = NULL;
3594 break;
3595 case DB_BTREE:
3596 case DB_HASH:
3597 default:
3598 retval = Py_BuildValue("s#s#", key.data, key.size,
3599 data.data, data.size);
3600 break;
3601 case DB_RECNO:
3602 case DB_QUEUE:
3603 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3604 data.data, data.size);
3605 break;
3606 }
3607 }
3608
3609 FREE_DBT(key);
3610 return retval;
3611}
3612
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003613static PyObject*
3614DBC_get_both(DBCursorObject* self, PyObject* args)
3615{
3616 int flags=0;
3617 PyObject *keyobj, *dataobj;
3618
3619 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3620 return NULL;
3621
Gregory P. Smith7441e652003-11-03 21:35:31 +00003622 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003623 CHECK_CURSOR_NOT_CLOSED(self);
3624
3625 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3626 self->mydb->moduleFlags.getReturnsNone);
3627}
3628
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003629/* Return size of entry */
3630static PyObject*
3631DBC_get_current_size(DBCursorObject* self, PyObject* args)
3632{
3633 int err, flags=DB_CURRENT;
3634 PyObject* retval = NULL;
3635 DBT key, data;
3636
3637 if (!PyArg_ParseTuple(args, ":get_current_size"))
3638 return NULL;
3639 CHECK_CURSOR_NOT_CLOSED(self);
3640 CLEAR_DBT(key);
3641 CLEAR_DBT(data);
3642
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003643 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003644 getting the record size. */
3645 data.flags = DB_DBT_USERMEM;
3646 data.ulen = 0;
3647 MYDB_BEGIN_ALLOW_THREADS;
3648 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3649 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003650 if (err == DB_BUFFER_SMALL || !err) {
3651 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003652 retval = PyInt_FromLong((long)data.size);
3653 err = 0;
3654 }
3655
3656 FREE_DBT(key);
3657 FREE_DBT(data);
3658 RETURN_IF_ERR();
3659 return retval;
3660}
3661
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003662static PyObject*
3663DBC_set_both(DBCursorObject* self, PyObject* args)
3664{
3665 int flags=0;
3666 PyObject *keyobj, *dataobj;
3667
3668 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3669 return NULL;
3670
Gregory P. Smith7441e652003-11-03 21:35:31 +00003671 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003672 CHECK_CURSOR_NOT_CLOSED(self);
3673
3674 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3675 self->mydb->moduleFlags.cursorSetReturnsNone);
3676}
3677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003678
3679static PyObject*
3680DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3681{
3682 int err, irecno, flags=0;
3683 db_recno_t recno;
3684 DBT key, data;
3685 PyObject* retval;
3686 int dlen = -1;
3687 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003688 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003689
3690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3691 &irecno, &flags, &dlen, &doff))
3692 return NULL;
3693
3694 CHECK_CURSOR_NOT_CLOSED(self);
3695
3696 CLEAR_DBT(key);
3697 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003698 /* use allocated space so DB will be able to realloc room for the real
3699 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003700 key.data = malloc(sizeof(db_recno_t));
3701 if (key.data == NULL) {
3702 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3703 return NULL;
3704 }
3705 key.size = sizeof(db_recno_t);
3706 key.ulen = key.size;
3707 memcpy(key.data, &recno, sizeof(db_recno_t));
3708 key.flags = DB_DBT_REALLOC;
3709
3710 CLEAR_DBT(data);
3711 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3712 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3713 data.flags = DB_DBT_MALLOC;
3714 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003715 if (!add_partial_dbt(&data, dlen, doff)) {
3716 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003718 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719
3720 MYDB_BEGIN_ALLOW_THREADS;
3721 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3722 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003723 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3724 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003725 Py_INCREF(Py_None);
3726 retval = Py_None;
3727 }
3728 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003729 retval = NULL;
3730 }
3731 else { /* Can only be used for BTrees, so no need to return int key */
3732 retval = Py_BuildValue("s#s#", key.data, key.size,
3733 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734 FREE_DBT(data);
3735 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003736 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003737
3738 return retval;
3739}
3740
3741
3742static PyObject*
3743DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3744{
3745 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3746}
3747
3748
3749static PyObject*
3750DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3751{
3752 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3753}
3754
3755
3756static PyObject*
3757DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3758{
3759 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3760}
3761
3762
3763static PyObject*
3764DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3765{
3766 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3767}
3768
3769
3770static PyObject*
3771DBC_join_item(DBCursorObject* self, PyObject* args)
3772{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003773 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003774 DBT key, data;
3775 PyObject* retval;
3776
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003777 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003778 return NULL;
3779
3780 CHECK_CURSOR_NOT_CLOSED(self);
3781
3782 CLEAR_DBT(key);
3783 CLEAR_DBT(data);
3784 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3785 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3786 key.flags = DB_DBT_MALLOC;
3787 }
3788
3789 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003790 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003792 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3793 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003794 Py_INCREF(Py_None);
3795 retval = Py_None;
3796 }
3797 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003798 retval = NULL;
3799 }
3800 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003801 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003802 FREE_DBT(key);
3803 }
3804
3805 return retval;
3806}
3807
3808
3809
3810/* --------------------------------------------------------------------- */
3811/* DBEnv methods */
3812
3813
3814static PyObject*
3815DBEnv_close(DBEnvObject* self, PyObject* args)
3816{
3817 int err, flags = 0;
3818
3819 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3820 return NULL;
3821 if (!self->closed) { /* Don't close more than once */
3822 MYDB_BEGIN_ALLOW_THREADS;
3823 err = self->db_env->close(self->db_env, flags);
3824 MYDB_END_ALLOW_THREADS;
3825 /* after calling DBEnv->close, regardless of error, this DBEnv
3826 * may not be accessed again (BerkeleyDB docs). */
3827 self->closed = 1;
3828 self->db_env = NULL;
3829 RETURN_IF_ERR();
3830 }
3831 RETURN_NONE();
3832}
3833
3834
3835static PyObject*
3836DBEnv_open(DBEnvObject* self, PyObject* args)
3837{
3838 int err, flags=0, mode=0660;
3839 char *db_home;
3840
3841 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3842 return NULL;
3843
3844 CHECK_ENV_NOT_CLOSED(self);
3845
3846 MYDB_BEGIN_ALLOW_THREADS;
3847 err = self->db_env->open(self->db_env, db_home, flags, mode);
3848 MYDB_END_ALLOW_THREADS;
3849 RETURN_IF_ERR();
3850 self->closed = 0;
3851 self->flags = flags;
3852 RETURN_NONE();
3853}
3854
3855
3856static PyObject*
3857DBEnv_remove(DBEnvObject* self, PyObject* args)
3858{
3859 int err, flags=0;
3860 char *db_home;
3861
3862 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3863 return NULL;
3864 CHECK_ENV_NOT_CLOSED(self);
3865 MYDB_BEGIN_ALLOW_THREADS;
3866 err = self->db_env->remove(self->db_env, db_home, flags);
3867 MYDB_END_ALLOW_THREADS;
3868 RETURN_IF_ERR();
3869 RETURN_NONE();
3870}
3871
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003872#if (DBVER >= 41)
3873static PyObject*
3874DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3875{
3876 int err;
3877 u_int32_t flags=0;
3878 char *file = NULL;
3879 char *database = NULL;
3880 PyObject *txnobj = NULL;
3881 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003882 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003883 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003884
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003886 &file, &database, &txnobj, &flags)) {
3887 return NULL;
3888 }
3889 if (!checkTxnObj(txnobj, &txn)) {
3890 return NULL;
3891 }
3892 CHECK_ENV_NOT_CLOSED(self);
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3898}
3899
3900static PyObject*
3901DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3902{
3903 int err;
3904 u_int32_t flags=0;
3905 char *file = NULL;
3906 char *database = NULL;
3907 char *newname = NULL;
3908 PyObject *txnobj = NULL;
3909 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003910 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003911 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003912
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003913 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003914 &file, &database, &newname, &txnobj, &flags)) {
3915 return NULL;
3916 }
3917 if (!checkTxnObj(txnobj, &txn)) {
3918 return NULL;
3919 }
3920 CHECK_ENV_NOT_CLOSED(self);
3921 MYDB_BEGIN_ALLOW_THREADS;
3922 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3923 flags);
3924 MYDB_END_ALLOW_THREADS;
3925 RETURN_IF_ERR();
3926 RETURN_NONE();
3927}
3928
3929static PyObject*
3930DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3931{
3932 int err;
3933 u_int32_t flags=0;
3934 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003935 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003936
3937 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3938 &passwd, &flags)) {
3939 return NULL;
3940 }
3941
3942 MYDB_BEGIN_ALLOW_THREADS;
3943 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3944 MYDB_END_ALLOW_THREADS;
3945
3946 RETURN_IF_ERR();
3947 RETURN_NONE();
3948}
3949#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003950
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003951#if (DBVER >= 40)
3952static PyObject*
3953DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3954{
3955 int err;
3956 u_int32_t flags=0;
3957 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003958 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003959
3960 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3961 &timeout, &flags)) {
3962 return NULL;
3963 }
3964
3965 MYDB_BEGIN_ALLOW_THREADS;
3966 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3967 MYDB_END_ALLOW_THREADS;
3968
3969 RETURN_IF_ERR();
3970 RETURN_NONE();
3971}
3972#endif /* DBVER >= 40 */
3973
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003974static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003975DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3976{
3977 int err;
3978 long shm_key = 0;
3979
3980 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983
3984 err = self->db_env->set_shm_key(self->db_env, shm_key);
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988
3989static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003990DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3991{
3992 int err, gbytes=0, bytes=0, ncache=0;
3993
3994 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3995 &gbytes, &bytes, &ncache))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3998
3999 MYDB_BEGIN_ALLOW_THREADS;
4000 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4001 MYDB_END_ALLOW_THREADS;
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006
4007#if (DBVER >= 32)
4008static PyObject*
4009DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4010{
4011 int err, flags=0, onoff=0;
4012
4013 if (!PyArg_ParseTuple(args, "ii:set_flags",
4014 &flags, &onoff))
4015 return NULL;
4016 CHECK_ENV_NOT_CLOSED(self);
4017
4018 MYDB_BEGIN_ALLOW_THREADS;
4019 err = self->db_env->set_flags(self->db_env, flags, onoff);
4020 MYDB_END_ALLOW_THREADS;
4021 RETURN_IF_ERR();
4022 RETURN_NONE();
4023}
4024#endif
4025
4026
4027static PyObject*
4028DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4029{
4030 int err;
4031 char *dir;
4032
4033 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_data_dir(self->db_env, dir);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045static PyObject*
4046DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4047{
4048 int err, lg_bsize;
4049
4050 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4064{
4065 int err;
4066 char *dir;
4067
4068 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4069 return NULL;
4070 CHECK_ENV_NOT_CLOSED(self);
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->set_lg_dir(self->db_env, dir);
4074 MYDB_END_ALLOW_THREADS;
4075 RETURN_IF_ERR();
4076 RETURN_NONE();
4077}
4078
4079static PyObject*
4080DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4081{
4082 int err, lg_max;
4083
4084 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_max(self->db_env, lg_max);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095
Neal Norwitz84562352005-10-20 04:30:15 +00004096#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004097static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004098DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4099{
4100 int err, lg_max;
4101
4102 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
Neal Norwitz84562352005-10-20 04:30:15 +00004112#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004113
4114
4115static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004116DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4117{
4118 int err, lk_detect;
4119
4120 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
4130
4131
4132static PyObject*
4133DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4134{
4135 int err, max;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_max(self->db_env, max);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
4149#if (DBVER >= 32)
4150
4151static PyObject*
4152DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4153{
4154 int err, max;
4155
4156 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4157 return NULL;
4158 CHECK_ENV_NOT_CLOSED(self);
4159
4160 MYDB_BEGIN_ALLOW_THREADS;
4161 err = self->db_env->set_lk_max_locks(self->db_env, max);
4162 MYDB_END_ALLOW_THREADS;
4163 RETURN_IF_ERR();
4164 RETURN_NONE();
4165}
4166
4167
4168static PyObject*
4169DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4170{
4171 int err, max;
4172
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184
4185static PyObject*
4186DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4187{
4188 int err, max;
4189
4190 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4191 return NULL;
4192 CHECK_ENV_NOT_CLOSED(self);
4193
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_lk_max_objects(self->db_env, max);
4196 MYDB_END_ALLOW_THREADS;
4197 RETURN_IF_ERR();
4198 RETURN_NONE();
4199}
4200
4201#endif
4202
4203
4204static PyObject*
4205DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4206{
4207 int err, mp_mmapsize;
4208
4209 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
4220
4221static PyObject*
4222DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4223{
4224 int err;
4225 char *dir;
4226
4227 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4230
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->set_tmp_dir(self->db_env, dir);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 RETURN_NONE();
4236}
4237
4238
4239static PyObject*
4240DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4241{
4242 int flags = 0;
4243 PyObject* txnobj = NULL;
4244 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004245 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004246
4247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4248 &txnobj, &flags))
4249 return NULL;
4250
4251 if (!checkTxnObj(txnobj, &txn))
4252 return NULL;
4253 CHECK_ENV_NOT_CLOSED(self);
4254
4255 return (PyObject*)newDBTxnObject(self, txn, flags);
4256}
4257
4258
4259static PyObject*
4260DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4261{
4262 int err, kbyte=0, min=0, flags=0;
4263
4264 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4265 return NULL;
4266 CHECK_ENV_NOT_CLOSED(self);
4267
4268 MYDB_BEGIN_ALLOW_THREADS;
4269#if (DBVER >= 40)
4270 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4271#else
4272 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4273#endif
4274 MYDB_END_ALLOW_THREADS;
4275 RETURN_IF_ERR();
4276 RETURN_NONE();
4277}
4278
4279
4280static PyObject*
4281DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4282{
4283 int err, max;
4284
4285 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
4288
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004289 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004290 RETURN_IF_ERR();
4291 RETURN_NONE();
4292}
4293
4294
4295static PyObject*
4296DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4297{
4298 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004299 long stamp;
4300 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004301
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004302 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004305 timestamp = (time_t)stamp;
4306 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004307 RETURN_IF_ERR();
4308 RETURN_NONE();
4309}
4310
4311
4312static PyObject*
4313DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4314{
4315 int err, atype, flags=0;
4316 int aborted = 0;
4317
4318 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4319 return NULL;
4320 CHECK_ENV_NOT_CLOSED(self);
4321
4322 MYDB_BEGIN_ALLOW_THREADS;
4323#if (DBVER >= 40)
4324 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4325#else
4326 err = lock_detect(self->db_env, flags, atype, &aborted);
4327#endif
4328 MYDB_END_ALLOW_THREADS;
4329 RETURN_IF_ERR();
4330 return PyInt_FromLong(aborted);
4331}
4332
4333
4334static PyObject*
4335DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4336{
4337 int flags=0;
4338 int locker, lock_mode;
4339 DBT obj;
4340 PyObject* objobj;
4341
4342 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4343 return NULL;
4344
4345
4346 if (!make_dbt(objobj, &obj))
4347 return NULL;
4348
4349 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4350}
4351
4352
4353static PyObject*
4354DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4355{
4356 int err;
4357 u_int32_t theID;
4358
4359 if (!PyArg_ParseTuple(args, ":lock_id"))
4360 return NULL;
4361
4362 CHECK_ENV_NOT_CLOSED(self);
4363 MYDB_BEGIN_ALLOW_THREADS;
4364#if (DBVER >= 40)
4365 err = self->db_env->lock_id(self->db_env, &theID);
4366#else
4367 err = lock_id(self->db_env, &theID);
4368#endif
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4371
4372 return PyInt_FromLong((long)theID);
4373}
4374
4375
4376static PyObject*
4377DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4378{
4379 int err;
4380 DBLockObject* dblockobj;
4381
4382 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
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_put(self->db_env, &dblockobj->lock);
4389#else
4390 err = lock_put(self->db_env, &dblockobj->lock);
4391#endif
4392 MYDB_END_ALLOW_THREADS;
4393 RETURN_IF_ERR();
4394 RETURN_NONE();
4395}
4396
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004397#if (DBVER >= 44)
4398static PyObject*
4399DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4400{
4401 int err;
4402 char *file;
4403 u_int32_t flags = 0;
4404 static char* kwnames[] = { "file", "flags", NULL};
4405
4406 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4407 &file, &flags))
4408 return NULL;
4409 CHECK_ENV_NOT_CLOSED(self);
4410
4411 MYDB_BEGIN_ALLOW_THREADS;
4412 err = self->db_env->lsn_reset(self->db_env, file, flags);
4413 MYDB_END_ALLOW_THREADS;
4414 RETURN_IF_ERR();
4415 RETURN_NONE();
4416}
4417#endif /* DBVER >= 4.4 */
4418
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004419#if (DBVER >= 40)
4420static PyObject*
4421DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4422{
4423 int err;
4424 DB_LOG_STAT* statp = NULL;
4425 PyObject* d = NULL;
4426 u_int32_t flags = 0;
4427
4428 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4429 return NULL;
4430 CHECK_ENV_NOT_CLOSED(self);
4431
4432 MYDB_BEGIN_ALLOW_THREADS;
4433 err = self->db_env->log_stat(self->db_env, &statp, flags);
4434 MYDB_END_ALLOW_THREADS;
4435 RETURN_IF_ERR();
4436
4437 /* Turn the stat structure into a dictionary */
4438 d = PyDict_New();
4439 if (d == NULL) {
4440 if (statp)
4441 free(statp);
4442 return NULL;
4443 }
4444
4445#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4446
4447 MAKE_ENTRY(magic);
4448 MAKE_ENTRY(version);
4449 MAKE_ENTRY(mode);
4450 MAKE_ENTRY(lg_bsize);
4451#if (DBVER >= 44)
4452 MAKE_ENTRY(lg_size);
4453 MAKE_ENTRY(record);
4454#endif
4455#if (DBVER <= 40)
4456 MAKE_ENTRY(lg_max);
4457#endif
4458 MAKE_ENTRY(w_mbytes);
4459 MAKE_ENTRY(w_bytes);
4460 MAKE_ENTRY(wc_mbytes);
4461 MAKE_ENTRY(wc_bytes);
4462 MAKE_ENTRY(wcount);
4463 MAKE_ENTRY(wcount_fill);
4464#if (DBVER >= 44)
4465 MAKE_ENTRY(rcount);
4466#endif
4467 MAKE_ENTRY(scount);
4468 MAKE_ENTRY(cur_file);
4469 MAKE_ENTRY(cur_offset);
4470 MAKE_ENTRY(disk_file);
4471 MAKE_ENTRY(disk_offset);
4472 MAKE_ENTRY(maxcommitperflush);
4473 MAKE_ENTRY(mincommitperflush);
4474 MAKE_ENTRY(regsize);
4475 MAKE_ENTRY(region_wait);
4476 MAKE_ENTRY(region_nowait);
4477
4478#undef MAKE_ENTRY
4479 free(statp);
4480 return d;
4481} /* DBEnv_log_stat */
4482#endif /* DBVER >= 4.0 for log_stat method */
4483
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004484
4485static PyObject*
4486DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4487{
4488 int err;
4489 DB_LOCK_STAT* sp;
4490 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004491 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492
4493 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4494 return NULL;
4495 CHECK_ENV_NOT_CLOSED(self);
4496
4497 MYDB_BEGIN_ALLOW_THREADS;
4498#if (DBVER >= 40)
4499 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4500#else
4501#if (DBVER >= 33)
4502 err = lock_stat(self->db_env, &sp);
4503#else
4504 err = lock_stat(self->db_env, &sp, NULL);
4505#endif
4506#endif
4507 MYDB_END_ALLOW_THREADS;
4508 RETURN_IF_ERR();
4509
4510 /* Turn the stat structure into a dictionary */
4511 d = PyDict_New();
4512 if (d == NULL) {
4513 free(sp);
4514 return NULL;
4515 }
4516
4517#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4518
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004519#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004520 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004521#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522 MAKE_ENTRY(nmodes);
4523#if (DBVER >= 32)
4524 MAKE_ENTRY(maxlocks);
4525 MAKE_ENTRY(maxlockers);
4526 MAKE_ENTRY(maxobjects);
4527 MAKE_ENTRY(nlocks);
4528 MAKE_ENTRY(maxnlocks);
4529#endif
4530 MAKE_ENTRY(nlockers);
4531 MAKE_ENTRY(maxnlockers);
4532#if (DBVER >= 32)
4533 MAKE_ENTRY(nobjects);
4534 MAKE_ENTRY(maxnobjects);
4535#endif
4536 MAKE_ENTRY(nrequests);
4537 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004538#if (DBVER < 44)
4539 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004541#else
4542 MAKE_ENTRY(lock_nowait);
4543 MAKE_ENTRY(lock_wait);
4544#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(ndeadlocks);
4546 MAKE_ENTRY(regsize);
4547 MAKE_ENTRY(region_wait);
4548 MAKE_ENTRY(region_nowait);
4549
4550#undef MAKE_ENTRY
4551 free(sp);
4552 return d;
4553}
4554
4555
4556static PyObject*
4557DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4558{
4559 int flags=0;
4560 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004561 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 PyObject* list;
4563 PyObject* item = NULL;
4564
4565 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4566 return NULL;
4567
4568 CHECK_ENV_NOT_CLOSED(self);
4569 MYDB_BEGIN_ALLOW_THREADS;
4570#if (DBVER >= 40)
4571 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4572#elif (DBVER == 33)
4573 err = log_archive(self->db_env, &log_list, flags);
4574#else
4575 err = log_archive(self->db_env, &log_list, flags, NULL);
4576#endif
4577 MYDB_END_ALLOW_THREADS;
4578 RETURN_IF_ERR();
4579
Gregory P. Smithbad47452006-06-05 00:33:35 +00004580 list = PyList_New(0);
4581 if (list == NULL) {
4582 if (log_list)
4583 free(log_list);
4584 return NULL;
4585 }
4586
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004588 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4590 item = PyString_FromString (*log_list);
4591 if (item == NULL) {
4592 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593 list = NULL;
4594 break;
4595 }
4596 PyList_Append(list, item);
4597 Py_DECREF(item);
4598 }
4599 free(log_list_start);
4600 }
4601 return list;
4602}
4603
4604
4605static PyObject*
4606DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4607{
4608 int err;
4609 DB_TXN_STAT* sp;
4610 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004611 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612
4613 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4614 return NULL;
4615 CHECK_ENV_NOT_CLOSED(self);
4616
4617 MYDB_BEGIN_ALLOW_THREADS;
4618#if (DBVER >= 40)
4619 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4620#elif (DBVER == 33)
4621 err = txn_stat(self->db_env, &sp);
4622#else
4623 err = txn_stat(self->db_env, &sp, NULL);
4624#endif
4625 MYDB_END_ALLOW_THREADS;
4626 RETURN_IF_ERR();
4627
4628 /* Turn the stat structure into a dictionary */
4629 d = PyDict_New();
4630 if (d == NULL) {
4631 free(sp);
4632 return NULL;
4633 }
4634
4635#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4636
4637 MAKE_ENTRY(time_ckp);
4638 MAKE_ENTRY(last_txnid);
4639 MAKE_ENTRY(maxtxns);
4640 MAKE_ENTRY(nactive);
4641 MAKE_ENTRY(maxnactive);
4642 MAKE_ENTRY(nbegins);
4643 MAKE_ENTRY(naborts);
4644 MAKE_ENTRY(ncommits);
4645 MAKE_ENTRY(regsize);
4646 MAKE_ENTRY(region_wait);
4647 MAKE_ENTRY(region_nowait);
4648
4649#undef MAKE_ENTRY
4650 free(sp);
4651 return d;
4652}
4653
4654
4655static PyObject*
4656DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4657{
4658 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004659 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004660
4661 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4662 return NULL;
4663 CHECK_ENV_NOT_CLOSED(self);
4664
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004665 if (self->moduleFlags.getReturnsNone)
4666 ++oldValue;
4667 if (self->moduleFlags.cursorSetReturnsNone)
4668 ++oldValue;
4669 self->moduleFlags.getReturnsNone = (flags >= 1);
4670 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004671 return PyInt_FromLong(oldValue);
4672}
4673
4674
4675/* --------------------------------------------------------------------- */
4676/* DBTxn methods */
4677
4678
4679static PyObject*
4680DBTxn_commit(DBTxnObject* self, PyObject* args)
4681{
4682 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004683 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684
4685 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4686 return NULL;
4687
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004688 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004689 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4690 "after txn_commit or txn_abort");
4691 PyErr_SetObject(DBError, t);
4692 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004693 return NULL;
4694 }
4695 txn = self->txn;
4696 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004697 MYDB_BEGIN_ALLOW_THREADS;
4698#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004699 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004700#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004701 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702#endif
4703 MYDB_END_ALLOW_THREADS;
4704 RETURN_IF_ERR();
4705 RETURN_NONE();
4706}
4707
4708static PyObject*
4709DBTxn_prepare(DBTxnObject* self, PyObject* args)
4710{
4711#if (DBVER >= 33)
4712 int err;
4713 char* gid=NULL;
4714 int gid_size=0;
4715
4716 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4717 return NULL;
4718
4719 if (gid_size != DB_XIDDATASIZE) {
4720 PyErr_SetString(PyExc_TypeError,
4721 "gid must be DB_XIDDATASIZE bytes long");
4722 return NULL;
4723 }
4724
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004725 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004726 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4727 "after txn_commit or txn_abort");
4728 PyErr_SetObject(DBError, t);
4729 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004730 return NULL;
4731 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004732 MYDB_BEGIN_ALLOW_THREADS;
4733#if (DBVER >= 40)
4734 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4735#else
4736 err = txn_prepare(self->txn, (u_int8_t*)gid);
4737#endif
4738 MYDB_END_ALLOW_THREADS;
4739 RETURN_IF_ERR();
4740 RETURN_NONE();
4741#else
4742 int err;
4743
4744 if (!PyArg_ParseTuple(args, ":prepare"))
4745 return NULL;
4746
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004747 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004748 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4749 "after txn_commit or txn_abort");
4750 PyErr_SetObject(DBError, t);
4751 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004752 return NULL;
4753 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004754 MYDB_BEGIN_ALLOW_THREADS;
4755 err = txn_prepare(self->txn);
4756 MYDB_END_ALLOW_THREADS;
4757 RETURN_IF_ERR();
4758 RETURN_NONE();
4759#endif
4760}
4761
4762
4763static PyObject*
4764DBTxn_abort(DBTxnObject* self, PyObject* args)
4765{
4766 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004767 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004768
4769 if (!PyArg_ParseTuple(args, ":abort"))
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 }
4779 txn = self->txn;
4780 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004781 MYDB_BEGIN_ALLOW_THREADS;
4782#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004783 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004784#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004785 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004786#endif
4787 MYDB_END_ALLOW_THREADS;
4788 RETURN_IF_ERR();
4789 RETURN_NONE();
4790}
4791
4792
4793static PyObject*
4794DBTxn_id(DBTxnObject* self, PyObject* args)
4795{
4796 int id;
4797
4798 if (!PyArg_ParseTuple(args, ":id"))
4799 return NULL;
4800
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004801 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004802 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4803 "after txn_commit or txn_abort");
4804 PyErr_SetObject(DBError, t);
4805 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 return NULL;
4807 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808 MYDB_BEGIN_ALLOW_THREADS;
4809#if (DBVER >= 40)
4810 id = self->txn->id(self->txn);
4811#else
4812 id = txn_id(self->txn);
4813#endif
4814 MYDB_END_ALLOW_THREADS;
4815 return PyInt_FromLong(id);
4816}
4817
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004818#if (DBVER >= 43)
4819/* --------------------------------------------------------------------- */
4820/* DBSequence methods */
4821
4822
4823static PyObject*
4824DBSequence_close(DBSequenceObject* self, PyObject* args)
4825{
4826 int err, flags=0;
4827 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4828 return NULL;
4829 CHECK_SEQUENCE_NOT_CLOSED(self)
4830
4831 MYDB_BEGIN_ALLOW_THREADS
4832 err = self->sequence->close(self->sequence, flags);
4833 self->sequence = NULL;
4834 MYDB_END_ALLOW_THREADS
4835
4836 RETURN_IF_ERR();
4837
4838 RETURN_NONE();
4839}
4840
4841static PyObject*
4842DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4843{
4844 int err, flags = 0;
4845 int delta = 1;
4846 db_seq_t value;
4847 PyObject *txnobj = NULL;
4848 DB_TXN *txn = NULL;
4849 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4850 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4851 return NULL;
4852 CHECK_SEQUENCE_NOT_CLOSED(self)
4853
4854 if (!checkTxnObj(txnobj, &txn))
4855 return NULL;
4856
4857 MYDB_BEGIN_ALLOW_THREADS
4858 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4859 MYDB_END_ALLOW_THREADS
4860
4861 RETURN_IF_ERR();
4862 return PyLong_FromLongLong(value);
4863
4864}
4865
4866static PyObject*
4867DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4868{
4869 if (!PyArg_ParseTuple(args,":get_dbp"))
4870 return NULL;
4871 CHECK_SEQUENCE_NOT_CLOSED(self)
4872 Py_INCREF(self->mydb);
4873 return (PyObject* )self->mydb;
4874}
4875
4876static PyObject*
4877DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4878{
4879 int err;
4880 DBT key;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882 MYDB_BEGIN_ALLOW_THREADS
4883 err = self->sequence->get_key(self->sequence, &key);
4884 MYDB_END_ALLOW_THREADS
4885
4886 RETURN_IF_ERR();
4887
4888 return PyString_FromStringAndSize(key.data, key.size);
4889}
4890
4891static PyObject*
4892DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4893{
4894 int err;
4895 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004896 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004897 return NULL;
4898 CHECK_SEQUENCE_NOT_CLOSED(self)
4899
4900 MYDB_BEGIN_ALLOW_THREADS
4901 err = self->sequence->initial_value(self->sequence, value);
4902 MYDB_END_ALLOW_THREADS
4903
4904 RETURN_IF_ERR();
4905
4906 RETURN_NONE();
4907}
4908
4909static PyObject*
4910DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4911{
4912 int err, flags = 0;
4913 PyObject* keyobj;
4914 PyObject *txnobj = NULL;
4915 DB_TXN *txn = NULL;
4916 DBT key;
4917
4918 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004920 return NULL;
4921
4922 if (!checkTxnObj(txnobj, &txn))
4923 return NULL;
4924
4925 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4926 return NULL;
4927
4928 MYDB_BEGIN_ALLOW_THREADS
4929 err = self->sequence->open(self->sequence, txn, &key, flags);
4930 MYDB_END_ALLOW_THREADS
4931
4932 CLEAR_DBT(key);
4933 RETURN_IF_ERR();
4934
4935 RETURN_NONE();
4936}
4937
4938static PyObject*
4939DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4940{
4941 int err, flags = 0;
4942 PyObject *txnobj = NULL;
4943 DB_TXN *txn = NULL;
4944
4945 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004947 return NULL;
4948
4949 if (!checkTxnObj(txnobj, &txn))
4950 return NULL;
4951
4952 CHECK_SEQUENCE_NOT_CLOSED(self)
4953
4954 MYDB_BEGIN_ALLOW_THREADS
4955 err = self->sequence->remove(self->sequence, txn, flags);
4956 MYDB_END_ALLOW_THREADS
4957
4958 RETURN_IF_ERR();
4959 RETURN_NONE();
4960}
4961
4962static PyObject*
4963DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4964{
4965 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004966 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004967 return NULL;
4968 CHECK_SEQUENCE_NOT_CLOSED(self)
4969
4970 MYDB_BEGIN_ALLOW_THREADS
4971 err = self->sequence->set_cachesize(self->sequence, size);
4972 MYDB_END_ALLOW_THREADS
4973
4974 RETURN_IF_ERR();
4975 RETURN_NONE();
4976}
4977
4978static PyObject*
4979DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4980{
4981 int err, size;
4982 if (!PyArg_ParseTuple(args,":get_cachesize"))
4983 return NULL;
4984 CHECK_SEQUENCE_NOT_CLOSED(self)
4985
4986 MYDB_BEGIN_ALLOW_THREADS
4987 err = self->sequence->get_cachesize(self->sequence, &size);
4988 MYDB_END_ALLOW_THREADS
4989
4990 RETURN_IF_ERR();
4991 return PyInt_FromLong(size);
4992}
4993
4994static PyObject*
4995DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4996{
4997 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004998 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004999 return NULL;
5000 CHECK_SEQUENCE_NOT_CLOSED(self)
5001
5002 MYDB_BEGIN_ALLOW_THREADS
5003 err = self->sequence->set_flags(self->sequence, flags);
5004 MYDB_END_ALLOW_THREADS
5005
5006 RETURN_IF_ERR();
5007 RETURN_NONE();
5008
5009}
5010
5011static PyObject*
5012DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5013{
5014 unsigned int flags;
5015 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005016 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5019
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->get_flags(self->sequence, &flags);
5022 MYDB_END_ALLOW_THREADS
5023
5024 RETURN_IF_ERR();
5025 return PyInt_FromLong((int)flags);
5026}
5027
5028static PyObject*
5029DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5030{
5031 int err;
5032 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005033 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5036
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->set_range(self->sequence, min, max);
5039 MYDB_END_ALLOW_THREADS
5040
5041 RETURN_IF_ERR();
5042 RETURN_NONE();
5043}
5044
5045static PyObject*
5046DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5047{
5048 int err;
5049 db_seq_t min, max;
5050 if (!PyArg_ParseTuple(args,":get_range"))
5051 return NULL;
5052 CHECK_SEQUENCE_NOT_CLOSED(self)
5053
5054 MYDB_BEGIN_ALLOW_THREADS
5055 err = self->sequence->get_range(self->sequence, &min, &max);
5056 MYDB_END_ALLOW_THREADS
5057
5058 RETURN_IF_ERR();
5059 return Py_BuildValue("(LL)", min, max);
5060}
5061
5062static PyObject*
5063DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5064{
5065 int err, flags = 0;
5066 DB_SEQUENCE_STAT* sp = NULL;
5067 PyObject* dict_stat;
5068 static char* kwnames[] = {"flags", NULL };
5069 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5070 return NULL;
5071 CHECK_SEQUENCE_NOT_CLOSED(self);
5072
5073 MYDB_BEGIN_ALLOW_THREADS;
5074 err = self->sequence->stat(self->sequence, &sp, flags);
5075 MYDB_END_ALLOW_THREADS;
5076 RETURN_IF_ERR();
5077
5078 if ((dict_stat = PyDict_New()) == NULL) {
5079 free(sp);
5080 return NULL;
5081 }
5082
5083
5084#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5085#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5086
5087 MAKE_INT_ENTRY(wait);
5088 MAKE_INT_ENTRY(nowait);
5089 MAKE_LONG_LONG_ENTRY(current);
5090 MAKE_LONG_LONG_ENTRY(value);
5091 MAKE_LONG_LONG_ENTRY(last_value);
5092 MAKE_LONG_LONG_ENTRY(min);
5093 MAKE_LONG_LONG_ENTRY(max);
5094 MAKE_INT_ENTRY(cache_size);
5095 MAKE_INT_ENTRY(flags);
5096
5097#undef MAKE_INT_ENTRY
5098#undef MAKE_LONG_LONG_ENTRY
5099
5100 free(sp);
5101 return dict_stat;
5102}
5103#endif
5104
5105
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005106/* --------------------------------------------------------------------- */
5107/* Method definition tables and type objects */
5108
5109static PyMethodDef DB_methods[] = {
5110 {"append", (PyCFunction)DB_append, METH_VARARGS},
5111#if (DBVER >= 33)
5112 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5113#endif
5114 {"close", (PyCFunction)DB_close, METH_VARARGS},
5115#if (DBVER >= 32)
5116 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5117 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5118#endif
5119 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5120 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5121 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5122 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005123#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005124 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5127 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5128 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5129 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5130 {"join", (PyCFunction)DB_join, METH_VARARGS},
5131 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5132 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5133 {"items", (PyCFunction)DB_items, METH_VARARGS},
5134 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5135 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5136 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5137 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5138 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5139 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005140#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005141 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005142#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005143 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005144#if (DBVER >= 41)
5145 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005147 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5148 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5149 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5150 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5151 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5152 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5153 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5154 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5155 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5156#if (DBVER >= 32)
5157 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5158#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005159 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005160 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5161#if (DBVER >= 33)
5162 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5163#endif
5164 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5165 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5166 {"values", (PyCFunction)DB_values, METH_VARARGS},
5167 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5168 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5169 {NULL, NULL} /* sentinel */
5170};
5171
5172
5173static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005174 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005175 (binaryfunc)DB_subscript, /*mp_subscript*/
5176 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5177};
5178
5179
5180static PyMethodDef DBCursor_methods[] = {
5181 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5182 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5183 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5184 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5185 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5186 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5187 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005188#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005189 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005190#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005191 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5192 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5193 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5194 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5195 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5196 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5197 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5198 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005199 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005200 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005201 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5202 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5203 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5204 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5205 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5206 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5207 {NULL, NULL} /* sentinel */
5208};
5209
5210
5211static PyMethodDef DBEnv_methods[] = {
5212 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5213 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5214 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005215#if (DBVER >= 41)
5216 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5217 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5218 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5219#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005220#if (DBVER >= 40)
5221 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5222#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005223 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005224 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5225 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5226#if (DBVER >= 32)
5227 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5228#endif
5229 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5230 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5231 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005232#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005233 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005234#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005235 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5236 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5237#if (DBVER >= 32)
5238 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5239 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5240 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5241#endif
5242 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5243 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5244 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5245 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5246 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5247 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005248 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005249 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5250 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5251 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5252 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5253 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5254 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005255#if (DBVER >= 40)
5256 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5257#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005258#if (DBVER >= 44)
5259 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5260#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005261 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5262 {NULL, NULL} /* sentinel */
5263};
5264
5265
5266static PyMethodDef DBTxn_methods[] = {
5267 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5268 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5269 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5270 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5271 {NULL, NULL} /* sentinel */
5272};
5273
5274
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005275#if (DBVER >= 43)
5276static PyMethodDef DBSequence_methods[] = {
5277 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5278 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5279 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5280 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005281 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5282 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5283 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5284 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5285 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5286 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5287 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5288 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5289 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5290 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5291 {NULL, NULL} /* sentinel */
5292};
5293#endif
5294
5295
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005296static PyObject*
5297DB_getattr(DBObject* self, char *name)
5298{
5299 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5300}
5301
5302
5303static PyObject*
5304DBEnv_getattr(DBEnvObject* self, char *name)
5305{
5306 if (!strcmp(name, "db_home")) {
5307 CHECK_ENV_NOT_CLOSED(self);
5308 if (self->db_env->db_home == NULL) {
5309 RETURN_NONE();
5310 }
5311 return PyString_FromString(self->db_env->db_home);
5312 }
5313
5314 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5315}
5316
5317
5318static PyObject*
5319DBCursor_getattr(DBCursorObject* self, char *name)
5320{
5321 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5322}
5323
5324static PyObject*
5325DBTxn_getattr(DBTxnObject* self, char *name)
5326{
5327 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5328}
5329
5330static PyObject*
5331DBLock_getattr(DBLockObject* self, char *name)
5332{
5333 return NULL;
5334}
5335
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005336#if (DBVER >= 43)
5337static PyObject*
5338DBSequence_getattr(DBSequenceObject* self, char *name)
5339{
5340 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5341}
5342#endif
5343
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005344statichere PyTypeObject DB_Type = {
5345 PyObject_HEAD_INIT(NULL)
5346 0, /*ob_size*/
5347 "DB", /*tp_name*/
5348 sizeof(DBObject), /*tp_basicsize*/
5349 0, /*tp_itemsize*/
5350 /* methods */
5351 (destructor)DB_dealloc, /*tp_dealloc*/
5352 0, /*tp_print*/
5353 (getattrfunc)DB_getattr, /*tp_getattr*/
5354 0, /*tp_setattr*/
5355 0, /*tp_compare*/
5356 0, /*tp_repr*/
5357 0, /*tp_as_number*/
5358 0, /*tp_as_sequence*/
5359 &DB_mapping,/*tp_as_mapping*/
5360 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005361#ifdef HAVE_WEAKREF
5362 0, /* tp_call */
5363 0, /* tp_str */
5364 0, /* tp_getattro */
5365 0, /* tp_setattro */
5366 0, /* tp_as_buffer */
5367 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5368 0, /* tp_doc */
5369 0, /* tp_traverse */
5370 0, /* tp_clear */
5371 0, /* tp_richcompare */
5372 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5373#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005374};
5375
5376
5377statichere PyTypeObject DBCursor_Type = {
5378 PyObject_HEAD_INIT(NULL)
5379 0, /*ob_size*/
5380 "DBCursor", /*tp_name*/
5381 sizeof(DBCursorObject), /*tp_basicsize*/
5382 0, /*tp_itemsize*/
5383 /* methods */
5384 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5385 0, /*tp_print*/
5386 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5387 0, /*tp_setattr*/
5388 0, /*tp_compare*/
5389 0, /*tp_repr*/
5390 0, /*tp_as_number*/
5391 0, /*tp_as_sequence*/
5392 0, /*tp_as_mapping*/
5393 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005394#ifdef HAVE_WEAKREF
5395 0, /* tp_call */
5396 0, /* tp_str */
5397 0, /* tp_getattro */
5398 0, /* tp_setattro */
5399 0, /* tp_as_buffer */
5400 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5401 0, /* tp_doc */
5402 0, /* tp_traverse */
5403 0, /* tp_clear */
5404 0, /* tp_richcompare */
5405 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5406#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005407};
5408
5409
5410statichere PyTypeObject DBEnv_Type = {
5411 PyObject_HEAD_INIT(NULL)
5412 0, /*ob_size*/
5413 "DBEnv", /*tp_name*/
5414 sizeof(DBEnvObject), /*tp_basicsize*/
5415 0, /*tp_itemsize*/
5416 /* methods */
5417 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5418 0, /*tp_print*/
5419 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5420 0, /*tp_setattr*/
5421 0, /*tp_compare*/
5422 0, /*tp_repr*/
5423 0, /*tp_as_number*/
5424 0, /*tp_as_sequence*/
5425 0, /*tp_as_mapping*/
5426 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005427#ifdef HAVE_WEAKREF
5428 0, /* tp_call */
5429 0, /* tp_str */
5430 0, /* tp_getattro */
5431 0, /* tp_setattro */
5432 0, /* tp_as_buffer */
5433 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5434 0, /* tp_doc */
5435 0, /* tp_traverse */
5436 0, /* tp_clear */
5437 0, /* tp_richcompare */
5438 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5439#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005440};
5441
5442statichere PyTypeObject DBTxn_Type = {
5443 PyObject_HEAD_INIT(NULL)
5444 0, /*ob_size*/
5445 "DBTxn", /*tp_name*/
5446 sizeof(DBTxnObject), /*tp_basicsize*/
5447 0, /*tp_itemsize*/
5448 /* methods */
5449 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5450 0, /*tp_print*/
5451 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5452 0, /*tp_setattr*/
5453 0, /*tp_compare*/
5454 0, /*tp_repr*/
5455 0, /*tp_as_number*/
5456 0, /*tp_as_sequence*/
5457 0, /*tp_as_mapping*/
5458 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005459#ifdef HAVE_WEAKREF
5460 0, /* tp_call */
5461 0, /* tp_str */
5462 0, /* tp_getattro */
5463 0, /* tp_setattro */
5464 0, /* tp_as_buffer */
5465 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5466 0, /* tp_doc */
5467 0, /* tp_traverse */
5468 0, /* tp_clear */
5469 0, /* tp_richcompare */
5470 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5471#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005472};
5473
5474
5475statichere PyTypeObject DBLock_Type = {
5476 PyObject_HEAD_INIT(NULL)
5477 0, /*ob_size*/
5478 "DBLock", /*tp_name*/
5479 sizeof(DBLockObject), /*tp_basicsize*/
5480 0, /*tp_itemsize*/
5481 /* methods */
5482 (destructor)DBLock_dealloc, /*tp_dealloc*/
5483 0, /*tp_print*/
5484 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5485 0, /*tp_setattr*/
5486 0, /*tp_compare*/
5487 0, /*tp_repr*/
5488 0, /*tp_as_number*/
5489 0, /*tp_as_sequence*/
5490 0, /*tp_as_mapping*/
5491 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005492#ifdef HAVE_WEAKREF
5493 0, /* tp_call */
5494 0, /* tp_str */
5495 0, /* tp_getattro */
5496 0, /* tp_setattro */
5497 0, /* tp_as_buffer */
5498 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5499 0, /* tp_doc */
5500 0, /* tp_traverse */
5501 0, /* tp_clear */
5502 0, /* tp_richcompare */
5503 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5504#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005505};
5506
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005507#if (DBVER >= 43)
5508statichere PyTypeObject DBSequence_Type = {
5509 PyObject_HEAD_INIT(NULL)
5510 0, /*ob_size*/
5511 "DBSequence", /*tp_name*/
5512 sizeof(DBSequenceObject), /*tp_basicsize*/
5513 0, /*tp_itemsize*/
5514 /* methods */
5515 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5516 0, /*tp_print*/
5517 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5518 0, /*tp_setattr*/
5519 0, /*tp_compare*/
5520 0, /*tp_repr*/
5521 0, /*tp_as_number*/
5522 0, /*tp_as_sequence*/
5523 0, /*tp_as_mapping*/
5524 0, /*tp_hash*/
5525#ifdef HAVE_WEAKREF
5526 0, /* tp_call */
5527 0, /* tp_str */
5528 0, /* tp_getattro */
5529 0, /* tp_setattro */
5530 0, /* tp_as_buffer */
5531 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5532 0, /* tp_doc */
5533 0, /* tp_traverse */
5534 0, /* tp_clear */
5535 0, /* tp_richcompare */
5536 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5537#endif
5538};
5539#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005540
5541/* --------------------------------------------------------------------- */
5542/* Module-level functions */
5543
5544static PyObject*
5545DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5546{
5547 PyObject* dbenvobj = NULL;
5548 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005549 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005550
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005551 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5552 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005553 return NULL;
5554 if (dbenvobj == Py_None)
5555 dbenvobj = NULL;
5556 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5557 makeTypeError("DBEnv", dbenvobj);
5558 return NULL;
5559 }
5560
5561 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5562}
5563
5564
5565static PyObject*
5566DBEnv_construct(PyObject* self, PyObject* args)
5567{
5568 int flags = 0;
5569 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5570 return (PyObject* )newDBEnvObject(flags);
5571}
5572
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005573#if (DBVER >= 43)
5574static PyObject*
5575DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5576{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005577 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005578 int flags = 0;
5579 static char* kwnames[] = { "db", "flags", NULL};
5580
5581 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5582 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005583 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005584 makeTypeError("DB", dbobj);
5585 return NULL;
5586 }
5587 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5588}
5589#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005590
5591static char bsddb_version_doc[] =
5592"Returns a tuple of major, minor, and patch release numbers of the\n\
5593underlying DB library.";
5594
5595static PyObject*
5596bsddb_version(PyObject* self, PyObject* args)
5597{
5598 int major, minor, patch;
5599
5600 if (!PyArg_ParseTuple(args, ":version"))
5601 return NULL;
5602 db_version(&major, &minor, &patch);
5603 return Py_BuildValue("(iii)", major, minor, patch);
5604}
5605
5606
5607/* List of functions defined in the module */
5608
5609static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005610 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5611 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5612#if (DBVER >= 43)
5613 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5614#endif
5615 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005616 {NULL, NULL} /* sentinel */
5617};
5618
5619
5620/* --------------------------------------------------------------------- */
5621/* Module initialization */
5622
5623
5624/* Convenience routine to export an integer value.
5625 * Errors are silently ignored, for better or for worse...
5626 */
5627#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5628
Gregory P. Smith41631e82003-09-21 00:08:14 +00005629#define MODULE_NAME_MAX_LEN 11
5630static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005631
5632DL_EXPORT(void) init_bsddb(void)
5633{
5634 PyObject* m;
5635 PyObject* d;
5636 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5637 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5638 PyObject* cvsid_s = PyString_FromString( rcs_id );
5639
5640 /* Initialize the type of the new type objects here; doing it here
5641 is required for portability to Windows without requiring C++. */
5642 DB_Type.ob_type = &PyType_Type;
5643 DBCursor_Type.ob_type = &PyType_Type;
5644 DBEnv_Type.ob_type = &PyType_Type;
5645 DBTxn_Type.ob_type = &PyType_Type;
5646 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005647#if (DBVER >= 43)
5648 DBSequence_Type.ob_type = &PyType_Type;
5649#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005650
5651
Mark Hammonda69d4092003-04-22 23:13:27 +00005652#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005654 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005655#endif
5656
5657 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005658 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005659 if (m == NULL)
5660 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005661
5662 /* Add some symbolic constants to the module */
5663 d = PyModule_GetDict(m);
5664 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5665 PyDict_SetItemString(d, "cvsid", cvsid_s);
5666 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5667 Py_DECREF(pybsddb_version_s);
5668 pybsddb_version_s = NULL;
5669 Py_DECREF(cvsid_s);
5670 cvsid_s = NULL;
5671 Py_DECREF(db_version_s);
5672 db_version_s = NULL;
5673
5674 ADD_INT(d, DB_VERSION_MAJOR);
5675 ADD_INT(d, DB_VERSION_MINOR);
5676 ADD_INT(d, DB_VERSION_PATCH);
5677
5678 ADD_INT(d, DB_MAX_PAGES);
5679 ADD_INT(d, DB_MAX_RECORDS);
5680
Gregory P. Smith41631e82003-09-21 00:08:14 +00005681#if (DBVER >= 42)
5682 ADD_INT(d, DB_RPCCLIENT);
5683#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005685 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5686 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5687#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005688 ADD_INT(d, DB_XA_CREATE);
5689
5690 ADD_INT(d, DB_CREATE);
5691 ADD_INT(d, DB_NOMMAP);
5692 ADD_INT(d, DB_THREAD);
5693
5694 ADD_INT(d, DB_FORCE);
5695 ADD_INT(d, DB_INIT_CDB);
5696 ADD_INT(d, DB_INIT_LOCK);
5697 ADD_INT(d, DB_INIT_LOG);
5698 ADD_INT(d, DB_INIT_MPOOL);
5699 ADD_INT(d, DB_INIT_TXN);
5700#if (DBVER >= 32)
5701 ADD_INT(d, DB_JOINENV);
5702#endif
5703
5704 ADD_INT(d, DB_RECOVER);
5705 ADD_INT(d, DB_RECOVER_FATAL);
5706 ADD_INT(d, DB_TXN_NOSYNC);
5707 ADD_INT(d, DB_USE_ENVIRON);
5708 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5709
5710 ADD_INT(d, DB_LOCKDOWN);
5711 ADD_INT(d, DB_PRIVATE);
5712 ADD_INT(d, DB_SYSTEM_MEM);
5713
5714 ADD_INT(d, DB_TXN_SYNC);
5715 ADD_INT(d, DB_TXN_NOWAIT);
5716
5717 ADD_INT(d, DB_EXCL);
5718 ADD_INT(d, DB_FCNTL_LOCKING);
5719 ADD_INT(d, DB_ODDFILESIZE);
5720 ADD_INT(d, DB_RDWRMASTER);
5721 ADD_INT(d, DB_RDONLY);
5722 ADD_INT(d, DB_TRUNCATE);
5723#if (DBVER >= 32)
5724 ADD_INT(d, DB_EXTENT);
5725 ADD_INT(d, DB_CDB_ALLDB);
5726 ADD_INT(d, DB_VERIFY);
5727#endif
5728 ADD_INT(d, DB_UPGRADE);
5729
5730 ADD_INT(d, DB_AGGRESSIVE);
5731 ADD_INT(d, DB_NOORDERCHK);
5732 ADD_INT(d, DB_ORDERCHKONLY);
5733 ADD_INT(d, DB_PR_PAGE);
5734#if ! (DBVER >= 33)
5735 ADD_INT(d, DB_VRFY_FLAGMASK);
5736 ADD_INT(d, DB_PR_HEADERS);
5737#endif
5738 ADD_INT(d, DB_PR_RECOVERYTEST);
5739 ADD_INT(d, DB_SALVAGE);
5740
5741 ADD_INT(d, DB_LOCK_NORUN);
5742 ADD_INT(d, DB_LOCK_DEFAULT);
5743 ADD_INT(d, DB_LOCK_OLDEST);
5744 ADD_INT(d, DB_LOCK_RANDOM);
5745 ADD_INT(d, DB_LOCK_YOUNGEST);
5746#if (DBVER >= 33)
5747 ADD_INT(d, DB_LOCK_MAXLOCKS);
5748 ADD_INT(d, DB_LOCK_MINLOCKS);
5749 ADD_INT(d, DB_LOCK_MINWRITE);
5750#endif
5751
5752
5753#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005754 /* docs say to use zero instead */
5755 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005756#else
5757 ADD_INT(d, DB_LOCK_CONFLICT);
5758#endif
5759
5760 ADD_INT(d, DB_LOCK_DUMP);
5761 ADD_INT(d, DB_LOCK_GET);
5762 ADD_INT(d, DB_LOCK_INHERIT);
5763 ADD_INT(d, DB_LOCK_PUT);
5764 ADD_INT(d, DB_LOCK_PUT_ALL);
5765 ADD_INT(d, DB_LOCK_PUT_OBJ);
5766
5767 ADD_INT(d, DB_LOCK_NG);
5768 ADD_INT(d, DB_LOCK_READ);
5769 ADD_INT(d, DB_LOCK_WRITE);
5770 ADD_INT(d, DB_LOCK_NOWAIT);
5771#if (DBVER >= 32)
5772 ADD_INT(d, DB_LOCK_WAIT);
5773#endif
5774 ADD_INT(d, DB_LOCK_IWRITE);
5775 ADD_INT(d, DB_LOCK_IREAD);
5776 ADD_INT(d, DB_LOCK_IWR);
5777#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005778#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005779 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005780#else
5781 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5782#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005783 ADD_INT(d, DB_LOCK_WWRITE);
5784#endif
5785
5786 ADD_INT(d, DB_LOCK_RECORD);
5787 ADD_INT(d, DB_LOCK_UPGRADE);
5788#if (DBVER >= 32)
5789 ADD_INT(d, DB_LOCK_SWITCH);
5790#endif
5791#if (DBVER >= 33)
5792 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5793#endif
5794
5795 ADD_INT(d, DB_LOCK_NOWAIT);
5796 ADD_INT(d, DB_LOCK_RECORD);
5797 ADD_INT(d, DB_LOCK_UPGRADE);
5798
5799#if (DBVER >= 33)
5800 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005801#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005803#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005804 ADD_INT(d, DB_LSTAT_FREE);
5805 ADD_INT(d, DB_LSTAT_HELD);
5806#if (DBVER == 33)
5807 ADD_INT(d, DB_LSTAT_NOGRANT);
5808#endif
5809 ADD_INT(d, DB_LSTAT_PENDING);
5810 ADD_INT(d, DB_LSTAT_WAITING);
5811#endif
5812
5813 ADD_INT(d, DB_ARCH_ABS);
5814 ADD_INT(d, DB_ARCH_DATA);
5815 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005816#if (DBVER >= 42)
5817 ADD_INT(d, DB_ARCH_REMOVE);
5818#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005819
5820 ADD_INT(d, DB_BTREE);
5821 ADD_INT(d, DB_HASH);
5822 ADD_INT(d, DB_RECNO);
5823 ADD_INT(d, DB_QUEUE);
5824 ADD_INT(d, DB_UNKNOWN);
5825
5826 ADD_INT(d, DB_DUP);
5827 ADD_INT(d, DB_DUPSORT);
5828 ADD_INT(d, DB_RECNUM);
5829 ADD_INT(d, DB_RENUMBER);
5830 ADD_INT(d, DB_REVSPLITOFF);
5831 ADD_INT(d, DB_SNAPSHOT);
5832
5833 ADD_INT(d, DB_JOIN_NOSORT);
5834
5835 ADD_INT(d, DB_AFTER);
5836 ADD_INT(d, DB_APPEND);
5837 ADD_INT(d, DB_BEFORE);
5838 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005839#if (DBVER >= 41)
5840 _addIntToDict(d, "DB_CHECKPOINT", 0);
5841#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005842 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005843 ADD_INT(d, DB_CURLSN);
5844#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005845#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846 ADD_INT(d, DB_COMMIT);
5847#endif
5848 ADD_INT(d, DB_CONSUME);
5849#if (DBVER >= 32)
5850 ADD_INT(d, DB_CONSUME_WAIT);
5851#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005852 ADD_INT(d, DB_CURRENT);
5853#if (DBVER >= 33)
5854 ADD_INT(d, DB_FAST_STAT);
5855#endif
5856 ADD_INT(d, DB_FIRST);
5857 ADD_INT(d, DB_FLUSH);
5858 ADD_INT(d, DB_GET_BOTH);
5859 ADD_INT(d, DB_GET_RECNO);
5860 ADD_INT(d, DB_JOIN_ITEM);
5861 ADD_INT(d, DB_KEYFIRST);
5862 ADD_INT(d, DB_KEYLAST);
5863 ADD_INT(d, DB_LAST);
5864 ADD_INT(d, DB_NEXT);
5865 ADD_INT(d, DB_NEXT_DUP);
5866 ADD_INT(d, DB_NEXT_NODUP);
5867 ADD_INT(d, DB_NODUPDATA);
5868 ADD_INT(d, DB_NOOVERWRITE);
5869 ADD_INT(d, DB_NOSYNC);
5870 ADD_INT(d, DB_POSITION);
5871 ADD_INT(d, DB_PREV);
5872 ADD_INT(d, DB_PREV_NODUP);
5873 ADD_INT(d, DB_RECORDCOUNT);
5874 ADD_INT(d, DB_SET);
5875 ADD_INT(d, DB_SET_RANGE);
5876 ADD_INT(d, DB_SET_RECNO);
5877 ADD_INT(d, DB_WRITECURSOR);
5878
5879 ADD_INT(d, DB_OPFLAGS_MASK);
5880 ADD_INT(d, DB_RMW);
5881#if (DBVER >= 33)
5882 ADD_INT(d, DB_DIRTY_READ);
5883 ADD_INT(d, DB_MULTIPLE);
5884 ADD_INT(d, DB_MULTIPLE_KEY);
5885#endif
5886
Gregory P. Smith29602d22006-01-24 09:46:48 +00005887#if (DBVER >= 44)
5888 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5889 ADD_INT(d, DB_READ_COMMITTED);
5890#endif
5891
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005892#if (DBVER >= 33)
5893 ADD_INT(d, DB_DONOTINDEX);
5894#endif
5895
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005896#if (DBVER >= 41)
5897 _addIntToDict(d, "DB_INCOMPLETE", 0);
5898#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005900#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005901 ADD_INT(d, DB_KEYEMPTY);
5902 ADD_INT(d, DB_KEYEXIST);
5903 ADD_INT(d, DB_LOCK_DEADLOCK);
5904 ADD_INT(d, DB_LOCK_NOTGRANTED);
5905 ADD_INT(d, DB_NOSERVER);
5906 ADD_INT(d, DB_NOSERVER_HOME);
5907 ADD_INT(d, DB_NOSERVER_ID);
5908 ADD_INT(d, DB_NOTFOUND);
5909 ADD_INT(d, DB_OLD_VERSION);
5910 ADD_INT(d, DB_RUNRECOVERY);
5911 ADD_INT(d, DB_VERIFY_BAD);
5912#if (DBVER >= 33)
5913 ADD_INT(d, DB_PAGE_NOTFOUND);
5914 ADD_INT(d, DB_SECONDARY_BAD);
5915#endif
5916#if (DBVER >= 40)
5917 ADD_INT(d, DB_STAT_CLEAR);
5918 ADD_INT(d, DB_REGION_INIT);
5919 ADD_INT(d, DB_NOLOCKING);
5920 ADD_INT(d, DB_YIELDCPU);
5921 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5922 ADD_INT(d, DB_NOPANIC);
5923#endif
5924
Gregory P. Smith41631e82003-09-21 00:08:14 +00005925#if (DBVER >= 42)
5926 ADD_INT(d, DB_TIME_NOTGRANTED);
5927 ADD_INT(d, DB_TXN_NOT_DURABLE);
5928 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5929 ADD_INT(d, DB_LOG_AUTOREMOVE);
5930 ADD_INT(d, DB_DIRECT_LOG);
5931 ADD_INT(d, DB_DIRECT_DB);
5932 ADD_INT(d, DB_INIT_REP);
5933 ADD_INT(d, DB_ENCRYPT);
5934 ADD_INT(d, DB_CHKSUM);
5935#endif
5936
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005937#if (DBVER >= 43)
5938 ADD_INT(d, DB_LOG_INMEMORY);
5939 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005940 ADD_INT(d, DB_SEQ_DEC);
5941 ADD_INT(d, DB_SEQ_INC);
5942 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005943#endif
5944
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005945#if (DBVER >= 41)
5946 ADD_INT(d, DB_ENCRYPT_AES);
5947 ADD_INT(d, DB_AUTO_COMMIT);
5948#else
5949 /* allow berkeleydb 4.1 aware apps to run on older versions */
5950 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5951#endif
5952
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005953 ADD_INT(d, EINVAL);
5954 ADD_INT(d, EACCES);
5955 ADD_INT(d, ENOSPC);
5956 ADD_INT(d, ENOMEM);
5957 ADD_INT(d, EAGAIN);
5958 ADD_INT(d, EBUSY);
5959 ADD_INT(d, EEXIST);
5960 ADD_INT(d, ENOENT);
5961 ADD_INT(d, EPERM);
5962
Barry Warsaw1baa9822003-03-31 19:51:29 +00005963#if (DBVER >= 40)
5964 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5965 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5966#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005967
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005968 /* The exception name must be correct for pickled exception *
5969 * objects to unpickle properly. */
5970#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5971#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5972#else
5973#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5974#endif
5975
5976 /* All the rest of the exceptions derive only from DBError */
5977#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5978 PyDict_SetItemString(d, #name, name)
5979
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005980 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005981 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5982 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005983
Gregory P. Smithe9477062005-06-04 06:46:59 +00005984 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5985 * from both DBError and KeyError, since the API only supports
5986 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005987 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005988 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5989 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005990 Py_file_input, d, d);
5991 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005992 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005993 PyDict_DelItemString(d, "KeyError");
5994
5995
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005996#if !INCOMPLETE_IS_WARNING
5997 MAKE_EX(DBIncompleteError);
5998#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005999 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000 MAKE_EX(DBKeyEmptyError);
6001 MAKE_EX(DBKeyExistError);
6002 MAKE_EX(DBLockDeadlockError);
6003 MAKE_EX(DBLockNotGrantedError);
6004 MAKE_EX(DBOldVersionError);
6005 MAKE_EX(DBRunRecoveryError);
6006 MAKE_EX(DBVerifyBadError);
6007 MAKE_EX(DBNoServerError);
6008 MAKE_EX(DBNoServerHomeError);
6009 MAKE_EX(DBNoServerIDError);
6010#if (DBVER >= 33)
6011 MAKE_EX(DBPageNotFoundError);
6012 MAKE_EX(DBSecondaryBadError);
6013#endif
6014
6015 MAKE_EX(DBInvalidArgError);
6016 MAKE_EX(DBAccessError);
6017 MAKE_EX(DBNoSpaceError);
6018 MAKE_EX(DBNoMemoryError);
6019 MAKE_EX(DBAgainError);
6020 MAKE_EX(DBBusyError);
6021 MAKE_EX(DBFileExistsError);
6022 MAKE_EX(DBNoSuchFileError);
6023 MAKE_EX(DBPermissionsError);
6024
6025#undef MAKE_EX
6026
6027 /* Check for errors */
6028 if (PyErr_Occurred()) {
6029 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006030 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006031 }
6032}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006033
6034/* allow this module to be named _pybsddb so that it can be installed
6035 * and imported on top of python >= 2.3 that includes its own older
6036 * copy of the library named _bsddb without importing the old version. */
6037DL_EXPORT(void) init_pybsddb(void)
6038{
6039 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6040 init_bsddb();
6041}