blob: 2a3ac5c9483b5c912c8011c299b74d924fec4e47 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000101#define PY_BSDDB_VERSION "4.4.5"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000106typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298static PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
Neal Norwitz227b5332006-03-22 09:28:35 +0000301static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000548#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000559#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000603 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
Gregory P. Smithe9477062005-06-04 06:46:59 +0000706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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);
Thomas Wouters0e3f5912006-08-11 14:57:12 +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)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000811 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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
Thomas Wouters4d70c3d2006-06-08 14:42:34 +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
1800
1801 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1802 return NULL;
1803
1804 CHECK_DB_NOT_CLOSED(self);
1805
1806 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001807 PyErr_SetString(PyExc_TypeError,
1808 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001809 return NULL;
1810 }
1811
1812 length = PyObject_Length(cursorsObj);
1813 cursors = malloc((length+1) * sizeof(DBC*));
1814 cursors[length] = NULL;
1815 for (x=0; x<length; x++) {
1816 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001817 if (item == NULL) {
1818 free(cursors);
1819 return NULL;
1820 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001822 PyErr_SetString(PyExc_TypeError,
1823 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001824 free(cursors);
1825 return NULL;
1826 }
1827 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001828 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 }
1830
1831 MYDB_BEGIN_ALLOW_THREADS;
1832 err = self->db->join(self->db, cursors, &dbc, flags);
1833 MYDB_END_ALLOW_THREADS;
1834 free(cursors);
1835 RETURN_IF_ERR();
1836
Gregory P. Smith7441e652003-11-03 21:35:31 +00001837 /* FIXME: this is a buggy interface. The returned cursor
1838 contains internal references to the passed in cursors
1839 but does not hold python references to them or prevent
1840 them from being closed prematurely. This can cause
1841 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 return (PyObject*) newDBCursorObject(dbc, self);
1843}
1844
1845
1846static PyObject*
1847DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1848{
1849 int err, flags=0;
1850 PyObject* txnobj = NULL;
1851 PyObject* keyobj;
1852 DBT key;
1853 DB_TXN *txn = NULL;
1854 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001855 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856
1857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1858 &keyobj, &txnobj, &flags))
1859 return NULL;
1860 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001861 if (!make_dbt(keyobj, &key))
1862 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863 return NULL;
1864 if (!checkTxnObj(txnobj, &txn))
1865 return NULL;
1866
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->key_range(self->db, txn, &key, &range, flags);
1869 MYDB_END_ALLOW_THREADS;
1870
1871 RETURN_IF_ERR();
1872 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1873}
1874
1875
1876static PyObject*
1877DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1878{
1879 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1880 char* filename = NULL;
1881 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001882#if (DBVER >= 41)
1883 PyObject *txnobj = NULL;
1884 DB_TXN *txn = NULL;
1885 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001886 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001887 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1888 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001889 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001890 "filename", "dbtype", "flags", "mode", "txn", NULL};
1891#else
1892 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001893 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001894 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1895 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001896 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001897 "filename", "dbtype", "flags", "mode", NULL};
1898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001899
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001900#if (DBVER >= 41)
1901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1902 &filename, &dbname, &type, &flags, &mode,
1903 &txnobj))
1904#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001906 &filename, &dbname, &type, &flags,
1907 &mode))
1908#endif
1909 {
1910 PyErr_Clear();
1911 type = DB_UNKNOWN; flags = 0; mode = 0660;
1912 filename = NULL; dbname = NULL;
1913#if (DBVER >= 41)
1914 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1915 kwnames_basic,
1916 &filename, &type, &flags, &mode,
1917 &txnobj))
1918 return NULL;
1919#else
1920 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1921 kwnames_basic,
1922 &filename, &type, &flags, &mode))
1923 return NULL;
1924#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001925 }
1926
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001927#if (DBVER >= 41)
1928 if (!checkTxnObj(txnobj, &txn)) return NULL;
1929#endif
1930
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001931 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001932 PyObject *t = Py_BuildValue("(is)", 0,
1933 "Cannot call open() twice for DB object");
1934 PyErr_SetObject(DBError, t);
1935 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936 return NULL;
1937 }
1938
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001939#if 0 && (DBVER >= 41)
1940 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1941 && (self->myenvobj->flags & DB_INIT_TXN))
1942 {
1943 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1944 * explicitly passed) but we are in a transaction ready environment:
1945 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1946 * to work on BerkeleyDB 4.1 without needing to modify their
1947 * DBEnv or DB open calls.
1948 * TODO make this behaviour of the library configurable.
1949 */
1950 flags |= DB_AUTO_COMMIT;
1951 }
1952#endif
1953
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001955#if (DBVER >= 41)
1956 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1957#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 MYDB_END_ALLOW_THREADS;
1961 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001962 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001963 self->db = NULL;
1964 return NULL;
1965 }
1966
1967 self->flags = flags;
1968 RETURN_NONE();
1969}
1970
1971
1972static PyObject*
1973DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1974{
1975 int flags=0;
1976 PyObject* txnobj = NULL;
1977 int dlen = -1;
1978 int doff = -1;
1979 PyObject* keyobj, *dataobj, *retval;
1980 DBT key, data;
1981 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001982 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001983 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984
1985 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1986 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1987 return NULL;
1988
1989 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001990 if (!make_key_dbt(self, keyobj, &key, NULL))
1991 return NULL;
1992 if ( !make_dbt(dataobj, &data) ||
1993 !add_partial_dbt(&data, dlen, doff) ||
1994 !checkTxnObj(txnobj, &txn) )
1995 {
1996 FREE_DBT(key);
1997 return NULL;
1998 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999
2000 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2001 FREE_DBT(key);
2002 return NULL;
2003 }
2004
2005 if (flags & DB_APPEND)
2006 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2007 else {
2008 retval = Py_None;
2009 Py_INCREF(retval);
2010 }
2011 FREE_DBT(key);
2012 return retval;
2013}
2014
2015
2016
2017static PyObject*
2018DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2019{
2020 char* filename;
2021 char* database = NULL;
2022 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002023 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002024
2025 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2026 &filename, &database, &flags))
2027 return NULL;
2028 CHECK_DB_NOT_CLOSED(self);
2029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002030 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002031 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002032 RETURN_IF_ERR();
2033 RETURN_NONE();
2034}
2035
2036
2037
2038static PyObject*
2039DB_rename(DBObject* self, PyObject* args)
2040{
2041 char* filename;
2042 char* database;
2043 char* newname;
2044 int err, flags=0;
2045
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002046 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2047 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002048 return NULL;
2049 CHECK_DB_NOT_CLOSED(self);
2050
2051 MYDB_BEGIN_ALLOW_THREADS;
2052 err = self->db->rename(self->db, filename, database, newname, flags);
2053 MYDB_END_ALLOW_THREADS;
2054 RETURN_IF_ERR();
2055 RETURN_NONE();
2056}
2057
2058
2059static PyObject*
2060DB_set_bt_minkey(DBObject* self, PyObject* args)
2061{
2062 int err, minkey;
2063
2064 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2065 return NULL;
2066 CHECK_DB_NOT_CLOSED(self);
2067
2068 MYDB_BEGIN_ALLOW_THREADS;
2069 err = self->db->set_bt_minkey(self->db, minkey);
2070 MYDB_END_ALLOW_THREADS;
2071 RETURN_IF_ERR();
2072 RETURN_NONE();
2073}
2074
Neal Norwitz84562352005-10-20 04:30:15 +00002075#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002076static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002077_default_cmp(const DBT *leftKey,
2078 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002079{
2080 int res;
2081 int lsize = leftKey->size, rsize = rightKey->size;
2082
Georg Brandlef1701f2006-03-07 14:57:48 +00002083 res = memcmp(leftKey->data, rightKey->data,
2084 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002085
2086 if (res == 0) {
2087 if (lsize < rsize) {
2088 res = -1;
2089 }
2090 else if (lsize > rsize) {
2091 res = 1;
2092 }
2093 }
2094 return res;
2095}
2096
2097static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002098_db_compareCallback(DB* db,
2099 const DBT *leftKey,
2100 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002101{
2102 int res = 0;
2103 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002104 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002105 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002106
2107 if (self == NULL || self->btCompareCallback == NULL) {
2108 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002109 PyErr_SetString(PyExc_TypeError,
2110 (self == 0
2111 ? "DB_bt_compare db is NULL."
2112 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002113 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002114 PyErr_Print();
2115 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002116 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002117 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002118 MYDB_BEGIN_BLOCK_THREADS;
2119
Thomas Woutersb3153832006-03-08 01:47:19 +00002120 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2121 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002122 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002123 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002126 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002128 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 PyErr_Print();
2130 res = _default_cmp(leftKey, rightKey);
2131 } else if (PyInt_Check(result)) {
2132 res = PyInt_AsLong(result);
2133 } else {
2134 PyErr_SetString(PyExc_TypeError,
2135 "DB_bt_compare callback MUST return an int.");
2136 /* we're in a callback within the DB code, we can't raise */
2137 PyErr_Print();
2138 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002139 }
2140
Thomas Woutersb3153832006-03-08 01:47:19 +00002141 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002142 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002143
2144 MYDB_END_BLOCK_THREADS;
2145 }
2146 return res;
2147}
2148
2149static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002150DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002151{
2152 int err;
2153 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002154 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155
Georg Brandlef1701f2006-03-07 14:57:48 +00002156 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002157 return NULL;
2158
Georg Brandlef1701f2006-03-07 14:57:48 +00002159 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160
Georg Brandlef1701f2006-03-07 14:57:48 +00002161 if (!PyCallable_Check(comparator)) {
2162 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163 return NULL;
2164 }
2165
2166 /*
2167 * Perform a test call of the comparator function with two empty
2168 * string objects here. verify that it returns an int (0).
2169 * err if not.
2170 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002171 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002172 result = PyEval_CallObject(comparator, tuple);
2173 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002174 if (result == NULL)
2175 return NULL;
2176 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002177 PyErr_SetString(PyExc_TypeError,
2178 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002179 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 } else if (PyInt_AsLong(result) != 0) {
2181 PyErr_SetString(PyExc_TypeError,
2182 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183 return NULL;
2184 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002185 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002186
2187 /* We don't accept multiple set_bt_compare operations, in order to
2188 * simplify the code. This would have no real use, as one cannot
2189 * change the function once the db is opened anyway */
2190 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002191 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002192 return NULL;
2193 }
2194
Georg Brandlef1701f2006-03-07 14:57:48 +00002195 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002196 self->btCompareCallback = comparator;
2197
2198 /* This is to workaround a problem with un-initialized threads (see
2199 comment in DB_associate) */
2200#ifdef WITH_THREAD
2201 PyEval_InitThreads();
2202#endif
2203
Thomas Woutersb3153832006-03-08 01:47:19 +00002204 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002205
2206 if (err) {
2207 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002208 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002209 self->btCompareCallback = NULL;
2210 }
2211
Georg Brandlef1701f2006-03-07 14:57:48 +00002212 RETURN_IF_ERR();
2213 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002214}
Neal Norwitz84562352005-10-20 04:30:15 +00002215#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002217
2218static PyObject*
2219DB_set_cachesize(DBObject* self, PyObject* args)
2220{
2221 int err;
2222 int gbytes = 0, bytes = 0, ncache = 0;
2223
2224 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2225 &gbytes,&bytes,&ncache))
2226 return NULL;
2227 CHECK_DB_NOT_CLOSED(self);
2228
2229 MYDB_BEGIN_ALLOW_THREADS;
2230 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2231 MYDB_END_ALLOW_THREADS;
2232 RETURN_IF_ERR();
2233 RETURN_NONE();
2234}
2235
2236
2237static PyObject*
2238DB_set_flags(DBObject* self, PyObject* args)
2239{
2240 int err, flags;
2241
2242 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2243 return NULL;
2244 CHECK_DB_NOT_CLOSED(self);
2245
2246 MYDB_BEGIN_ALLOW_THREADS;
2247 err = self->db->set_flags(self->db, flags);
2248 MYDB_END_ALLOW_THREADS;
2249 RETURN_IF_ERR();
2250
2251 self->setflags |= flags;
2252 RETURN_NONE();
2253}
2254
2255
2256static PyObject*
2257DB_set_h_ffactor(DBObject* self, PyObject* args)
2258{
2259 int err, ffactor;
2260
2261 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2262 return NULL;
2263 CHECK_DB_NOT_CLOSED(self);
2264
2265 MYDB_BEGIN_ALLOW_THREADS;
2266 err = self->db->set_h_ffactor(self->db, ffactor);
2267 MYDB_END_ALLOW_THREADS;
2268 RETURN_IF_ERR();
2269 RETURN_NONE();
2270}
2271
2272
2273static PyObject*
2274DB_set_h_nelem(DBObject* self, PyObject* args)
2275{
2276 int err, nelem;
2277
2278 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2279 return NULL;
2280 CHECK_DB_NOT_CLOSED(self);
2281
2282 MYDB_BEGIN_ALLOW_THREADS;
2283 err = self->db->set_h_nelem(self->db, nelem);
2284 MYDB_END_ALLOW_THREADS;
2285 RETURN_IF_ERR();
2286 RETURN_NONE();
2287}
2288
2289
2290static PyObject*
2291DB_set_lorder(DBObject* self, PyObject* args)
2292{
2293 int err, lorder;
2294
2295 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2296 return NULL;
2297 CHECK_DB_NOT_CLOSED(self);
2298
2299 MYDB_BEGIN_ALLOW_THREADS;
2300 err = self->db->set_lorder(self->db, lorder);
2301 MYDB_END_ALLOW_THREADS;
2302 RETURN_IF_ERR();
2303 RETURN_NONE();
2304}
2305
2306
2307static PyObject*
2308DB_set_pagesize(DBObject* self, PyObject* args)
2309{
2310 int err, pagesize;
2311
2312 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2313 return NULL;
2314 CHECK_DB_NOT_CLOSED(self);
2315
2316 MYDB_BEGIN_ALLOW_THREADS;
2317 err = self->db->set_pagesize(self->db, pagesize);
2318 MYDB_END_ALLOW_THREADS;
2319 RETURN_IF_ERR();
2320 RETURN_NONE();
2321}
2322
2323
2324static PyObject*
2325DB_set_re_delim(DBObject* self, PyObject* args)
2326{
2327 int err;
2328 char delim;
2329
2330 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2331 PyErr_Clear();
2332 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2333 return NULL;
2334 }
2335
2336 CHECK_DB_NOT_CLOSED(self);
2337
2338 MYDB_BEGIN_ALLOW_THREADS;
2339 err = self->db->set_re_delim(self->db, delim);
2340 MYDB_END_ALLOW_THREADS;
2341 RETURN_IF_ERR();
2342 RETURN_NONE();
2343}
2344
2345static PyObject*
2346DB_set_re_len(DBObject* self, PyObject* args)
2347{
2348 int err, len;
2349
2350 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2351 return NULL;
2352 CHECK_DB_NOT_CLOSED(self);
2353
2354 MYDB_BEGIN_ALLOW_THREADS;
2355 err = self->db->set_re_len(self->db, len);
2356 MYDB_END_ALLOW_THREADS;
2357 RETURN_IF_ERR();
2358 RETURN_NONE();
2359}
2360
2361
2362static PyObject*
2363DB_set_re_pad(DBObject* self, PyObject* args)
2364{
2365 int err;
2366 char pad;
2367
2368 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2369 PyErr_Clear();
2370 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2371 return NULL;
2372 }
2373 CHECK_DB_NOT_CLOSED(self);
2374
2375 MYDB_BEGIN_ALLOW_THREADS;
2376 err = self->db->set_re_pad(self->db, pad);
2377 MYDB_END_ALLOW_THREADS;
2378 RETURN_IF_ERR();
2379 RETURN_NONE();
2380}
2381
2382
2383static PyObject*
2384DB_set_re_source(DBObject* self, PyObject* args)
2385{
2386 int err;
2387 char *re_source;
2388
2389 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2390 return NULL;
2391 CHECK_DB_NOT_CLOSED(self);
2392
2393 MYDB_BEGIN_ALLOW_THREADS;
2394 err = self->db->set_re_source(self->db, re_source);
2395 MYDB_END_ALLOW_THREADS;
2396 RETURN_IF_ERR();
2397 RETURN_NONE();
2398}
2399
2400
2401#if (DBVER >= 32)
2402static PyObject*
2403DB_set_q_extentsize(DBObject* self, PyObject* args)
2404{
2405 int err;
2406 int extentsize;
2407
2408 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2409 return NULL;
2410 CHECK_DB_NOT_CLOSED(self);
2411
2412 MYDB_BEGIN_ALLOW_THREADS;
2413 err = self->db->set_q_extentsize(self->db, extentsize);
2414 MYDB_END_ALLOW_THREADS;
2415 RETURN_IF_ERR();
2416 RETURN_NONE();
2417}
2418#endif
2419
2420static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002421DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002422{
2423 int err, flags = 0, type;
2424 void* sp;
2425 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002426#if (DBVER >= 43)
2427 PyObject* txnobj = NULL;
2428 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002429 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002431 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002432#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002433
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434#if (DBVER >= 43)
2435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2436 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002437 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438 if (!checkTxnObj(txnobj, &txn))
2439 return NULL;
2440#else
2441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2442 return NULL;
2443#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 CHECK_DB_NOT_CLOSED(self);
2445
2446 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002447#if (DBVER >= 43)
2448 err = self->db->stat(self->db, txn, &sp, flags);
2449#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002450 err = self->db->stat(self->db, &sp, flags);
2451#else
2452 err = self->db->stat(self->db, &sp, NULL, flags);
2453#endif
2454 MYDB_END_ALLOW_THREADS;
2455 RETURN_IF_ERR();
2456
2457 self->haveStat = 1;
2458
2459 /* Turn the stat structure into a dictionary */
2460 type = _DB_get_type(self);
2461 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2462 free(sp);
2463 return NULL;
2464 }
2465
2466#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2467#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2468#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2469
2470 switch (type) {
2471 case DB_HASH:
2472 MAKE_HASH_ENTRY(magic);
2473 MAKE_HASH_ENTRY(version);
2474 MAKE_HASH_ENTRY(nkeys);
2475 MAKE_HASH_ENTRY(ndata);
2476 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002477#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002478 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002479#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002480 MAKE_HASH_ENTRY(ffactor);
2481 MAKE_HASH_ENTRY(buckets);
2482 MAKE_HASH_ENTRY(free);
2483 MAKE_HASH_ENTRY(bfree);
2484 MAKE_HASH_ENTRY(bigpages);
2485 MAKE_HASH_ENTRY(big_bfree);
2486 MAKE_HASH_ENTRY(overflows);
2487 MAKE_HASH_ENTRY(ovfl_free);
2488 MAKE_HASH_ENTRY(dup);
2489 MAKE_HASH_ENTRY(dup_free);
2490 break;
2491
2492 case DB_BTREE:
2493 case DB_RECNO:
2494 MAKE_BT_ENTRY(magic);
2495 MAKE_BT_ENTRY(version);
2496 MAKE_BT_ENTRY(nkeys);
2497 MAKE_BT_ENTRY(ndata);
2498 MAKE_BT_ENTRY(pagesize);
2499 MAKE_BT_ENTRY(minkey);
2500 MAKE_BT_ENTRY(re_len);
2501 MAKE_BT_ENTRY(re_pad);
2502 MAKE_BT_ENTRY(levels);
2503 MAKE_BT_ENTRY(int_pg);
2504 MAKE_BT_ENTRY(leaf_pg);
2505 MAKE_BT_ENTRY(dup_pg);
2506 MAKE_BT_ENTRY(over_pg);
2507 MAKE_BT_ENTRY(free);
2508 MAKE_BT_ENTRY(int_pgfree);
2509 MAKE_BT_ENTRY(leaf_pgfree);
2510 MAKE_BT_ENTRY(dup_pgfree);
2511 MAKE_BT_ENTRY(over_pgfree);
2512 break;
2513
2514 case DB_QUEUE:
2515 MAKE_QUEUE_ENTRY(magic);
2516 MAKE_QUEUE_ENTRY(version);
2517 MAKE_QUEUE_ENTRY(nkeys);
2518 MAKE_QUEUE_ENTRY(ndata);
2519 MAKE_QUEUE_ENTRY(pagesize);
2520 MAKE_QUEUE_ENTRY(pages);
2521 MAKE_QUEUE_ENTRY(re_len);
2522 MAKE_QUEUE_ENTRY(re_pad);
2523 MAKE_QUEUE_ENTRY(pgfree);
2524#if (DBVER == 31)
2525 MAKE_QUEUE_ENTRY(start);
2526#endif
2527 MAKE_QUEUE_ENTRY(first_recno);
2528 MAKE_QUEUE_ENTRY(cur_recno);
2529 break;
2530
2531 default:
2532 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2533 Py_DECREF(d);
2534 d = NULL;
2535 }
2536
2537#undef MAKE_HASH_ENTRY
2538#undef MAKE_BT_ENTRY
2539#undef MAKE_QUEUE_ENTRY
2540
2541 free(sp);
2542 return d;
2543}
2544
2545static PyObject*
2546DB_sync(DBObject* self, PyObject* args)
2547{
2548 int err;
2549 int flags = 0;
2550
2551 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2552 return NULL;
2553 CHECK_DB_NOT_CLOSED(self);
2554
2555 MYDB_BEGIN_ALLOW_THREADS;
2556 err = self->db->sync(self->db, flags);
2557 MYDB_END_ALLOW_THREADS;
2558 RETURN_IF_ERR();
2559 RETURN_NONE();
2560}
2561
2562
2563#if (DBVER >= 33)
2564static PyObject*
2565DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2566{
2567 int err, flags=0;
2568 u_int32_t count=0;
2569 PyObject* txnobj = NULL;
2570 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002571 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002572
2573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2574 &txnobj, &flags))
2575 return NULL;
2576 CHECK_DB_NOT_CLOSED(self);
2577 if (!checkTxnObj(txnobj, &txn))
2578 return NULL;
2579
2580 MYDB_BEGIN_ALLOW_THREADS;
2581 err = self->db->truncate(self->db, txn, &count, flags);
2582 MYDB_END_ALLOW_THREADS;
2583 RETURN_IF_ERR();
2584 return PyInt_FromLong(count);
2585}
2586#endif
2587
2588
2589static PyObject*
2590DB_upgrade(DBObject* self, PyObject* args)
2591{
2592 int err, flags=0;
2593 char *filename;
2594
2595 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2596 return NULL;
2597 CHECK_DB_NOT_CLOSED(self);
2598
2599 MYDB_BEGIN_ALLOW_THREADS;
2600 err = self->db->upgrade(self->db, filename, flags);
2601 MYDB_END_ALLOW_THREADS;
2602 RETURN_IF_ERR();
2603 RETURN_NONE();
2604}
2605
2606
2607static PyObject*
2608DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2609{
2610 int err, flags=0;
2611 char* fileName;
2612 char* dbName=NULL;
2613 char* outFileName=NULL;
2614 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002615 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002616 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002617
2618 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2619 &fileName, &dbName, &outFileName, &flags))
2620 return NULL;
2621
2622 CHECK_DB_NOT_CLOSED(self);
2623 if (outFileName)
2624 outFile = fopen(outFileName, "w");
2625
2626 MYDB_BEGIN_ALLOW_THREADS;
2627 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2628 MYDB_END_ALLOW_THREADS;
2629 if (outFileName)
2630 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002631
2632 /* DB.verify acts as a DB handle destructor (like close); this was
2633 * documented in BerkeleyDB 4.2 but had the undocumented effect
2634 * of not being safe in prior versions while still requiring an explicit
2635 * DB.close call afterwards. Lets call close for the user to emulate
2636 * the safe 4.2 behaviour. */
2637#if (DBVER <= 41)
2638 self->db->close(self->db, 0);
2639#endif
2640 self->db = NULL;
2641
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002642 RETURN_IF_ERR();
2643 RETURN_NONE();
2644}
2645
2646
2647static PyObject*
2648DB_set_get_returns_none(DBObject* self, PyObject* args)
2649{
2650 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002651 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002652
2653 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2654 return NULL;
2655 CHECK_DB_NOT_CLOSED(self);
2656
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002657 if (self->moduleFlags.getReturnsNone)
2658 ++oldValue;
2659 if (self->moduleFlags.cursorSetReturnsNone)
2660 ++oldValue;
2661 self->moduleFlags.getReturnsNone = (flags >= 1);
2662 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002663 return PyInt_FromLong(oldValue);
2664}
2665
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002666#if (DBVER >= 41)
2667static PyObject*
2668DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2669{
2670 int err;
2671 u_int32_t flags=0;
2672 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002673 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002674
2675 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2676 &passwd, &flags)) {
2677 return NULL;
2678 }
2679
2680 MYDB_BEGIN_ALLOW_THREADS;
2681 err = self->db->set_encrypt(self->db, passwd, flags);
2682 MYDB_END_ALLOW_THREADS;
2683
2684 RETURN_IF_ERR();
2685 RETURN_NONE();
2686}
2687#endif /* DBVER >= 41 */
2688
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002689
2690/*-------------------------------------------------------------- */
2691/* Mapping and Dictionary-like access routines */
2692
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002693Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002694{
2695 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002696 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002697 int flags = 0;
2698 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002699 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700
2701 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002702 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2703 PyErr_SetObject(DBError, t);
2704 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002705 return -1;
2706 }
2707
2708 if (self->haveStat) { /* Has the stat function been called recently? If
2709 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002710 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002711 }
2712
2713 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002714redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002715#if (DBVER >= 43)
2716 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2717#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002718 err = self->db->stat(self->db, &sp, flags);
2719#else
2720 err = self->db->stat(self->db, &sp, NULL, flags);
2721#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002722
2723 /* All the stat structures have matching fields upto the ndata field,
2724 so we can use any of them for the type cast */
2725 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2726
2727 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2728 * redo a full stat to make sure.
2729 * Fixes SF python bug 1493322, pybsddb bug 1184012
2730 */
2731 if (size == 0 && (flags & DB_FAST_STAT)) {
2732 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002733 if (!err)
2734 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002735 goto redo_stat_for_length;
2736 }
2737
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002738 MYDB_END_ALLOW_THREADS;
2739
2740 if (err)
2741 return -1;
2742
2743 self->haveStat = 1;
2744
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002745 free(sp);
2746 return size;
2747}
2748
2749
2750PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2751{
2752 int err;
2753 PyObject* retval;
2754 DBT key;
2755 DBT data;
2756
2757 CHECK_DB_NOT_CLOSED(self);
2758 if (!make_key_dbt(self, keyobj, &key, NULL))
2759 return NULL;
2760
2761 CLEAR_DBT(data);
2762 if (CHECK_DBFLAG(self, DB_THREAD)) {
2763 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2764 data.flags = DB_DBT_MALLOC;
2765 }
2766 MYDB_BEGIN_ALLOW_THREADS;
2767 err = self->db->get(self->db, NULL, &key, &data, 0);
2768 MYDB_END_ALLOW_THREADS;
2769 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2770 PyErr_SetObject(PyExc_KeyError, keyobj);
2771 retval = NULL;
2772 }
2773 else if (makeDBError(err)) {
2774 retval = NULL;
2775 }
2776 else {
2777 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2778 FREE_DBT(data);
2779 }
2780
2781 FREE_DBT(key);
2782 return retval;
2783}
2784
2785
2786static int
2787DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2788{
2789 DBT key, data;
2790 int retval;
2791 int flags = 0;
2792
2793 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002794 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2795 PyErr_SetObject(DBError, t);
2796 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002797 return -1;
2798 }
2799
2800 if (!make_key_dbt(self, keyobj, &key, NULL))
2801 return -1;
2802
2803 if (dataobj != NULL) {
2804 if (!make_dbt(dataobj, &data))
2805 retval = -1;
2806 else {
2807 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002808 /* dictionaries shouldn't have duplicate keys */
2809 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002810 retval = _DB_put(self, NULL, &key, &data, flags);
2811
2812 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002813 /* try deleting any old record that matches and then PUT it
2814 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002815 _DB_delete(self, NULL, &key, 0);
2816 PyErr_Clear();
2817 retval = _DB_put(self, NULL, &key, &data, flags);
2818 }
2819 }
2820 }
2821 else {
2822 /* dataobj == NULL, so delete the key */
2823 retval = _DB_delete(self, NULL, &key, 0);
2824 }
2825 FREE_DBT(key);
2826 return retval;
2827}
2828
2829
2830static PyObject*
2831DB_has_key(DBObject* self, PyObject* args)
2832{
2833 int err;
2834 PyObject* keyobj;
2835 DBT key, data;
2836 PyObject* txnobj = NULL;
2837 DB_TXN *txn = NULL;
2838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002839 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002840 return NULL;
2841 CHECK_DB_NOT_CLOSED(self);
2842 if (!make_key_dbt(self, keyobj, &key, NULL))
2843 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002844 if (!checkTxnObj(txnobj, &txn)) {
2845 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002847 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002849 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 it has a record but can't allocate a buffer for the data. This saves
2851 having to deal with data we won't be using.
2852 */
2853 CLEAR_DBT(data);
2854 data.flags = DB_DBT_USERMEM;
2855
2856 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002857 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 MYDB_END_ALLOW_THREADS;
2859 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002860
2861 if (err == DB_BUFFER_SMALL || err == 0) {
2862 return PyInt_FromLong(1);
2863 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2864 return PyInt_FromLong(0);
2865 }
2866
2867 makeDBError(err);
2868 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869}
2870
2871
2872#define _KEYS_LIST 1
2873#define _VALUES_LIST 2
2874#define _ITEMS_LIST 3
2875
2876static PyObject*
2877_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2878{
2879 int err, dbtype;
2880 DBT key;
2881 DBT data;
2882 DBC *cursor;
2883 PyObject* list;
2884 PyObject* item = NULL;
2885
2886 CHECK_DB_NOT_CLOSED(self);
2887 CLEAR_DBT(key);
2888 CLEAR_DBT(data);
2889
2890 dbtype = _DB_get_type(self);
2891 if (dbtype == -1)
2892 return NULL;
2893
2894 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002895 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002896 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002897
2898 /* get a cursor */
2899 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002900 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002902 if (makeDBError(err)) {
2903 Py_DECREF(list);
2904 return NULL;
2905 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906
2907 if (CHECK_DBFLAG(self, DB_THREAD)) {
2908 key.flags = DB_DBT_REALLOC;
2909 data.flags = DB_DBT_REALLOC;
2910 }
2911
2912 while (1) { /* use the cursor to traverse the DB, collecting items */
2913 MYDB_BEGIN_ALLOW_THREADS;
2914 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2915 MYDB_END_ALLOW_THREADS;
2916
2917 if (err) {
2918 /* for any error, break out of the loop */
2919 break;
2920 }
2921
2922 switch (type) {
2923 case _KEYS_LIST:
2924 switch(dbtype) {
2925 case DB_BTREE:
2926 case DB_HASH:
2927 default:
2928 item = PyString_FromStringAndSize((char*)key.data, key.size);
2929 break;
2930 case DB_RECNO:
2931 case DB_QUEUE:
2932 item = PyInt_FromLong(*((db_recno_t*)key.data));
2933 break;
2934 }
2935 break;
2936
2937 case _VALUES_LIST:
2938 item = PyString_FromStringAndSize((char*)data.data, data.size);
2939 break;
2940
2941 case _ITEMS_LIST:
2942 switch(dbtype) {
2943 case DB_BTREE:
2944 case DB_HASH:
2945 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002946 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2947 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 break;
2949 case DB_RECNO:
2950 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002951 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2952 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002953 break;
2954 }
2955 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002956 default:
2957 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2958 item = NULL;
2959 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 }
2961 if (item == NULL) {
2962 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 list = NULL;
2964 goto done;
2965 }
2966 PyList_Append(list, item);
2967 Py_DECREF(item);
2968 }
2969
Gregory P. Smithe9477062005-06-04 06:46:59 +00002970 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2971 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002972 Py_DECREF(list);
2973 list = NULL;
2974 }
2975
2976 done:
2977 FREE_DBT(key);
2978 FREE_DBT(data);
2979 MYDB_BEGIN_ALLOW_THREADS;
2980 cursor->c_close(cursor);
2981 MYDB_END_ALLOW_THREADS;
2982 return list;
2983}
2984
2985
2986static PyObject*
2987DB_keys(DBObject* self, PyObject* args)
2988{
2989 PyObject* txnobj = NULL;
2990 DB_TXN *txn = NULL;
2991
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002992 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002993 return NULL;
2994 if (!checkTxnObj(txnobj, &txn))
2995 return NULL;
2996 return _DB_make_list(self, txn, _KEYS_LIST);
2997}
2998
2999
3000static PyObject*
3001DB_items(DBObject* self, PyObject* args)
3002{
3003 PyObject* txnobj = NULL;
3004 DB_TXN *txn = NULL;
3005
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003006 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003007 return NULL;
3008 if (!checkTxnObj(txnobj, &txn))
3009 return NULL;
3010 return _DB_make_list(self, txn, _ITEMS_LIST);
3011}
3012
3013
3014static PyObject*
3015DB_values(DBObject* self, PyObject* args)
3016{
3017 PyObject* txnobj = NULL;
3018 DB_TXN *txn = NULL;
3019
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003020 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003021 return NULL;
3022 if (!checkTxnObj(txnobj, &txn))
3023 return NULL;
3024 return _DB_make_list(self, txn, _VALUES_LIST);
3025}
3026
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003027/* --------------------------------------------------------------------- */
3028/* DBCursor methods */
3029
3030
3031static PyObject*
3032DBC_close(DBCursorObject* self, PyObject* args)
3033{
3034 int err = 0;
3035
3036 if (!PyArg_ParseTuple(args, ":close"))
3037 return NULL;
3038
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003039 if (self->dbc != NULL) {
3040 MYDB_BEGIN_ALLOW_THREADS;
3041 err = self->dbc->c_close(self->dbc);
3042 self->dbc = NULL;
3043 MYDB_END_ALLOW_THREADS;
3044 }
3045 RETURN_IF_ERR();
3046 RETURN_NONE();
3047}
3048
3049
3050static PyObject*
3051DBC_count(DBCursorObject* self, PyObject* args)
3052{
3053 int err = 0;
3054 db_recno_t count;
3055 int flags = 0;
3056
3057 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3058 return NULL;
3059
3060 CHECK_CURSOR_NOT_CLOSED(self);
3061
3062 MYDB_BEGIN_ALLOW_THREADS;
3063 err = self->dbc->c_count(self->dbc, &count, flags);
3064 MYDB_END_ALLOW_THREADS;
3065 RETURN_IF_ERR();
3066
3067 return PyInt_FromLong(count);
3068}
3069
3070
3071static PyObject*
3072DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3073{
3074 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3075}
3076
3077
3078static PyObject*
3079DBC_delete(DBCursorObject* self, PyObject* args)
3080{
3081 int err, flags=0;
3082
3083 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3084 return NULL;
3085
3086 CHECK_CURSOR_NOT_CLOSED(self);
3087
3088 MYDB_BEGIN_ALLOW_THREADS;
3089 err = self->dbc->c_del(self->dbc, flags);
3090 MYDB_END_ALLOW_THREADS;
3091 RETURN_IF_ERR();
3092
3093 self->mydb->haveStat = 0;
3094 RETURN_NONE();
3095}
3096
3097
3098static PyObject*
3099DBC_dup(DBCursorObject* self, PyObject* args)
3100{
3101 int err, flags =0;
3102 DBC* dbc = NULL;
3103
3104 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3105 return NULL;
3106
3107 CHECK_CURSOR_NOT_CLOSED(self);
3108
3109 MYDB_BEGIN_ALLOW_THREADS;
3110 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3111 MYDB_END_ALLOW_THREADS;
3112 RETURN_IF_ERR();
3113
3114 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3115}
3116
3117static PyObject*
3118DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3119{
3120 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3121}
3122
3123
3124static PyObject*
3125DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3126{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003127 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 PyObject* keyobj = NULL;
3129 PyObject* dataobj = NULL;
3130 PyObject* retval = NULL;
3131 int dlen = -1;
3132 int doff = -1;
3133 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003134 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003135 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136
3137 CLEAR_DBT(key);
3138 CLEAR_DBT(data);
3139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003140 &flags, &dlen, &doff))
3141 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3144 &kwnames[1],
3145 &keyobj, &flags, &dlen, &doff))
3146 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003147 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003148 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3149 kwnames, &keyobj, &dataobj,
3150 &flags, &dlen, &doff))
3151 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152 return NULL;
3153 }
3154 }
3155 }
3156
3157 CHECK_CURSOR_NOT_CLOSED(self);
3158
3159 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3160 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003161 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3162 (!add_partial_dbt(&data, dlen, doff)) )
3163 {
3164 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003166 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167
3168 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3169 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003170 if (!(key.flags & DB_DBT_REALLOC)) {
3171 key.flags |= DB_DBT_MALLOC;
3172 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 }
3174
3175 MYDB_BEGIN_ALLOW_THREADS;
3176 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3177 MYDB_END_ALLOW_THREADS;
3178
Gregory P. Smithe9477062005-06-04 06:46:59 +00003179 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3180 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003181 Py_INCREF(Py_None);
3182 retval = Py_None;
3183 }
3184 else if (makeDBError(err)) {
3185 retval = NULL;
3186 }
3187 else {
3188 switch (_DB_get_type(self->mydb)) {
3189 case -1:
3190 retval = NULL;
3191 break;
3192 case DB_BTREE:
3193 case DB_HASH:
3194 default:
3195 retval = Py_BuildValue("s#s#", key.data, key.size,
3196 data.data, data.size);
3197 break;
3198 case DB_RECNO:
3199 case DB_QUEUE:
3200 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3201 data.data, data.size);
3202 break;
3203 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003204 FREE_DBT(data);
3205 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003206 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003207 return retval;
3208}
3209
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003210#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003211static PyObject*
3212DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3213{
3214 int err, flags=0;
3215 PyObject* keyobj = NULL;
3216 PyObject* dataobj = NULL;
3217 PyObject* retval = NULL;
3218 int dlen = -1;
3219 int doff = -1;
3220 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003221 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3222 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003223
3224 CLEAR_DBT(key);
3225 CLEAR_DBT(data);
3226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3227 &flags, &dlen, &doff))
3228 {
3229 PyErr_Clear();
3230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003231 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003232 &keyobj, &flags, &dlen, &doff))
3233 {
3234 PyErr_Clear();
3235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3236 kwnames, &keyobj, &dataobj,
3237 &flags, &dlen, &doff))
3238 {
3239 return NULL;
3240 }
3241 }
3242 }
3243
3244 CHECK_CURSOR_NOT_CLOSED(self);
3245
3246 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3247 return NULL;
3248 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3249 (!add_partial_dbt(&data, dlen, doff)) ) {
3250 FREE_DBT(key);
3251 return NULL;
3252 }
3253
3254 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3255 data.flags = DB_DBT_MALLOC;
3256 if (!(key.flags & DB_DBT_REALLOC)) {
3257 key.flags |= DB_DBT_MALLOC;
3258 }
3259 }
3260
3261 CLEAR_DBT(pkey);
3262 pkey.flags = DB_DBT_MALLOC;
3263
3264 MYDB_BEGIN_ALLOW_THREADS;
3265 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3266 MYDB_END_ALLOW_THREADS;
3267
Gregory P. Smithe9477062005-06-04 06:46:59 +00003268 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3269 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003270 Py_INCREF(Py_None);
3271 retval = Py_None;
3272 }
3273 else if (makeDBError(err)) {
3274 retval = NULL;
3275 }
3276 else {
3277 PyObject *pkeyObj;
3278 PyObject *dataObj;
3279 dataObj = PyString_FromStringAndSize(data.data, data.size);
3280
3281 if (self->mydb->primaryDBType == DB_RECNO ||
3282 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003283 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003284 else
3285 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3286
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003287 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003288 {
3289 PyObject *keyObj;
3290 int type = _DB_get_type(self->mydb);
3291 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003292 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293 else
3294 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003295#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003296 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003297#else
3298 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3299#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003300 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301 FREE_DBT(key);
3302 }
3303 else /* return just the pkey and data */
3304 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003305#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003306 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003307#else
3308 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3309#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003310 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003311 Py_DECREF(dataObj);
3312 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313 FREE_DBT(pkey);
3314 FREE_DBT(data);
3315 }
3316 /* the only time REALLOC should be set is if we used an integer
3317 * key that make_key_dbt malloc'd for us. always free these. */
3318 if (key.flags & DB_DBT_REALLOC) {
3319 FREE_DBT(key);
3320 }
3321 return retval;
3322}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003323#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003325
3326static PyObject*
3327DBC_get_recno(DBCursorObject* self, PyObject* args)
3328{
3329 int err;
3330 db_recno_t recno;
3331 DBT key;
3332 DBT data;
3333
3334 if (!PyArg_ParseTuple(args, ":get_recno"))
3335 return NULL;
3336
3337 CHECK_CURSOR_NOT_CLOSED(self);
3338
3339 CLEAR_DBT(key);
3340 CLEAR_DBT(data);
3341 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3342 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3343 data.flags = DB_DBT_MALLOC;
3344 key.flags = DB_DBT_MALLOC;
3345 }
3346
3347 MYDB_BEGIN_ALLOW_THREADS;
3348 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3349 MYDB_END_ALLOW_THREADS;
3350 RETURN_IF_ERR();
3351
3352 recno = *((db_recno_t*)data.data);
3353 FREE_DBT(key);
3354 FREE_DBT(data);
3355 return PyInt_FromLong(recno);
3356}
3357
3358
3359static PyObject*
3360DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3361{
3362 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3363}
3364
3365
3366static PyObject*
3367DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3368{
3369 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3370}
3371
3372
3373static PyObject*
3374DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3375{
3376 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3377}
3378
3379
3380static PyObject*
3381DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3382{
3383 int err, flags = 0;
3384 PyObject* keyobj, *dataobj;
3385 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003386 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003387 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003388 int dlen = -1;
3389 int doff = -1;
3390
3391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3392 &keyobj, &dataobj, &flags, &dlen, &doff))
3393 return NULL;
3394
3395 CHECK_CURSOR_NOT_CLOSED(self);
3396
3397 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3398 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003399 if (!make_dbt(dataobj, &data) ||
3400 !add_partial_dbt(&data, dlen, doff) )
3401 {
3402 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003403 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003404 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003405
3406 MYDB_BEGIN_ALLOW_THREADS;
3407 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3408 MYDB_END_ALLOW_THREADS;
3409 FREE_DBT(key);
3410 RETURN_IF_ERR();
3411 self->mydb->haveStat = 0;
3412 RETURN_NONE();
3413}
3414
3415
3416static PyObject*
3417DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3418{
3419 int err, flags = 0;
3420 DBT key, data;
3421 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003422 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003423 int dlen = -1;
3424 int doff = -1;
3425
3426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3427 &keyobj, &flags, &dlen, &doff))
3428 return NULL;
3429
3430 CHECK_CURSOR_NOT_CLOSED(self);
3431
3432 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3433 return NULL;
3434
3435 CLEAR_DBT(data);
3436 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3437 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3438 data.flags = DB_DBT_MALLOC;
3439 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003440 if (!add_partial_dbt(&data, dlen, doff)) {
3441 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003443 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444
3445 MYDB_BEGIN_ALLOW_THREADS;
3446 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3447 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003448 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3449 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003450 Py_INCREF(Py_None);
3451 retval = Py_None;
3452 }
3453 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454 retval = NULL;
3455 }
3456 else {
3457 switch (_DB_get_type(self->mydb)) {
3458 case -1:
3459 retval = NULL;
3460 break;
3461 case DB_BTREE:
3462 case DB_HASH:
3463 default:
3464 retval = Py_BuildValue("s#s#", key.data, key.size,
3465 data.data, data.size);
3466 break;
3467 case DB_RECNO:
3468 case DB_QUEUE:
3469 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3470 data.data, data.size);
3471 break;
3472 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003474 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003476 /* the only time REALLOC should be set is if we used an integer
3477 * key that make_key_dbt malloc'd for us. always free these. */
3478 if (key.flags & DB_DBT_REALLOC) {
3479 FREE_DBT(key);
3480 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481
3482 return retval;
3483}
3484
3485
3486static PyObject*
3487DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3488{
3489 int err, flags = 0;
3490 DBT key, data;
3491 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003492 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003493 int dlen = -1;
3494 int doff = -1;
3495
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3497 &keyobj, &flags, &dlen, &doff))
3498 return NULL;
3499
3500 CHECK_CURSOR_NOT_CLOSED(self);
3501
3502 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3503 return NULL;
3504
3505 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003506 if (!add_partial_dbt(&data, dlen, doff)) {
3507 FREE_DBT(key);
3508 return NULL;
3509 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003510 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3511 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003512 data.flags |= DB_DBT_MALLOC;
3513 /* only BTREE databases will return anything in the key */
3514 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3515 key.flags |= DB_DBT_MALLOC;
3516 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003517 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003518 MYDB_BEGIN_ALLOW_THREADS;
3519 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3520 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003521 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3522 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003523 Py_INCREF(Py_None);
3524 retval = Py_None;
3525 }
3526 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003527 retval = NULL;
3528 }
3529 else {
3530 switch (_DB_get_type(self->mydb)) {
3531 case -1:
3532 retval = NULL;
3533 break;
3534 case DB_BTREE:
3535 case DB_HASH:
3536 default:
3537 retval = Py_BuildValue("s#s#", key.data, key.size,
3538 data.data, data.size);
3539 break;
3540 case DB_RECNO:
3541 case DB_QUEUE:
3542 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3543 data.data, data.size);
3544 break;
3545 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003546 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 FREE_DBT(data);
3548 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003549 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003550 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003551 if (key.flags & DB_DBT_REALLOC) {
3552 FREE_DBT(key);
3553 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554
3555 return retval;
3556}
3557
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003559_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3560 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003561{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003562 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003563 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003564 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565
Gregory P. Smith7441e652003-11-03 21:35:31 +00003566 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3568 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003569 if (!make_dbt(dataobj, &data)) {
3570 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573
3574 MYDB_BEGIN_ALLOW_THREADS;
3575 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3576 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003577 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003578 Py_INCREF(Py_None);
3579 retval = Py_None;
3580 }
3581 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 retval = NULL;
3583 }
3584 else {
3585 switch (_DB_get_type(self->mydb)) {
3586 case -1:
3587 retval = NULL;
3588 break;
3589 case DB_BTREE:
3590 case DB_HASH:
3591 default:
3592 retval = Py_BuildValue("s#s#", key.data, key.size,
3593 data.data, data.size);
3594 break;
3595 case DB_RECNO:
3596 case DB_QUEUE:
3597 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3598 data.data, data.size);
3599 break;
3600 }
3601 }
3602
3603 FREE_DBT(key);
3604 return retval;
3605}
3606
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003607static PyObject*
3608DBC_get_both(DBCursorObject* self, PyObject* args)
3609{
3610 int flags=0;
3611 PyObject *keyobj, *dataobj;
3612
3613 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3614 return NULL;
3615
Gregory P. Smith7441e652003-11-03 21:35:31 +00003616 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003617 CHECK_CURSOR_NOT_CLOSED(self);
3618
3619 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3620 self->mydb->moduleFlags.getReturnsNone);
3621}
3622
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003623/* Return size of entry */
3624static PyObject*
3625DBC_get_current_size(DBCursorObject* self, PyObject* args)
3626{
3627 int err, flags=DB_CURRENT;
3628 PyObject* retval = NULL;
3629 DBT key, data;
3630
3631 if (!PyArg_ParseTuple(args, ":get_current_size"))
3632 return NULL;
3633 CHECK_CURSOR_NOT_CLOSED(self);
3634 CLEAR_DBT(key);
3635 CLEAR_DBT(data);
3636
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003637 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003638 getting the record size. */
3639 data.flags = DB_DBT_USERMEM;
3640 data.ulen = 0;
3641 MYDB_BEGIN_ALLOW_THREADS;
3642 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3643 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003644 if (err == DB_BUFFER_SMALL || !err) {
3645 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003646 retval = PyInt_FromLong((long)data.size);
3647 err = 0;
3648 }
3649
3650 FREE_DBT(key);
3651 FREE_DBT(data);
3652 RETURN_IF_ERR();
3653 return retval;
3654}
3655
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003656static PyObject*
3657DBC_set_both(DBCursorObject* self, PyObject* args)
3658{
3659 int flags=0;
3660 PyObject *keyobj, *dataobj;
3661
3662 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3663 return NULL;
3664
Gregory P. Smith7441e652003-11-03 21:35:31 +00003665 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003666 CHECK_CURSOR_NOT_CLOSED(self);
3667
3668 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3669 self->mydb->moduleFlags.cursorSetReturnsNone);
3670}
3671
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672
3673static PyObject*
3674DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3675{
3676 int err, irecno, flags=0;
3677 db_recno_t recno;
3678 DBT key, data;
3679 PyObject* retval;
3680 int dlen = -1;
3681 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003682 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683
3684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3685 &irecno, &flags, &dlen, &doff))
3686 return NULL;
3687
3688 CHECK_CURSOR_NOT_CLOSED(self);
3689
3690 CLEAR_DBT(key);
3691 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003692 /* use allocated space so DB will be able to realloc room for the real
3693 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694 key.data = malloc(sizeof(db_recno_t));
3695 if (key.data == NULL) {
3696 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3697 return NULL;
3698 }
3699 key.size = sizeof(db_recno_t);
3700 key.ulen = key.size;
3701 memcpy(key.data, &recno, sizeof(db_recno_t));
3702 key.flags = DB_DBT_REALLOC;
3703
3704 CLEAR_DBT(data);
3705 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3706 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3707 data.flags = DB_DBT_MALLOC;
3708 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003709 if (!add_partial_dbt(&data, dlen, doff)) {
3710 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003711 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003712 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003713
3714 MYDB_BEGIN_ALLOW_THREADS;
3715 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3716 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003717 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3718 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003719 Py_INCREF(Py_None);
3720 retval = Py_None;
3721 }
3722 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003723 retval = NULL;
3724 }
3725 else { /* Can only be used for BTrees, so no need to return int key */
3726 retval = Py_BuildValue("s#s#", key.data, key.size,
3727 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003728 FREE_DBT(data);
3729 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003730 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003731
3732 return retval;
3733}
3734
3735
3736static PyObject*
3737DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3738{
3739 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3740}
3741
3742
3743static PyObject*
3744DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3745{
3746 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3747}
3748
3749
3750static PyObject*
3751DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3752{
3753 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3754}
3755
3756
3757static PyObject*
3758DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3759{
3760 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3761}
3762
3763
3764static PyObject*
3765DBC_join_item(DBCursorObject* self, PyObject* args)
3766{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003767 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003768 DBT key, data;
3769 PyObject* retval;
3770
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003771 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003772 return NULL;
3773
3774 CHECK_CURSOR_NOT_CLOSED(self);
3775
3776 CLEAR_DBT(key);
3777 CLEAR_DBT(data);
3778 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3779 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3780 key.flags = DB_DBT_MALLOC;
3781 }
3782
3783 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003784 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003785 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003786 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3787 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003788 Py_INCREF(Py_None);
3789 retval = Py_None;
3790 }
3791 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003792 retval = NULL;
3793 }
3794 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003795 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796 FREE_DBT(key);
3797 }
3798
3799 return retval;
3800}
3801
3802
3803
3804/* --------------------------------------------------------------------- */
3805/* DBEnv methods */
3806
3807
3808static PyObject*
3809DBEnv_close(DBEnvObject* self, PyObject* args)
3810{
3811 int err, flags = 0;
3812
3813 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3814 return NULL;
3815 if (!self->closed) { /* Don't close more than once */
3816 MYDB_BEGIN_ALLOW_THREADS;
3817 err = self->db_env->close(self->db_env, flags);
3818 MYDB_END_ALLOW_THREADS;
3819 /* after calling DBEnv->close, regardless of error, this DBEnv
3820 * may not be accessed again (BerkeleyDB docs). */
3821 self->closed = 1;
3822 self->db_env = NULL;
3823 RETURN_IF_ERR();
3824 }
3825 RETURN_NONE();
3826}
3827
3828
3829static PyObject*
3830DBEnv_open(DBEnvObject* self, PyObject* args)
3831{
3832 int err, flags=0, mode=0660;
3833 char *db_home;
3834
3835 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3836 return NULL;
3837
3838 CHECK_ENV_NOT_CLOSED(self);
3839
3840 MYDB_BEGIN_ALLOW_THREADS;
3841 err = self->db_env->open(self->db_env, db_home, flags, mode);
3842 MYDB_END_ALLOW_THREADS;
3843 RETURN_IF_ERR();
3844 self->closed = 0;
3845 self->flags = flags;
3846 RETURN_NONE();
3847}
3848
3849
3850static PyObject*
3851DBEnv_remove(DBEnvObject* self, PyObject* args)
3852{
3853 int err, flags=0;
3854 char *db_home;
3855
3856 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3857 return NULL;
3858 CHECK_ENV_NOT_CLOSED(self);
3859 MYDB_BEGIN_ALLOW_THREADS;
3860 err = self->db_env->remove(self->db_env, db_home, flags);
3861 MYDB_END_ALLOW_THREADS;
3862 RETURN_IF_ERR();
3863 RETURN_NONE();
3864}
3865
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003866#if (DBVER >= 41)
3867static PyObject*
3868DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3869{
3870 int err;
3871 u_int32_t flags=0;
3872 char *file = NULL;
3873 char *database = NULL;
3874 PyObject *txnobj = NULL;
3875 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003876 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003877 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003878
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003879 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003880 &file, &database, &txnobj, &flags)) {
3881 return NULL;
3882 }
3883 if (!checkTxnObj(txnobj, &txn)) {
3884 return NULL;
3885 }
3886 CHECK_ENV_NOT_CLOSED(self);
3887 MYDB_BEGIN_ALLOW_THREADS;
3888 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3889 MYDB_END_ALLOW_THREADS;
3890 RETURN_IF_ERR();
3891 RETURN_NONE();
3892}
3893
3894static PyObject*
3895DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3896{
3897 int err;
3898 u_int32_t flags=0;
3899 char *file = NULL;
3900 char *database = NULL;
3901 char *newname = NULL;
3902 PyObject *txnobj = NULL;
3903 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003904 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003905 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003906
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003908 &file, &database, &newname, &txnobj, &flags)) {
3909 return NULL;
3910 }
3911 if (!checkTxnObj(txnobj, &txn)) {
3912 return NULL;
3913 }
3914 CHECK_ENV_NOT_CLOSED(self);
3915 MYDB_BEGIN_ALLOW_THREADS;
3916 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3917 flags);
3918 MYDB_END_ALLOW_THREADS;
3919 RETURN_IF_ERR();
3920 RETURN_NONE();
3921}
3922
3923static PyObject*
3924DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3925{
3926 int err;
3927 u_int32_t flags=0;
3928 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003929 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003930
3931 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3932 &passwd, &flags)) {
3933 return NULL;
3934 }
3935
3936 MYDB_BEGIN_ALLOW_THREADS;
3937 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3938 MYDB_END_ALLOW_THREADS;
3939
3940 RETURN_IF_ERR();
3941 RETURN_NONE();
3942}
3943#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003944
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003945#if (DBVER >= 40)
3946static PyObject*
3947DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3948{
3949 int err;
3950 u_int32_t flags=0;
3951 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003952 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003953
3954 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3955 &timeout, &flags)) {
3956 return NULL;
3957 }
3958
3959 MYDB_BEGIN_ALLOW_THREADS;
3960 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3961 MYDB_END_ALLOW_THREADS;
3962
3963 RETURN_IF_ERR();
3964 RETURN_NONE();
3965}
3966#endif /* DBVER >= 40 */
3967
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003968static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003969DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3970{
3971 int err;
3972 long shm_key = 0;
3973
3974 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3975 return NULL;
3976 CHECK_ENV_NOT_CLOSED(self);
3977
3978 err = self->db_env->set_shm_key(self->db_env, shm_key);
3979 RETURN_IF_ERR();
3980 RETURN_NONE();
3981}
3982
3983static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003984DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3985{
3986 int err, gbytes=0, bytes=0, ncache=0;
3987
3988 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3989 &gbytes, &bytes, &ncache))
3990 return NULL;
3991 CHECK_ENV_NOT_CLOSED(self);
3992
3993 MYDB_BEGIN_ALLOW_THREADS;
3994 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3995 MYDB_END_ALLOW_THREADS;
3996 RETURN_IF_ERR();
3997 RETURN_NONE();
3998}
3999
4000
4001#if (DBVER >= 32)
4002static PyObject*
4003DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4004{
4005 int err, flags=0, onoff=0;
4006
4007 if (!PyArg_ParseTuple(args, "ii:set_flags",
4008 &flags, &onoff))
4009 return NULL;
4010 CHECK_ENV_NOT_CLOSED(self);
4011
4012 MYDB_BEGIN_ALLOW_THREADS;
4013 err = self->db_env->set_flags(self->db_env, flags, onoff);
4014 MYDB_END_ALLOW_THREADS;
4015 RETURN_IF_ERR();
4016 RETURN_NONE();
4017}
4018#endif
4019
4020
4021static PyObject*
4022DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4023{
4024 int err;
4025 char *dir;
4026
4027 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4028 return NULL;
4029 CHECK_ENV_NOT_CLOSED(self);
4030
4031 MYDB_BEGIN_ALLOW_THREADS;
4032 err = self->db_env->set_data_dir(self->db_env, dir);
4033 MYDB_END_ALLOW_THREADS;
4034 RETURN_IF_ERR();
4035 RETURN_NONE();
4036}
4037
4038
4039static PyObject*
4040DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4041{
4042 int err, lg_bsize;
4043
4044 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4045 return NULL;
4046 CHECK_ENV_NOT_CLOSED(self);
4047
4048 MYDB_BEGIN_ALLOW_THREADS;
4049 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4050 MYDB_END_ALLOW_THREADS;
4051 RETURN_IF_ERR();
4052 RETURN_NONE();
4053}
4054
4055
4056static PyObject*
4057DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4058{
4059 int err;
4060 char *dir;
4061
4062 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4063 return NULL;
4064 CHECK_ENV_NOT_CLOSED(self);
4065
4066 MYDB_BEGIN_ALLOW_THREADS;
4067 err = self->db_env->set_lg_dir(self->db_env, dir);
4068 MYDB_END_ALLOW_THREADS;
4069 RETURN_IF_ERR();
4070 RETURN_NONE();
4071}
4072
4073static PyObject*
4074DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4075{
4076 int err, lg_max;
4077
4078 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4079 return NULL;
4080 CHECK_ENV_NOT_CLOSED(self);
4081
4082 MYDB_BEGIN_ALLOW_THREADS;
4083 err = self->db_env->set_lg_max(self->db_env, lg_max);
4084 MYDB_END_ALLOW_THREADS;
4085 RETURN_IF_ERR();
4086 RETURN_NONE();
4087}
4088
4089
Neal Norwitz84562352005-10-20 04:30:15 +00004090#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004091static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004092DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4093{
4094 int err, lg_max;
4095
4096 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4097 return NULL;
4098 CHECK_ENV_NOT_CLOSED(self);
4099
4100 MYDB_BEGIN_ALLOW_THREADS;
4101 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4102 MYDB_END_ALLOW_THREADS;
4103 RETURN_IF_ERR();
4104 RETURN_NONE();
4105}
Neal Norwitz84562352005-10-20 04:30:15 +00004106#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004107
4108
4109static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004110DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4111{
4112 int err, lk_detect;
4113
4114 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4115 return NULL;
4116 CHECK_ENV_NOT_CLOSED(self);
4117
4118 MYDB_BEGIN_ALLOW_THREADS;
4119 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4120 MYDB_END_ALLOW_THREADS;
4121 RETURN_IF_ERR();
4122 RETURN_NONE();
4123}
4124
4125
4126static PyObject*
4127DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4128{
4129 int err, max;
4130
4131 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4132 return NULL;
4133 CHECK_ENV_NOT_CLOSED(self);
4134
4135 MYDB_BEGIN_ALLOW_THREADS;
4136 err = self->db_env->set_lk_max(self->db_env, max);
4137 MYDB_END_ALLOW_THREADS;
4138 RETURN_IF_ERR();
4139 RETURN_NONE();
4140}
4141
4142
4143#if (DBVER >= 32)
4144
4145static PyObject*
4146DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4147{
4148 int err, max;
4149
4150 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4151 return NULL;
4152 CHECK_ENV_NOT_CLOSED(self);
4153
4154 MYDB_BEGIN_ALLOW_THREADS;
4155 err = self->db_env->set_lk_max_locks(self->db_env, max);
4156 MYDB_END_ALLOW_THREADS;
4157 RETURN_IF_ERR();
4158 RETURN_NONE();
4159}
4160
4161
4162static PyObject*
4163DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4164{
4165 int err, max;
4166
4167 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4168 return NULL;
4169 CHECK_ENV_NOT_CLOSED(self);
4170
4171 MYDB_BEGIN_ALLOW_THREADS;
4172 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4173 MYDB_END_ALLOW_THREADS;
4174 RETURN_IF_ERR();
4175 RETURN_NONE();
4176}
4177
4178
4179static PyObject*
4180DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4181{
4182 int err, max;
4183
4184 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4185 return NULL;
4186 CHECK_ENV_NOT_CLOSED(self);
4187
4188 MYDB_BEGIN_ALLOW_THREADS;
4189 err = self->db_env->set_lk_max_objects(self->db_env, max);
4190 MYDB_END_ALLOW_THREADS;
4191 RETURN_IF_ERR();
4192 RETURN_NONE();
4193}
4194
4195#endif
4196
4197
4198static PyObject*
4199DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4200{
4201 int err, mp_mmapsize;
4202
4203 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4204 return NULL;
4205 CHECK_ENV_NOT_CLOSED(self);
4206
4207 MYDB_BEGIN_ALLOW_THREADS;
4208 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4209 MYDB_END_ALLOW_THREADS;
4210 RETURN_IF_ERR();
4211 RETURN_NONE();
4212}
4213
4214
4215static PyObject*
4216DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4217{
4218 int err;
4219 char *dir;
4220
4221 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4222 return NULL;
4223 CHECK_ENV_NOT_CLOSED(self);
4224
4225 MYDB_BEGIN_ALLOW_THREADS;
4226 err = self->db_env->set_tmp_dir(self->db_env, dir);
4227 MYDB_END_ALLOW_THREADS;
4228 RETURN_IF_ERR();
4229 RETURN_NONE();
4230}
4231
4232
4233static PyObject*
4234DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4235{
4236 int flags = 0;
4237 PyObject* txnobj = NULL;
4238 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004239 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004240
4241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4242 &txnobj, &flags))
4243 return NULL;
4244
4245 if (!checkTxnObj(txnobj, &txn))
4246 return NULL;
4247 CHECK_ENV_NOT_CLOSED(self);
4248
4249 return (PyObject*)newDBTxnObject(self, txn, flags);
4250}
4251
4252
4253static PyObject*
4254DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4255{
4256 int err, kbyte=0, min=0, flags=0;
4257
4258 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4259 return NULL;
4260 CHECK_ENV_NOT_CLOSED(self);
4261
4262 MYDB_BEGIN_ALLOW_THREADS;
4263#if (DBVER >= 40)
4264 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4265#else
4266 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4267#endif
4268 MYDB_END_ALLOW_THREADS;
4269 RETURN_IF_ERR();
4270 RETURN_NONE();
4271}
4272
4273
4274static PyObject*
4275DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4276{
4277 int err, max;
4278
4279 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4280 return NULL;
4281 CHECK_ENV_NOT_CLOSED(self);
4282
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004283 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004284 RETURN_IF_ERR();
4285 RETURN_NONE();
4286}
4287
4288
4289static PyObject*
4290DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4291{
4292 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004293 long stamp;
4294 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004295
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004296 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004297 return NULL;
4298 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004299 timestamp = (time_t)stamp;
4300 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004301 RETURN_IF_ERR();
4302 RETURN_NONE();
4303}
4304
4305
4306static PyObject*
4307DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4308{
4309 int err, atype, flags=0;
4310 int aborted = 0;
4311
4312 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4313 return NULL;
4314 CHECK_ENV_NOT_CLOSED(self);
4315
4316 MYDB_BEGIN_ALLOW_THREADS;
4317#if (DBVER >= 40)
4318 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4319#else
4320 err = lock_detect(self->db_env, flags, atype, &aborted);
4321#endif
4322 MYDB_END_ALLOW_THREADS;
4323 RETURN_IF_ERR();
4324 return PyInt_FromLong(aborted);
4325}
4326
4327
4328static PyObject*
4329DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4330{
4331 int flags=0;
4332 int locker, lock_mode;
4333 DBT obj;
4334 PyObject* objobj;
4335
4336 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4337 return NULL;
4338
4339
4340 if (!make_dbt(objobj, &obj))
4341 return NULL;
4342
4343 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4344}
4345
4346
4347static PyObject*
4348DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4349{
4350 int err;
4351 u_int32_t theID;
4352
4353 if (!PyArg_ParseTuple(args, ":lock_id"))
4354 return NULL;
4355
4356 CHECK_ENV_NOT_CLOSED(self);
4357 MYDB_BEGIN_ALLOW_THREADS;
4358#if (DBVER >= 40)
4359 err = self->db_env->lock_id(self->db_env, &theID);
4360#else
4361 err = lock_id(self->db_env, &theID);
4362#endif
4363 MYDB_END_ALLOW_THREADS;
4364 RETURN_IF_ERR();
4365
4366 return PyInt_FromLong((long)theID);
4367}
4368
4369
4370static PyObject*
4371DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4372{
4373 int err;
4374 DBLockObject* dblockobj;
4375
4376 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4377 return NULL;
4378
4379 CHECK_ENV_NOT_CLOSED(self);
4380 MYDB_BEGIN_ALLOW_THREADS;
4381#if (DBVER >= 40)
4382 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4383#else
4384 err = lock_put(self->db_env, &dblockobj->lock);
4385#endif
4386 MYDB_END_ALLOW_THREADS;
4387 RETURN_IF_ERR();
4388 RETURN_NONE();
4389}
4390
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004391#if (DBVER >= 44)
4392static PyObject*
4393DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4394{
4395 int err;
4396 char *file;
4397 u_int32_t flags = 0;
4398 static char* kwnames[] = { "file", "flags", NULL};
4399
4400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4401 &file, &flags))
4402 return NULL;
4403 CHECK_ENV_NOT_CLOSED(self);
4404
4405 MYDB_BEGIN_ALLOW_THREADS;
4406 err = self->db_env->lsn_reset(self->db_env, file, flags);
4407 MYDB_END_ALLOW_THREADS;
4408 RETURN_IF_ERR();
4409 RETURN_NONE();
4410}
4411#endif /* DBVER >= 4.4 */
4412
4413#if (DBVER >= 40)
4414static PyObject*
4415DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4416{
4417 int err;
4418 DB_LOG_STAT* statp = NULL;
4419 PyObject* d = NULL;
4420 u_int32_t flags = 0;
4421
4422 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4423 return NULL;
4424 CHECK_ENV_NOT_CLOSED(self);
4425
4426 MYDB_BEGIN_ALLOW_THREADS;
4427 err = self->db_env->log_stat(self->db_env, &statp, flags);
4428 MYDB_END_ALLOW_THREADS;
4429 RETURN_IF_ERR();
4430
4431 /* Turn the stat structure into a dictionary */
4432 d = PyDict_New();
4433 if (d == NULL) {
4434 if (statp)
4435 free(statp);
4436 return NULL;
4437 }
4438
4439#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4440
4441 MAKE_ENTRY(magic);
4442 MAKE_ENTRY(version);
4443 MAKE_ENTRY(mode);
4444 MAKE_ENTRY(lg_bsize);
4445#if (DBVER >= 44)
4446 MAKE_ENTRY(lg_size);
4447 MAKE_ENTRY(record);
4448#endif
4449#if (DBVER <= 40)
4450 MAKE_ENTRY(lg_max);
4451#endif
4452 MAKE_ENTRY(w_mbytes);
4453 MAKE_ENTRY(w_bytes);
4454 MAKE_ENTRY(wc_mbytes);
4455 MAKE_ENTRY(wc_bytes);
4456 MAKE_ENTRY(wcount);
4457 MAKE_ENTRY(wcount_fill);
4458#if (DBVER >= 44)
4459 MAKE_ENTRY(rcount);
4460#endif
4461 MAKE_ENTRY(scount);
4462 MAKE_ENTRY(cur_file);
4463 MAKE_ENTRY(cur_offset);
4464 MAKE_ENTRY(disk_file);
4465 MAKE_ENTRY(disk_offset);
4466 MAKE_ENTRY(maxcommitperflush);
4467 MAKE_ENTRY(mincommitperflush);
4468 MAKE_ENTRY(regsize);
4469 MAKE_ENTRY(region_wait);
4470 MAKE_ENTRY(region_nowait);
4471
4472#undef MAKE_ENTRY
4473 free(statp);
4474 return d;
4475} /* DBEnv_log_stat */
4476#endif /* DBVER >= 4.0 for log_stat method */
4477
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004478
4479static PyObject*
4480DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4481{
4482 int err;
4483 DB_LOCK_STAT* sp;
4484 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004485 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004486
4487 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4488 return NULL;
4489 CHECK_ENV_NOT_CLOSED(self);
4490
4491 MYDB_BEGIN_ALLOW_THREADS;
4492#if (DBVER >= 40)
4493 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4494#else
4495#if (DBVER >= 33)
4496 err = lock_stat(self->db_env, &sp);
4497#else
4498 err = lock_stat(self->db_env, &sp, NULL);
4499#endif
4500#endif
4501 MYDB_END_ALLOW_THREADS;
4502 RETURN_IF_ERR();
4503
4504 /* Turn the stat structure into a dictionary */
4505 d = PyDict_New();
4506 if (d == NULL) {
4507 free(sp);
4508 return NULL;
4509 }
4510
4511#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4512
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004513#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004514 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004515#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004516 MAKE_ENTRY(nmodes);
4517#if (DBVER >= 32)
4518 MAKE_ENTRY(maxlocks);
4519 MAKE_ENTRY(maxlockers);
4520 MAKE_ENTRY(maxobjects);
4521 MAKE_ENTRY(nlocks);
4522 MAKE_ENTRY(maxnlocks);
4523#endif
4524 MAKE_ENTRY(nlockers);
4525 MAKE_ENTRY(maxnlockers);
4526#if (DBVER >= 32)
4527 MAKE_ENTRY(nobjects);
4528 MAKE_ENTRY(maxnobjects);
4529#endif
4530 MAKE_ENTRY(nrequests);
4531 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004532#if (DBVER < 44)
4533 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004534 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004535#else
4536 MAKE_ENTRY(lock_nowait);
4537 MAKE_ENTRY(lock_wait);
4538#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 MAKE_ENTRY(ndeadlocks);
4540 MAKE_ENTRY(regsize);
4541 MAKE_ENTRY(region_wait);
4542 MAKE_ENTRY(region_nowait);
4543
4544#undef MAKE_ENTRY
4545 free(sp);
4546 return d;
4547}
4548
4549
4550static PyObject*
4551DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4552{
4553 int flags=0;
4554 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004555 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004556 PyObject* list;
4557 PyObject* item = NULL;
4558
4559 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4560 return NULL;
4561
4562 CHECK_ENV_NOT_CLOSED(self);
4563 MYDB_BEGIN_ALLOW_THREADS;
4564#if (DBVER >= 40)
4565 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4566#elif (DBVER == 33)
4567 err = log_archive(self->db_env, &log_list, flags);
4568#else
4569 err = log_archive(self->db_env, &log_list, flags, NULL);
4570#endif
4571 MYDB_END_ALLOW_THREADS;
4572 RETURN_IF_ERR();
4573
4574 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004575 if (list == NULL) {
4576 if (log_list)
4577 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004578 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004579 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004580
4581 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004582 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004583 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4584 item = PyString_FromString (*log_list);
4585 if (item == NULL) {
4586 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 list = NULL;
4588 break;
4589 }
4590 PyList_Append(list, item);
4591 Py_DECREF(item);
4592 }
4593 free(log_list_start);
4594 }
4595 return list;
4596}
4597
4598
4599static PyObject*
4600DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4601{
4602 int err;
4603 DB_TXN_STAT* sp;
4604 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004605 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606
4607 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4608 return NULL;
4609 CHECK_ENV_NOT_CLOSED(self);
4610
4611 MYDB_BEGIN_ALLOW_THREADS;
4612#if (DBVER >= 40)
4613 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4614#elif (DBVER == 33)
4615 err = txn_stat(self->db_env, &sp);
4616#else
4617 err = txn_stat(self->db_env, &sp, NULL);
4618#endif
4619 MYDB_END_ALLOW_THREADS;
4620 RETURN_IF_ERR();
4621
4622 /* Turn the stat structure into a dictionary */
4623 d = PyDict_New();
4624 if (d == NULL) {
4625 free(sp);
4626 return NULL;
4627 }
4628
4629#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4630
4631 MAKE_ENTRY(time_ckp);
4632 MAKE_ENTRY(last_txnid);
4633 MAKE_ENTRY(maxtxns);
4634 MAKE_ENTRY(nactive);
4635 MAKE_ENTRY(maxnactive);
4636 MAKE_ENTRY(nbegins);
4637 MAKE_ENTRY(naborts);
4638 MAKE_ENTRY(ncommits);
4639 MAKE_ENTRY(regsize);
4640 MAKE_ENTRY(region_wait);
4641 MAKE_ENTRY(region_nowait);
4642
4643#undef MAKE_ENTRY
4644 free(sp);
4645 return d;
4646}
4647
4648
4649static PyObject*
4650DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4651{
4652 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004653 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004654
4655 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4656 return NULL;
4657 CHECK_ENV_NOT_CLOSED(self);
4658
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004659 if (self->moduleFlags.getReturnsNone)
4660 ++oldValue;
4661 if (self->moduleFlags.cursorSetReturnsNone)
4662 ++oldValue;
4663 self->moduleFlags.getReturnsNone = (flags >= 1);
4664 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004665 return PyInt_FromLong(oldValue);
4666}
4667
4668
4669/* --------------------------------------------------------------------- */
4670/* DBTxn methods */
4671
4672
4673static PyObject*
4674DBTxn_commit(DBTxnObject* self, PyObject* args)
4675{
4676 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004677 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004678
4679 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4680 return NULL;
4681
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004682 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004683 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4684 "after txn_commit or txn_abort");
4685 PyErr_SetObject(DBError, t);
4686 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004687 return NULL;
4688 }
4689 txn = self->txn;
4690 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691 MYDB_BEGIN_ALLOW_THREADS;
4692#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004693 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004694#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004695 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004696#endif
4697 MYDB_END_ALLOW_THREADS;
4698 RETURN_IF_ERR();
4699 RETURN_NONE();
4700}
4701
4702static PyObject*
4703DBTxn_prepare(DBTxnObject* self, PyObject* args)
4704{
4705#if (DBVER >= 33)
4706 int err;
4707 char* gid=NULL;
4708 int gid_size=0;
4709
4710 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4711 return NULL;
4712
4713 if (gid_size != DB_XIDDATASIZE) {
4714 PyErr_SetString(PyExc_TypeError,
4715 "gid must be DB_XIDDATASIZE bytes long");
4716 return NULL;
4717 }
4718
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004719 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004720 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4721 "after txn_commit or txn_abort");
4722 PyErr_SetObject(DBError, t);
4723 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004724 return NULL;
4725 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004726 MYDB_BEGIN_ALLOW_THREADS;
4727#if (DBVER >= 40)
4728 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4729#else
4730 err = txn_prepare(self->txn, (u_int8_t*)gid);
4731#endif
4732 MYDB_END_ALLOW_THREADS;
4733 RETURN_IF_ERR();
4734 RETURN_NONE();
4735#else
4736 int err;
4737
4738 if (!PyArg_ParseTuple(args, ":prepare"))
4739 return NULL;
4740
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004741 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004742 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4743 "after txn_commit or txn_abort");
4744 PyErr_SetObject(DBError, t);
4745 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004746 return NULL;
4747 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004748 MYDB_BEGIN_ALLOW_THREADS;
4749 err = txn_prepare(self->txn);
4750 MYDB_END_ALLOW_THREADS;
4751 RETURN_IF_ERR();
4752 RETURN_NONE();
4753#endif
4754}
4755
4756
4757static PyObject*
4758DBTxn_abort(DBTxnObject* self, PyObject* args)
4759{
4760 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004761 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004762
4763 if (!PyArg_ParseTuple(args, ":abort"))
4764 return NULL;
4765
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004766 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004767 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4768 "after txn_commit or txn_abort");
4769 PyErr_SetObject(DBError, t);
4770 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004771 return NULL;
4772 }
4773 txn = self->txn;
4774 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004775 MYDB_BEGIN_ALLOW_THREADS;
4776#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004777 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004778#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004779 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004780#endif
4781 MYDB_END_ALLOW_THREADS;
4782 RETURN_IF_ERR();
4783 RETURN_NONE();
4784}
4785
4786
4787static PyObject*
4788DBTxn_id(DBTxnObject* self, PyObject* args)
4789{
4790 int id;
4791
4792 if (!PyArg_ParseTuple(args, ":id"))
4793 return NULL;
4794
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004795 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004796 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4797 "after txn_commit or txn_abort");
4798 PyErr_SetObject(DBError, t);
4799 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004800 return NULL;
4801 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004802 MYDB_BEGIN_ALLOW_THREADS;
4803#if (DBVER >= 40)
4804 id = self->txn->id(self->txn);
4805#else
4806 id = txn_id(self->txn);
4807#endif
4808 MYDB_END_ALLOW_THREADS;
4809 return PyInt_FromLong(id);
4810}
4811
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004812#if (DBVER >= 43)
4813/* --------------------------------------------------------------------- */
4814/* DBSequence methods */
4815
4816
4817static PyObject*
4818DBSequence_close(DBSequenceObject* self, PyObject* args)
4819{
4820 int err, flags=0;
4821 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4822 return NULL;
4823 CHECK_SEQUENCE_NOT_CLOSED(self)
4824
4825 MYDB_BEGIN_ALLOW_THREADS
4826 err = self->sequence->close(self->sequence, flags);
4827 self->sequence = NULL;
4828 MYDB_END_ALLOW_THREADS
4829
4830 RETURN_IF_ERR();
4831
4832 RETURN_NONE();
4833}
4834
4835static PyObject*
4836DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4837{
4838 int err, flags = 0;
4839 int delta = 1;
4840 db_seq_t value;
4841 PyObject *txnobj = NULL;
4842 DB_TXN *txn = NULL;
4843 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4844 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4845 return NULL;
4846 CHECK_SEQUENCE_NOT_CLOSED(self)
4847
4848 if (!checkTxnObj(txnobj, &txn))
4849 return NULL;
4850
4851 MYDB_BEGIN_ALLOW_THREADS
4852 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4853 MYDB_END_ALLOW_THREADS
4854
4855 RETURN_IF_ERR();
4856 return PyLong_FromLongLong(value);
4857
4858}
4859
4860static PyObject*
4861DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4862{
4863 if (!PyArg_ParseTuple(args,":get_dbp"))
4864 return NULL;
4865 CHECK_SEQUENCE_NOT_CLOSED(self)
4866 Py_INCREF(self->mydb);
4867 return (PyObject* )self->mydb;
4868}
4869
4870static PyObject*
4871DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4872{
4873 int err;
4874 DBT key;
4875 CHECK_SEQUENCE_NOT_CLOSED(self)
4876 MYDB_BEGIN_ALLOW_THREADS
4877 err = self->sequence->get_key(self->sequence, &key);
4878 MYDB_END_ALLOW_THREADS
4879
4880 RETURN_IF_ERR();
4881
4882 return PyString_FromStringAndSize(key.data, key.size);
4883}
4884
4885static PyObject*
4886DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4887{
4888 int err;
4889 db_seq_t value;
4890 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4891 return NULL;
4892 CHECK_SEQUENCE_NOT_CLOSED(self)
4893
4894 MYDB_BEGIN_ALLOW_THREADS
4895 err = self->sequence->initial_value(self->sequence, value);
4896 MYDB_END_ALLOW_THREADS
4897
4898 RETURN_IF_ERR();
4899
4900 RETURN_NONE();
4901}
4902
4903static PyObject*
4904DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4905{
4906 int err, flags = 0;
4907 PyObject* keyobj;
4908 PyObject *txnobj = NULL;
4909 DB_TXN *txn = NULL;
4910 DBT key;
4911
4912 static char* kwnames[] = {"key", "txn", "flags", NULL };
4913 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4914 return NULL;
4915
4916 if (!checkTxnObj(txnobj, &txn))
4917 return NULL;
4918
4919 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4920 return NULL;
4921
4922 MYDB_BEGIN_ALLOW_THREADS
4923 err = self->sequence->open(self->sequence, txn, &key, flags);
4924 MYDB_END_ALLOW_THREADS
4925
4926 CLEAR_DBT(key);
4927 RETURN_IF_ERR();
4928
4929 RETURN_NONE();
4930}
4931
4932static PyObject*
4933DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4934{
4935 int err, flags = 0;
4936 PyObject *txnobj = NULL;
4937 DB_TXN *txn = NULL;
4938
4939 static char* kwnames[] = {"txn", "flags", NULL };
4940 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4941 return NULL;
4942
4943 if (!checkTxnObj(txnobj, &txn))
4944 return NULL;
4945
4946 CHECK_SEQUENCE_NOT_CLOSED(self)
4947
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err = self->sequence->remove(self->sequence, txn, flags);
4950 MYDB_END_ALLOW_THREADS
4951
4952 RETURN_IF_ERR();
4953 RETURN_NONE();
4954}
4955
4956static PyObject*
4957DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4958{
4959 int err, size;
4960 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4961 return NULL;
4962 CHECK_SEQUENCE_NOT_CLOSED(self)
4963
4964 MYDB_BEGIN_ALLOW_THREADS
4965 err = self->sequence->set_cachesize(self->sequence, size);
4966 MYDB_END_ALLOW_THREADS
4967
4968 RETURN_IF_ERR();
4969 RETURN_NONE();
4970}
4971
4972static PyObject*
4973DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4974{
4975 int err, size;
4976 if (!PyArg_ParseTuple(args,":get_cachesize"))
4977 return NULL;
4978 CHECK_SEQUENCE_NOT_CLOSED(self)
4979
4980 MYDB_BEGIN_ALLOW_THREADS
4981 err = self->sequence->get_cachesize(self->sequence, &size);
4982 MYDB_END_ALLOW_THREADS
4983
4984 RETURN_IF_ERR();
4985 return PyInt_FromLong(size);
4986}
4987
4988static PyObject*
4989DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4990{
4991 int err, flags = 0;
4992 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4993 return NULL;
4994 CHECK_SEQUENCE_NOT_CLOSED(self)
4995
4996 MYDB_BEGIN_ALLOW_THREADS
4997 err = self->sequence->set_flags(self->sequence, flags);
4998 MYDB_END_ALLOW_THREADS
4999
5000 RETURN_IF_ERR();
5001 RETURN_NONE();
5002
5003}
5004
5005static PyObject*
5006DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5007{
5008 unsigned int flags;
5009 int err;
5010 if (!PyArg_ParseTuple(args,":get_flags"))
5011 return NULL;
5012 CHECK_SEQUENCE_NOT_CLOSED(self)
5013
5014 MYDB_BEGIN_ALLOW_THREADS
5015 err = self->sequence->get_flags(self->sequence, &flags);
5016 MYDB_END_ALLOW_THREADS
5017
5018 RETURN_IF_ERR();
5019 return PyInt_FromLong((int)flags);
5020}
5021
5022static PyObject*
5023DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5024{
5025 int err;
5026 db_seq_t min, max;
5027 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5028 return NULL;
5029 CHECK_SEQUENCE_NOT_CLOSED(self)
5030
5031 MYDB_BEGIN_ALLOW_THREADS
5032 err = self->sequence->set_range(self->sequence, min, max);
5033 MYDB_END_ALLOW_THREADS
5034
5035 RETURN_IF_ERR();
5036 RETURN_NONE();
5037}
5038
5039static PyObject*
5040DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5041{
5042 int err;
5043 db_seq_t min, max;
5044 if (!PyArg_ParseTuple(args,":get_range"))
5045 return NULL;
5046 CHECK_SEQUENCE_NOT_CLOSED(self)
5047
5048 MYDB_BEGIN_ALLOW_THREADS
5049 err = self->sequence->get_range(self->sequence, &min, &max);
5050 MYDB_END_ALLOW_THREADS
5051
5052 RETURN_IF_ERR();
5053 return Py_BuildValue("(LL)", min, max);
5054}
5055
5056static PyObject*
5057DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5058{
5059 int err, flags = 0;
5060 DB_SEQUENCE_STAT* sp = NULL;
5061 PyObject* dict_stat;
5062 static char* kwnames[] = {"flags", NULL };
5063 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5064 return NULL;
5065 CHECK_SEQUENCE_NOT_CLOSED(self);
5066
5067 MYDB_BEGIN_ALLOW_THREADS;
5068 err = self->sequence->stat(self->sequence, &sp, flags);
5069 MYDB_END_ALLOW_THREADS;
5070 RETURN_IF_ERR();
5071
5072 if ((dict_stat = PyDict_New()) == NULL) {
5073 free(sp);
5074 return NULL;
5075 }
5076
5077
5078#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5079#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5080
5081 MAKE_INT_ENTRY(wait);
5082 MAKE_INT_ENTRY(nowait);
5083 MAKE_LONG_LONG_ENTRY(current);
5084 MAKE_LONG_LONG_ENTRY(value);
5085 MAKE_LONG_LONG_ENTRY(last_value);
5086 MAKE_LONG_LONG_ENTRY(min);
5087 MAKE_LONG_LONG_ENTRY(max);
5088 MAKE_INT_ENTRY(cache_size);
5089 MAKE_INT_ENTRY(flags);
5090
5091#undef MAKE_INT_ENTRY
5092#undef MAKE_LONG_LONG_ENTRY
5093
5094 free(sp);
5095 return dict_stat;
5096}
5097#endif
5098
5099
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005100/* --------------------------------------------------------------------- */
5101/* Method definition tables and type objects */
5102
5103static PyMethodDef DB_methods[] = {
5104 {"append", (PyCFunction)DB_append, METH_VARARGS},
5105#if (DBVER >= 33)
5106 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5107#endif
5108 {"close", (PyCFunction)DB_close, METH_VARARGS},
5109#if (DBVER >= 32)
5110 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5111 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5112#endif
5113 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5114 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5115 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5116 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005117#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005118 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005119#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005120 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5121 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5122 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5123 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5124 {"join", (PyCFunction)DB_join, METH_VARARGS},
5125 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5126 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5127 {"items", (PyCFunction)DB_items, METH_VARARGS},
5128 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5129 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5130 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5131 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5132 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5133 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005134#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005135 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005136#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005137 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005138#if (DBVER >= 41)
5139 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5140#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005141 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5142 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5143 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5144 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5145 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5146 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5147 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5148 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5149 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5150#if (DBVER >= 32)
5151 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5152#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005153 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5155#if (DBVER >= 33)
5156 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5157#endif
5158 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5159 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5160 {"values", (PyCFunction)DB_values, METH_VARARGS},
5161 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5162 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5163 {NULL, NULL} /* sentinel */
5164};
5165
5166
5167static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005168 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005169 (binaryfunc)DB_subscript, /*mp_subscript*/
5170 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5171};
5172
5173
5174static PyMethodDef DBCursor_methods[] = {
5175 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5176 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5177 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5178 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5179 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5180 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5181 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005182#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005183 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005184#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005185 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5186 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5187 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5188 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5189 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5190 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5191 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5192 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005193 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005194 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005195 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5196 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5197 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5198 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5199 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5200 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5201 {NULL, NULL} /* sentinel */
5202};
5203
5204
5205static PyMethodDef DBEnv_methods[] = {
5206 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5207 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5208 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005209#if (DBVER >= 41)
5210 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5211 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5212 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5213#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005214#if (DBVER >= 40)
5215 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5216#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005217 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5219 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5220#if (DBVER >= 32)
5221 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5222#endif
5223 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5224 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5225 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005226#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005227 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005228#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005229 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5230 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5231#if (DBVER >= 32)
5232 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5233 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5234 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5235#endif
5236 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5237 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5238 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5239 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5240 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5241 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005242 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005243 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5244 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5245 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5246 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5247 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5248 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005249#if (DBVER >= 40)
5250 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5251#endif
5252#if (DBVER >= 44)
5253 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5254#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005255 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5256 {NULL, NULL} /* sentinel */
5257};
5258
5259
5260static PyMethodDef DBTxn_methods[] = {
5261 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5262 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5263 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5264 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5265 {NULL, NULL} /* sentinel */
5266};
5267
5268
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005269#if (DBVER >= 43)
5270static PyMethodDef DBSequence_methods[] = {
5271 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5272 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5273 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5274 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5275 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5276 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5277 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5278 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5279 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5280 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5281 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5282 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5283 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5284 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5285 {NULL, NULL} /* sentinel */
5286};
5287#endif
5288
5289
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005290static PyObject*
5291DB_getattr(DBObject* self, char *name)
5292{
5293 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5294}
5295
5296
5297static PyObject*
5298DBEnv_getattr(DBEnvObject* self, char *name)
5299{
5300 if (!strcmp(name, "db_home")) {
5301 CHECK_ENV_NOT_CLOSED(self);
5302 if (self->db_env->db_home == NULL) {
5303 RETURN_NONE();
5304 }
5305 return PyString_FromString(self->db_env->db_home);
5306 }
5307
5308 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5309}
5310
5311
5312static PyObject*
5313DBCursor_getattr(DBCursorObject* self, char *name)
5314{
5315 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5316}
5317
5318static PyObject*
5319DBTxn_getattr(DBTxnObject* self, char *name)
5320{
5321 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5322}
5323
5324static PyObject*
5325DBLock_getattr(DBLockObject* self, char *name)
5326{
5327 return NULL;
5328}
5329
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005330#if (DBVER >= 43)
5331static PyObject*
5332DBSequence_getattr(DBSequenceObject* self, char *name)
5333{
5334 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5335}
5336#endif
5337
Neal Norwitz227b5332006-03-22 09:28:35 +00005338static PyTypeObject DB_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005339 PyObject_HEAD_INIT(NULL)
5340 0, /*ob_size*/
5341 "DB", /*tp_name*/
5342 sizeof(DBObject), /*tp_basicsize*/
5343 0, /*tp_itemsize*/
5344 /* methods */
5345 (destructor)DB_dealloc, /*tp_dealloc*/
5346 0, /*tp_print*/
5347 (getattrfunc)DB_getattr, /*tp_getattr*/
5348 0, /*tp_setattr*/
5349 0, /*tp_compare*/
5350 0, /*tp_repr*/
5351 0, /*tp_as_number*/
5352 0, /*tp_as_sequence*/
5353 &DB_mapping,/*tp_as_mapping*/
5354 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005355#ifdef HAVE_WEAKREF
5356 0, /* tp_call */
5357 0, /* tp_str */
5358 0, /* tp_getattro */
5359 0, /* tp_setattro */
5360 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005361 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005362 0, /* tp_doc */
5363 0, /* tp_traverse */
5364 0, /* tp_clear */
5365 0, /* tp_richcompare */
5366 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5367#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005368};
5369
5370
Neal Norwitz227b5332006-03-22 09:28:35 +00005371static PyTypeObject DBCursor_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005372 PyObject_HEAD_INIT(NULL)
5373 0, /*ob_size*/
5374 "DBCursor", /*tp_name*/
5375 sizeof(DBCursorObject), /*tp_basicsize*/
5376 0, /*tp_itemsize*/
5377 /* methods */
5378 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5379 0, /*tp_print*/
5380 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5381 0, /*tp_setattr*/
5382 0, /*tp_compare*/
5383 0, /*tp_repr*/
5384 0, /*tp_as_number*/
5385 0, /*tp_as_sequence*/
5386 0, /*tp_as_mapping*/
5387 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005388#ifdef HAVE_WEAKREF
5389 0, /* tp_call */
5390 0, /* tp_str */
5391 0, /* tp_getattro */
5392 0, /* tp_setattro */
5393 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005394 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005395 0, /* tp_doc */
5396 0, /* tp_traverse */
5397 0, /* tp_clear */
5398 0, /* tp_richcompare */
5399 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5400#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005401};
5402
5403
Neal Norwitz227b5332006-03-22 09:28:35 +00005404static PyTypeObject DBEnv_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005405 PyObject_HEAD_INIT(NULL)
5406 0, /*ob_size*/
5407 "DBEnv", /*tp_name*/
5408 sizeof(DBEnvObject), /*tp_basicsize*/
5409 0, /*tp_itemsize*/
5410 /* methods */
5411 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5412 0, /*tp_print*/
5413 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5414 0, /*tp_setattr*/
5415 0, /*tp_compare*/
5416 0, /*tp_repr*/
5417 0, /*tp_as_number*/
5418 0, /*tp_as_sequence*/
5419 0, /*tp_as_mapping*/
5420 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005421#ifdef HAVE_WEAKREF
5422 0, /* tp_call */
5423 0, /* tp_str */
5424 0, /* tp_getattro */
5425 0, /* tp_setattro */
5426 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005427 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005428 0, /* tp_doc */
5429 0, /* tp_traverse */
5430 0, /* tp_clear */
5431 0, /* tp_richcompare */
5432 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5433#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434};
5435
Neal Norwitz227b5332006-03-22 09:28:35 +00005436static PyTypeObject DBTxn_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005437 PyObject_HEAD_INIT(NULL)
5438 0, /*ob_size*/
5439 "DBTxn", /*tp_name*/
5440 sizeof(DBTxnObject), /*tp_basicsize*/
5441 0, /*tp_itemsize*/
5442 /* methods */
5443 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5444 0, /*tp_print*/
5445 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5446 0, /*tp_setattr*/
5447 0, /*tp_compare*/
5448 0, /*tp_repr*/
5449 0, /*tp_as_number*/
5450 0, /*tp_as_sequence*/
5451 0, /*tp_as_mapping*/
5452 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005453#ifdef HAVE_WEAKREF
5454 0, /* tp_call */
5455 0, /* tp_str */
5456 0, /* tp_getattro */
5457 0, /* tp_setattro */
5458 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005459 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005460 0, /* tp_doc */
5461 0, /* tp_traverse */
5462 0, /* tp_clear */
5463 0, /* tp_richcompare */
5464 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5465#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005466};
5467
5468
Neal Norwitz227b5332006-03-22 09:28:35 +00005469static PyTypeObject DBLock_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005470 PyObject_HEAD_INIT(NULL)
5471 0, /*ob_size*/
5472 "DBLock", /*tp_name*/
5473 sizeof(DBLockObject), /*tp_basicsize*/
5474 0, /*tp_itemsize*/
5475 /* methods */
5476 (destructor)DBLock_dealloc, /*tp_dealloc*/
5477 0, /*tp_print*/
5478 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5479 0, /*tp_setattr*/
5480 0, /*tp_compare*/
5481 0, /*tp_repr*/
5482 0, /*tp_as_number*/
5483 0, /*tp_as_sequence*/
5484 0, /*tp_as_mapping*/
5485 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005486#ifdef HAVE_WEAKREF
5487 0, /* tp_call */
5488 0, /* tp_str */
5489 0, /* tp_getattro */
5490 0, /* tp_setattro */
5491 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005492 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005493 0, /* tp_doc */
5494 0, /* tp_traverse */
5495 0, /* tp_clear */
5496 0, /* tp_richcompare */
5497 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499};
5500
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005501#if (DBVER >= 43)
5502static PyTypeObject DBSequence_Type = {
5503 PyObject_HEAD_INIT(NULL)
5504 0, /*ob_size*/
5505 "DBSequence", /*tp_name*/
5506 sizeof(DBSequenceObject), /*tp_basicsize*/
5507 0, /*tp_itemsize*/
5508 /* methods */
5509 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5510 0, /*tp_print*/
5511 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5512 0, /*tp_setattr*/
5513 0, /*tp_compare*/
5514 0, /*tp_repr*/
5515 0, /*tp_as_number*/
5516 0, /*tp_as_sequence*/
5517 0, /*tp_as_mapping*/
5518 0, /*tp_hash*/
5519#ifdef HAVE_WEAKREF
5520 0, /* tp_call */
5521 0, /* tp_str */
5522 0, /* tp_getattro */
5523 0, /* tp_setattro */
5524 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005525 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005526 0, /* tp_doc */
5527 0, /* tp_traverse */
5528 0, /* tp_clear */
5529 0, /* tp_richcompare */
5530 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5531#endif
5532};
5533#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005534
5535/* --------------------------------------------------------------------- */
5536/* Module-level functions */
5537
5538static PyObject*
5539DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5540{
5541 PyObject* dbenvobj = NULL;
5542 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005543 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005544
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005545 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5546 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005547 return NULL;
5548 if (dbenvobj == Py_None)
5549 dbenvobj = NULL;
5550 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5551 makeTypeError("DBEnv", dbenvobj);
5552 return NULL;
5553 }
5554
5555 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5556}
5557
5558
5559static PyObject*
5560DBEnv_construct(PyObject* self, PyObject* args)
5561{
5562 int flags = 0;
5563 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5564 return (PyObject* )newDBEnvObject(flags);
5565}
5566
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005567#if (DBVER >= 43)
5568static PyObject*
5569DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5570{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005571 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005572 int flags = 0;
5573 static char* kwnames[] = { "db", "flags", NULL};
5574
5575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5576 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005577 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005578 makeTypeError("DB", dbobj);
5579 return NULL;
5580 }
5581 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5582}
5583#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005584
5585static char bsddb_version_doc[] =
5586"Returns a tuple of major, minor, and patch release numbers of the\n\
5587underlying DB library.";
5588
5589static PyObject*
5590bsddb_version(PyObject* self, PyObject* args)
5591{
5592 int major, minor, patch;
5593
5594 if (!PyArg_ParseTuple(args, ":version"))
5595 return NULL;
5596 db_version(&major, &minor, &patch);
5597 return Py_BuildValue("(iii)", major, minor, patch);
5598}
5599
5600
5601/* List of functions defined in the module */
5602
5603static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005604 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5605 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5606#if (DBVER >= 43)
5607 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5608#endif
5609 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005610 {NULL, NULL} /* sentinel */
5611};
5612
5613
5614/* --------------------------------------------------------------------- */
5615/* Module initialization */
5616
5617
5618/* Convenience routine to export an integer value.
5619 * Errors are silently ignored, for better or for worse...
5620 */
5621#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5622
Gregory P. Smith41631e82003-09-21 00:08:14 +00005623#define MODULE_NAME_MAX_LEN 11
5624static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005625
5626DL_EXPORT(void) init_bsddb(void)
5627{
5628 PyObject* m;
5629 PyObject* d;
5630 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5631 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5632 PyObject* cvsid_s = PyString_FromString( rcs_id );
5633
5634 /* Initialize the type of the new type objects here; doing it here
5635 is required for portability to Windows without requiring C++. */
5636 DB_Type.ob_type = &PyType_Type;
5637 DBCursor_Type.ob_type = &PyType_Type;
5638 DBEnv_Type.ob_type = &PyType_Type;
5639 DBTxn_Type.ob_type = &PyType_Type;
5640 DBLock_Type.ob_type = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005641#if (DBVER >= 43)
5642 DBSequence_Type.ob_type = &PyType_Type;
5643#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644
5645
Mark Hammonda69d4092003-04-22 23:13:27 +00005646#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005648 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649#endif
5650
5651 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005652 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005653 if (m == NULL)
5654 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005655
5656 /* Add some symbolic constants to the module */
5657 d = PyModule_GetDict(m);
5658 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5659 PyDict_SetItemString(d, "cvsid", cvsid_s);
5660 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5661 Py_DECREF(pybsddb_version_s);
5662 pybsddb_version_s = NULL;
5663 Py_DECREF(cvsid_s);
5664 cvsid_s = NULL;
5665 Py_DECREF(db_version_s);
5666 db_version_s = NULL;
5667
5668 ADD_INT(d, DB_VERSION_MAJOR);
5669 ADD_INT(d, DB_VERSION_MINOR);
5670 ADD_INT(d, DB_VERSION_PATCH);
5671
5672 ADD_INT(d, DB_MAX_PAGES);
5673 ADD_INT(d, DB_MAX_RECORDS);
5674
Gregory P. Smith41631e82003-09-21 00:08:14 +00005675#if (DBVER >= 42)
5676 ADD_INT(d, DB_RPCCLIENT);
5677#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005679 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5680 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5681#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682 ADD_INT(d, DB_XA_CREATE);
5683
5684 ADD_INT(d, DB_CREATE);
5685 ADD_INT(d, DB_NOMMAP);
5686 ADD_INT(d, DB_THREAD);
5687
5688 ADD_INT(d, DB_FORCE);
5689 ADD_INT(d, DB_INIT_CDB);
5690 ADD_INT(d, DB_INIT_LOCK);
5691 ADD_INT(d, DB_INIT_LOG);
5692 ADD_INT(d, DB_INIT_MPOOL);
5693 ADD_INT(d, DB_INIT_TXN);
5694#if (DBVER >= 32)
5695 ADD_INT(d, DB_JOINENV);
5696#endif
5697
5698 ADD_INT(d, DB_RECOVER);
5699 ADD_INT(d, DB_RECOVER_FATAL);
5700 ADD_INT(d, DB_TXN_NOSYNC);
5701 ADD_INT(d, DB_USE_ENVIRON);
5702 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5703
5704 ADD_INT(d, DB_LOCKDOWN);
5705 ADD_INT(d, DB_PRIVATE);
5706 ADD_INT(d, DB_SYSTEM_MEM);
5707
5708 ADD_INT(d, DB_TXN_SYNC);
5709 ADD_INT(d, DB_TXN_NOWAIT);
5710
5711 ADD_INT(d, DB_EXCL);
5712 ADD_INT(d, DB_FCNTL_LOCKING);
5713 ADD_INT(d, DB_ODDFILESIZE);
5714 ADD_INT(d, DB_RDWRMASTER);
5715 ADD_INT(d, DB_RDONLY);
5716 ADD_INT(d, DB_TRUNCATE);
5717#if (DBVER >= 32)
5718 ADD_INT(d, DB_EXTENT);
5719 ADD_INT(d, DB_CDB_ALLDB);
5720 ADD_INT(d, DB_VERIFY);
5721#endif
5722 ADD_INT(d, DB_UPGRADE);
5723
5724 ADD_INT(d, DB_AGGRESSIVE);
5725 ADD_INT(d, DB_NOORDERCHK);
5726 ADD_INT(d, DB_ORDERCHKONLY);
5727 ADD_INT(d, DB_PR_PAGE);
5728#if ! (DBVER >= 33)
5729 ADD_INT(d, DB_VRFY_FLAGMASK);
5730 ADD_INT(d, DB_PR_HEADERS);
5731#endif
5732 ADD_INT(d, DB_PR_RECOVERYTEST);
5733 ADD_INT(d, DB_SALVAGE);
5734
5735 ADD_INT(d, DB_LOCK_NORUN);
5736 ADD_INT(d, DB_LOCK_DEFAULT);
5737 ADD_INT(d, DB_LOCK_OLDEST);
5738 ADD_INT(d, DB_LOCK_RANDOM);
5739 ADD_INT(d, DB_LOCK_YOUNGEST);
5740#if (DBVER >= 33)
5741 ADD_INT(d, DB_LOCK_MAXLOCKS);
5742 ADD_INT(d, DB_LOCK_MINLOCKS);
5743 ADD_INT(d, DB_LOCK_MINWRITE);
5744#endif
5745
5746
5747#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005748 /* docs say to use zero instead */
5749 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005750#else
5751 ADD_INT(d, DB_LOCK_CONFLICT);
5752#endif
5753
5754 ADD_INT(d, DB_LOCK_DUMP);
5755 ADD_INT(d, DB_LOCK_GET);
5756 ADD_INT(d, DB_LOCK_INHERIT);
5757 ADD_INT(d, DB_LOCK_PUT);
5758 ADD_INT(d, DB_LOCK_PUT_ALL);
5759 ADD_INT(d, DB_LOCK_PUT_OBJ);
5760
5761 ADD_INT(d, DB_LOCK_NG);
5762 ADD_INT(d, DB_LOCK_READ);
5763 ADD_INT(d, DB_LOCK_WRITE);
5764 ADD_INT(d, DB_LOCK_NOWAIT);
5765#if (DBVER >= 32)
5766 ADD_INT(d, DB_LOCK_WAIT);
5767#endif
5768 ADD_INT(d, DB_LOCK_IWRITE);
5769 ADD_INT(d, DB_LOCK_IREAD);
5770 ADD_INT(d, DB_LOCK_IWR);
5771#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005772#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005773 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005774#else
5775 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5776#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005777 ADD_INT(d, DB_LOCK_WWRITE);
5778#endif
5779
5780 ADD_INT(d, DB_LOCK_RECORD);
5781 ADD_INT(d, DB_LOCK_UPGRADE);
5782#if (DBVER >= 32)
5783 ADD_INT(d, DB_LOCK_SWITCH);
5784#endif
5785#if (DBVER >= 33)
5786 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5787#endif
5788
5789 ADD_INT(d, DB_LOCK_NOWAIT);
5790 ADD_INT(d, DB_LOCK_RECORD);
5791 ADD_INT(d, DB_LOCK_UPGRADE);
5792
5793#if (DBVER >= 33)
5794 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005795#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005797#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005798 ADD_INT(d, DB_LSTAT_FREE);
5799 ADD_INT(d, DB_LSTAT_HELD);
5800#if (DBVER == 33)
5801 ADD_INT(d, DB_LSTAT_NOGRANT);
5802#endif
5803 ADD_INT(d, DB_LSTAT_PENDING);
5804 ADD_INT(d, DB_LSTAT_WAITING);
5805#endif
5806
5807 ADD_INT(d, DB_ARCH_ABS);
5808 ADD_INT(d, DB_ARCH_DATA);
5809 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005810#if (DBVER >= 42)
5811 ADD_INT(d, DB_ARCH_REMOVE);
5812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005813
5814 ADD_INT(d, DB_BTREE);
5815 ADD_INT(d, DB_HASH);
5816 ADD_INT(d, DB_RECNO);
5817 ADD_INT(d, DB_QUEUE);
5818 ADD_INT(d, DB_UNKNOWN);
5819
5820 ADD_INT(d, DB_DUP);
5821 ADD_INT(d, DB_DUPSORT);
5822 ADD_INT(d, DB_RECNUM);
5823 ADD_INT(d, DB_RENUMBER);
5824 ADD_INT(d, DB_REVSPLITOFF);
5825 ADD_INT(d, DB_SNAPSHOT);
5826
5827 ADD_INT(d, DB_JOIN_NOSORT);
5828
5829 ADD_INT(d, DB_AFTER);
5830 ADD_INT(d, DB_APPEND);
5831 ADD_INT(d, DB_BEFORE);
5832 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005833#if (DBVER >= 41)
5834 _addIntToDict(d, "DB_CHECKPOINT", 0);
5835#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005836 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005837 ADD_INT(d, DB_CURLSN);
5838#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005839#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005840 ADD_INT(d, DB_COMMIT);
5841#endif
5842 ADD_INT(d, DB_CONSUME);
5843#if (DBVER >= 32)
5844 ADD_INT(d, DB_CONSUME_WAIT);
5845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846 ADD_INT(d, DB_CURRENT);
5847#if (DBVER >= 33)
5848 ADD_INT(d, DB_FAST_STAT);
5849#endif
5850 ADD_INT(d, DB_FIRST);
5851 ADD_INT(d, DB_FLUSH);
5852 ADD_INT(d, DB_GET_BOTH);
5853 ADD_INT(d, DB_GET_RECNO);
5854 ADD_INT(d, DB_JOIN_ITEM);
5855 ADD_INT(d, DB_KEYFIRST);
5856 ADD_INT(d, DB_KEYLAST);
5857 ADD_INT(d, DB_LAST);
5858 ADD_INT(d, DB_NEXT);
5859 ADD_INT(d, DB_NEXT_DUP);
5860 ADD_INT(d, DB_NEXT_NODUP);
5861 ADD_INT(d, DB_NODUPDATA);
5862 ADD_INT(d, DB_NOOVERWRITE);
5863 ADD_INT(d, DB_NOSYNC);
5864 ADD_INT(d, DB_POSITION);
5865 ADD_INT(d, DB_PREV);
5866 ADD_INT(d, DB_PREV_NODUP);
5867 ADD_INT(d, DB_RECORDCOUNT);
5868 ADD_INT(d, DB_SET);
5869 ADD_INT(d, DB_SET_RANGE);
5870 ADD_INT(d, DB_SET_RECNO);
5871 ADD_INT(d, DB_WRITECURSOR);
5872
5873 ADD_INT(d, DB_OPFLAGS_MASK);
5874 ADD_INT(d, DB_RMW);
5875#if (DBVER >= 33)
5876 ADD_INT(d, DB_DIRTY_READ);
5877 ADD_INT(d, DB_MULTIPLE);
5878 ADD_INT(d, DB_MULTIPLE_KEY);
5879#endif
5880
Gregory P. Smith29602d22006-01-24 09:46:48 +00005881#if (DBVER >= 44)
5882 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5883 ADD_INT(d, DB_READ_COMMITTED);
5884#endif
5885
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005886#if (DBVER >= 33)
5887 ADD_INT(d, DB_DONOTINDEX);
5888#endif
5889
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005890#if (DBVER >= 41)
5891 _addIntToDict(d, "DB_INCOMPLETE", 0);
5892#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005893 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005894#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005895 ADD_INT(d, DB_KEYEMPTY);
5896 ADD_INT(d, DB_KEYEXIST);
5897 ADD_INT(d, DB_LOCK_DEADLOCK);
5898 ADD_INT(d, DB_LOCK_NOTGRANTED);
5899 ADD_INT(d, DB_NOSERVER);
5900 ADD_INT(d, DB_NOSERVER_HOME);
5901 ADD_INT(d, DB_NOSERVER_ID);
5902 ADD_INT(d, DB_NOTFOUND);
5903 ADD_INT(d, DB_OLD_VERSION);
5904 ADD_INT(d, DB_RUNRECOVERY);
5905 ADD_INT(d, DB_VERIFY_BAD);
5906#if (DBVER >= 33)
5907 ADD_INT(d, DB_PAGE_NOTFOUND);
5908 ADD_INT(d, DB_SECONDARY_BAD);
5909#endif
5910#if (DBVER >= 40)
5911 ADD_INT(d, DB_STAT_CLEAR);
5912 ADD_INT(d, DB_REGION_INIT);
5913 ADD_INT(d, DB_NOLOCKING);
5914 ADD_INT(d, DB_YIELDCPU);
5915 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5916 ADD_INT(d, DB_NOPANIC);
5917#endif
5918
Gregory P. Smith41631e82003-09-21 00:08:14 +00005919#if (DBVER >= 42)
5920 ADD_INT(d, DB_TIME_NOTGRANTED);
5921 ADD_INT(d, DB_TXN_NOT_DURABLE);
5922 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5923 ADD_INT(d, DB_LOG_AUTOREMOVE);
5924 ADD_INT(d, DB_DIRECT_LOG);
5925 ADD_INT(d, DB_DIRECT_DB);
5926 ADD_INT(d, DB_INIT_REP);
5927 ADD_INT(d, DB_ENCRYPT);
5928 ADD_INT(d, DB_CHKSUM);
5929#endif
5930
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005931#if (DBVER >= 43)
5932 ADD_INT(d, DB_LOG_INMEMORY);
5933 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005934 ADD_INT(d, DB_SEQ_DEC);
5935 ADD_INT(d, DB_SEQ_INC);
5936 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005937#endif
5938
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005939#if (DBVER >= 41)
5940 ADD_INT(d, DB_ENCRYPT_AES);
5941 ADD_INT(d, DB_AUTO_COMMIT);
5942#else
5943 /* allow berkeleydb 4.1 aware apps to run on older versions */
5944 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5945#endif
5946
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005947 ADD_INT(d, EINVAL);
5948 ADD_INT(d, EACCES);
5949 ADD_INT(d, ENOSPC);
5950 ADD_INT(d, ENOMEM);
5951 ADD_INT(d, EAGAIN);
5952 ADD_INT(d, EBUSY);
5953 ADD_INT(d, EEXIST);
5954 ADD_INT(d, ENOENT);
5955 ADD_INT(d, EPERM);
5956
Barry Warsaw1baa9822003-03-31 19:51:29 +00005957#if (DBVER >= 40)
5958 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5959 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5960#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005961
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005962 /* The exception name must be correct for pickled exception *
5963 * objects to unpickle properly. */
5964#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5965#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5966#else
5967#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5968#endif
5969
5970 /* All the rest of the exceptions derive only from DBError */
5971#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5972 PyDict_SetItemString(d, #name, name)
5973
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005974 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005975 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5976 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005977
Gregory P. Smithe9477062005-06-04 06:46:59 +00005978 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5979 * from both DBError and KeyError, since the API only supports
5980 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005982 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5983 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984 Py_file_input, d, d);
5985 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005986 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005987 PyDict_DelItemString(d, "KeyError");
5988
5989
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005990#if !INCOMPLETE_IS_WARNING
5991 MAKE_EX(DBIncompleteError);
5992#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005993 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005994 MAKE_EX(DBKeyEmptyError);
5995 MAKE_EX(DBKeyExistError);
5996 MAKE_EX(DBLockDeadlockError);
5997 MAKE_EX(DBLockNotGrantedError);
5998 MAKE_EX(DBOldVersionError);
5999 MAKE_EX(DBRunRecoveryError);
6000 MAKE_EX(DBVerifyBadError);
6001 MAKE_EX(DBNoServerError);
6002 MAKE_EX(DBNoServerHomeError);
6003 MAKE_EX(DBNoServerIDError);
6004#if (DBVER >= 33)
6005 MAKE_EX(DBPageNotFoundError);
6006 MAKE_EX(DBSecondaryBadError);
6007#endif
6008
6009 MAKE_EX(DBInvalidArgError);
6010 MAKE_EX(DBAccessError);
6011 MAKE_EX(DBNoSpaceError);
6012 MAKE_EX(DBNoMemoryError);
6013 MAKE_EX(DBAgainError);
6014 MAKE_EX(DBBusyError);
6015 MAKE_EX(DBFileExistsError);
6016 MAKE_EX(DBNoSuchFileError);
6017 MAKE_EX(DBPermissionsError);
6018
6019#undef MAKE_EX
6020
6021 /* Check for errors */
6022 if (PyErr_Occurred()) {
6023 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006024 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006025 }
6026}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006027
6028/* allow this module to be named _pybsddb so that it can be installed
6029 * and imported on top of python >= 2.3 that includes its own older
6030 * copy of the library named _bsddb without importing the old version. */
6031DL_EXPORT(void) init_pybsddb(void)
6032{
6033 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6034 init_bsddb();
6035}