blob: e7613fb315982952ffd2193886dd31fb47daa52a [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith1a050f52007-01-05 02:09:06 +0000101#define PY_BSDDB_VERSION "4.4.5.2"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000547 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000548#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000559#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000603 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
Gregory P. Smithe9477062005-06-04 06:46:59 +0000706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000752#if (DBVER >= 43)
753/* add an db_seq_t to a dictionary using the given name as a key */
754static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
755{
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000760 Py_XDECREF(v);
761}
762#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763
764
765
766/* --------------------------------------------------------------------- */
767/* Allocators and deallocators */
768
769static DBObject*
770newDBObject(DBEnvObject* arg, int flags)
771{
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
775
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (self == NULL)
778 return NULL;
779
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784#if (DBVER >= 33)
785 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000786 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 self->primaryDBType = 0;
788#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000789#ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
798 }
799
800 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000801 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000811 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000813 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000817 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
822 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000823 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824 self = NULL;
825 }
826 return self;
827}
828
829
830static void
831DB_dealloc(DBObject* self)
832{
833 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000837 (self->myenvobj && self->myenvobj->db_env))
838 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000842#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846#endif
847 }
848 self->db = NULL;
849 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000850#ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
853 }
854#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
858 }
859#if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
863 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
867 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870}
871
872
873static DBCursorObject*
874newDBCursorObject(DBC* dbc, DBObject* db)
875{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 if (self == NULL)
878 return NULL;
879
880 self->dbc = dbc;
881 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000882#ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 Py_INCREF(self->mydb);
886 return self;
887}
888
889
890static void
891DBCursor_dealloc(DBCursorObject* self)
892{
893 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000894
895#ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
898 }
899#endif
900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000911 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
914 }
915 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917}
918
919
920static DBEnvObject*
921newDBEnvObject(int flags)
922{
923 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925 if (self == NULL)
926 return NULL;
927
928 self->closed = 1;
929 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000932#ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000940 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 self = NULL;
942 }
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
945 }
946 return self;
947}
948
949
950static void
951DBEnv_dealloc(DBEnvObject* self)
952{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953#ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
956 }
957#endif
958
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000959 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
963 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965}
966
967
968static DBTxnObject*
969newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
970{
971 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000973 if (self == NULL)
974 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000977#ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980
981 MYDB_BEGIN_ALLOW_THREADS;
982#if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984#else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000989 Py_DECREF(self->env);
990 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 self = NULL;
992 }
993 return self;
994}
995
996
997static void
998DBTxn_dealloc(DBTxnObject* self)
999{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000#ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1003 }
1004#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005
Gregory P. Smith31c50652004-06-28 01:20:40 +00001006#ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010#if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012#else
1013 txn_abort(self->txn);
1014#endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1018 }
1019#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020
Neal Norwitz62a21122006-01-25 05:21:55 +00001021 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023}
1024
1025
1026static DBLockObject*
1027newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1029{
1030 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032 if (self == NULL)
1033 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001034#ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037
1038 MYDB_BEGIN_ALLOW_THREADS;
1039#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001042#else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044#endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001047 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001048 self = NULL;
1049 }
1050
1051 return self;
1052}
1053
1054
1055static void
1056DBLock_dealloc(DBLockObject* self)
1057{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001058#ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1061 }
1062#endif
1063 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001066}
1067
1068
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001069#if (DBVER >= 43)
1070static DBSequenceObject*
1071newDBSequenceObject(DBObject* mydb, int flags)
1072{
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079#ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081#endif
1082
1083
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1091 }
1092
1093 return self;
1094}
1095
1096
1097static void
1098DBSequence_dealloc(DBSequenceObject* self)
1099{
1100#ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1103 }
1104#endif
1105
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108}
1109#endif
1110
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111/* --------------------------------------------------------------------- */
1112/* DB methods */
1113
1114static PyObject*
1115DB_append(DBObject* self, PyObject* args)
1116{
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1122
Georg Brandl96a8c392006-05-29 21:04:52 +00001123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001124 return NULL;
1125
1126 CHECK_DB_NOT_CLOSED(self);
1127
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1135
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1138
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1141
1142 return PyInt_FromLong(recno);
1143}
1144
1145
1146#if (DBVER >= 33)
1147
1148static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151{
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001156 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001157 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001158
1159
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1162
Thomas Woutersb3153832006-03-08 01:47:19 +00001163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001169 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001170 result = PyEval_CallObject(callback, args);
1171 }
1172 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 PyErr_Print();
1174 }
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1177 }
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1180 }
1181 else if (PyString_Check(result)) {
1182 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001183 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184
1185 CLEAR_DBT(*secKey);
1186#if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190#else
1191 PyString_AsStringAndSize(result, &data, &size);
1192#endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1199 }
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1204 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 }
1206 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 PyErr_Print();
1211 }
1212
Thomas Woutersb3153832006-03-08 01:47:19 +00001213 Py_XDECREF(args);
1214 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001215
1216 MYDB_END_BLOCK_THREADS;
1217 }
1218 return retval;
1219}
1220
1221
1222static PyObject*
1223DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1224{
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001232 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001233#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237#if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001243 &secondaryDB, &callback, &flags)) {
1244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246 }
1247
1248#if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1256 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001257 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 if (callback == Py_None) {
1259 callback = NULL;
1260 }
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1264 }
1265
1266 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001267 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001268 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1271
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1281 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001282#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001283 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001284#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001286#if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001297#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 MYDB_END_ALLOW_THREADS;
1299
1300 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 secondaryDB->primaryDBType = 0;
1304 }
1305
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1308}
1309
1310
1311#endif
1312
1313
1314static PyObject*
1315DB_close(DBObject* self, PyObject* args)
1316{
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001324 self->db = NULL;
1325 RETURN_IF_ERR();
1326 }
1327 RETURN_NONE();
1328}
1329
1330
1331#if (DBVER >= 32)
1332static PyObject*
1333_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1334{
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001340 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1345
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001353 return NULL;
1354 }
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1357
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1364 }
1365
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1369
Gregory P. Smithe9477062005-06-04 06:46:59 +00001370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1375 }
1376 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001379 FREE_DBT(key);
1380 FREE_DBT(data);
1381 }
1382
1383 RETURN_IF_ERR();
1384 return retval;
1385}
1386
1387static PyObject*
1388DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1389{
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1391}
1392
1393static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001394DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396{
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1398}
1399#endif
1400
1401
1402
1403static PyObject*
1404DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1405{
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001410 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1418
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1424}
1425
1426
1427static PyObject*
1428DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1429{
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001435 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001446 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001447
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001452
1453 FREE_DBT(key);
1454 RETURN_NONE();
1455}
1456
1457
1458static PyObject*
1459DB_fd(DBObject* self, PyObject* args)
1460{
1461 int err, the_fd;
1462
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1472}
1473
1474
1475static PyObject*
1476DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1477{
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001488 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493 return NULL;
1494
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001500 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1507 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001511 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1516
Gregory P. Smithe9477062005-06-04 06:46:59 +00001517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1521 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1527 }
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 FREE_DBT(data);
1535 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001536 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001537
1538 RETURN_IF_ERR();
1539 return retval;
1540}
1541
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001542#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001543static PyObject*
1544DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1545{
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001556 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001557
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1562
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1569 }
1570
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1575 }
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1579 }
1580
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1583
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1587
Gregory P. Smithe9477062005-06-04 06:46:59 +00001588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1592 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1598 }
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1603
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1609
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1611 {
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001615 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001623 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 }
1625 else /* return just the pkey and data */
1626 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001627#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001629#else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1637 }
1638 FREE_DBT(key);
1639
1640 RETURN_IF_ERR();
1641 return retval;
1642}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001643#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001644
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645
1646/* Return size of entry */
1647static PyObject*
1648DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1649{
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001656 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001667 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668 CLEAR_DBT(data);
1669
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001677 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1680 }
1681
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1686}
1687
1688
1689static PyObject*
1690DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1691{
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700
1701
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1705
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
Neal Norwitz73bf1012007-05-19 04:37:31 +00001709 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001710 if ( !make_dbt(dataobj, &data) ||
1711 !checkTxnObj(txnobj, &txn) )
1712 {
1713 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001715 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001716
1717 flags |= DB_GET_BOTH;
1718
1719 if (CHECK_DBFLAG(self, DB_THREAD)) {
1720 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1721 data.flags = DB_DBT_MALLOC;
1722 /* TODO: Is this flag needed? We're passing a data object that should
1723 match what's in the DB, so there should be no need to malloc.
1724 We run the risk of freeing something twice! Check this. */
1725 }
1726
1727 MYDB_BEGIN_ALLOW_THREADS;
1728 err = self->db->get(self->db, txn, &key, &data, flags);
1729 MYDB_END_ALLOW_THREADS;
1730
Gregory P. Smithe9477062005-06-04 06:46:59 +00001731 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1732 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001733 err = 0;
1734 Py_INCREF(Py_None);
1735 retval = Py_None;
1736 }
1737 else if (!err) {
1738 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1739 FREE_DBT(data); /* Only if retrieval was successful */
1740 }
1741
1742 FREE_DBT(key);
1743 RETURN_IF_ERR();
1744 return retval;
1745}
1746
1747
1748static PyObject*
1749DB_get_byteswapped(DBObject* self, PyObject* args)
1750{
1751#if (DBVER >= 33)
1752 int err = 0;
1753#endif
1754 int retval = -1;
1755
1756 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1757 return NULL;
1758 CHECK_DB_NOT_CLOSED(self);
1759
1760#if (DBVER >= 33)
1761 MYDB_BEGIN_ALLOW_THREADS;
1762 err = self->db->get_byteswapped(self->db, &retval);
1763 MYDB_END_ALLOW_THREADS;
1764 RETURN_IF_ERR();
1765#else
1766 MYDB_BEGIN_ALLOW_THREADS;
1767 retval = self->db->get_byteswapped(self->db);
1768 MYDB_END_ALLOW_THREADS;
1769#endif
1770 return PyInt_FromLong(retval);
1771}
1772
1773
1774static PyObject*
1775DB_get_type(DBObject* self, PyObject* args)
1776{
1777 int type;
1778
1779 if (!PyArg_ParseTuple(args,":get_type"))
1780 return NULL;
1781 CHECK_DB_NOT_CLOSED(self);
1782
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001783 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001784 if (type == -1)
1785 return NULL;
1786 return PyInt_FromLong(type);
1787}
1788
1789
1790static PyObject*
1791DB_join(DBObject* self, PyObject* args)
1792{
1793 int err, flags=0;
1794 int length, x;
1795 PyObject* cursorsObj;
1796 DBC** cursors;
1797 DBC* dbc;
1798
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1800 return NULL;
1801
1802 CHECK_DB_NOT_CLOSED(self);
1803
1804 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001805 PyErr_SetString(PyExc_TypeError,
1806 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001807 return NULL;
1808 }
1809
1810 length = PyObject_Length(cursorsObj);
1811 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001812 if (!cursors) {
1813 PyErr_NoMemory();
1814 return NULL;
1815 }
1816
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001817 cursors[length] = NULL;
1818 for (x=0; x<length; x++) {
1819 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001820 if (item == NULL) {
1821 free(cursors);
1822 return NULL;
1823 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001824 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001825 PyErr_SetString(PyExc_TypeError,
1826 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001827 free(cursors);
1828 return NULL;
1829 }
1830 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001831 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001832 }
1833
1834 MYDB_BEGIN_ALLOW_THREADS;
1835 err = self->db->join(self->db, cursors, &dbc, flags);
1836 MYDB_END_ALLOW_THREADS;
1837 free(cursors);
1838 RETURN_IF_ERR();
1839
Gregory P. Smith7441e652003-11-03 21:35:31 +00001840 /* FIXME: this is a buggy interface. The returned cursor
1841 contains internal references to the passed in cursors
1842 but does not hold python references to them or prevent
1843 them from being closed prematurely. This can cause
1844 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 return (PyObject*) newDBCursorObject(dbc, self);
1846}
1847
1848
1849static PyObject*
1850DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1851{
1852 int err, flags=0;
1853 PyObject* txnobj = NULL;
1854 PyObject* keyobj;
1855 DBT key;
1856 DB_TXN *txn = NULL;
1857 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001858 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859
1860 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1861 &keyobj, &txnobj, &flags))
1862 return NULL;
1863 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001864 if (!make_dbt(keyobj, &key))
1865 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001866 return NULL;
1867 if (!checkTxnObj(txnobj, &txn))
1868 return NULL;
1869
1870 MYDB_BEGIN_ALLOW_THREADS;
1871 err = self->db->key_range(self->db, txn, &key, &range, flags);
1872 MYDB_END_ALLOW_THREADS;
1873
1874 RETURN_IF_ERR();
1875 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1876}
1877
1878
1879static PyObject*
1880DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1881{
1882 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1883 char* filename = NULL;
1884 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001885#if (DBVER >= 41)
1886 PyObject *txnobj = NULL;
1887 DB_TXN *txn = NULL;
1888 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001889 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001890 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1891 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001892 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001893 "filename", "dbtype", "flags", "mode", "txn", NULL};
1894#else
1895 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001896 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001897 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1898 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001899 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001900 "filename", "dbtype", "flags", "mode", NULL};
1901#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001902
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001903#if (DBVER >= 41)
1904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1905 &filename, &dbname, &type, &flags, &mode,
1906 &txnobj))
1907#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001908 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001909 &filename, &dbname, &type, &flags,
1910 &mode))
1911#endif
1912 {
1913 PyErr_Clear();
1914 type = DB_UNKNOWN; flags = 0; mode = 0660;
1915 filename = NULL; dbname = NULL;
1916#if (DBVER >= 41)
1917 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1918 kwnames_basic,
1919 &filename, &type, &flags, &mode,
1920 &txnobj))
1921 return NULL;
1922#else
1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1924 kwnames_basic,
1925 &filename, &type, &flags, &mode))
1926 return NULL;
1927#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 }
1929
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001930#if (DBVER >= 41)
1931 if (!checkTxnObj(txnobj, &txn)) return NULL;
1932#endif
1933
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001934 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001935 PyObject *t = Py_BuildValue("(is)", 0,
1936 "Cannot call open() twice for DB object");
1937 PyErr_SetObject(DBError, t);
1938 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001939 return NULL;
1940 }
1941
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001942#if 0 && (DBVER >= 41)
1943 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1944 && (self->myenvobj->flags & DB_INIT_TXN))
1945 {
1946 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1947 * explicitly passed) but we are in a transaction ready environment:
1948 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1949 * to work on BerkeleyDB 4.1 without needing to modify their
1950 * DBEnv or DB open calls.
1951 * TODO make this behaviour of the library configurable.
1952 */
1953 flags |= DB_AUTO_COMMIT;
1954 }
1955#endif
1956
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001958#if (DBVER >= 41)
1959 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1960#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001962#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001963 MYDB_END_ALLOW_THREADS;
1964 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001965 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001966 self->db = NULL;
1967 return NULL;
1968 }
1969
1970 self->flags = flags;
1971 RETURN_NONE();
1972}
1973
1974
1975static PyObject*
1976DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1977{
1978 int flags=0;
1979 PyObject* txnobj = NULL;
1980 int dlen = -1;
1981 int doff = -1;
1982 PyObject* keyobj, *dataobj, *retval;
1983 DBT key, data;
1984 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001985 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001986 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001987
1988 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1989 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1990 return NULL;
1991
1992 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001993 if (!make_key_dbt(self, keyobj, &key, NULL))
1994 return NULL;
1995 if ( !make_dbt(dataobj, &data) ||
1996 !add_partial_dbt(&data, dlen, doff) ||
1997 !checkTxnObj(txnobj, &txn) )
1998 {
1999 FREE_DBT(key);
2000 return NULL;
2001 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002002
2003 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2004 FREE_DBT(key);
2005 return NULL;
2006 }
2007
2008 if (flags & DB_APPEND)
2009 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2010 else {
2011 retval = Py_None;
2012 Py_INCREF(retval);
2013 }
2014 FREE_DBT(key);
2015 return retval;
2016}
2017
2018
2019
2020static PyObject*
2021DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2022{
2023 char* filename;
2024 char* database = NULL;
2025 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002026 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002027
2028 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2029 &filename, &database, &flags))
2030 return NULL;
2031 CHECK_DB_NOT_CLOSED(self);
2032
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002033 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002034 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035 RETURN_IF_ERR();
2036 RETURN_NONE();
2037}
2038
2039
2040
2041static PyObject*
2042DB_rename(DBObject* self, PyObject* args)
2043{
2044 char* filename;
2045 char* database;
2046 char* newname;
2047 int err, flags=0;
2048
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002049 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2050 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051 return NULL;
2052 CHECK_DB_NOT_CLOSED(self);
2053
2054 MYDB_BEGIN_ALLOW_THREADS;
2055 err = self->db->rename(self->db, filename, database, newname, flags);
2056 MYDB_END_ALLOW_THREADS;
2057 RETURN_IF_ERR();
2058 RETURN_NONE();
2059}
2060
2061
2062static PyObject*
2063DB_set_bt_minkey(DBObject* self, PyObject* args)
2064{
2065 int err, minkey;
2066
2067 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2068 return NULL;
2069 CHECK_DB_NOT_CLOSED(self);
2070
2071 MYDB_BEGIN_ALLOW_THREADS;
2072 err = self->db->set_bt_minkey(self->db, minkey);
2073 MYDB_END_ALLOW_THREADS;
2074 RETURN_IF_ERR();
2075 RETURN_NONE();
2076}
2077
Neal Norwitz84562352005-10-20 04:30:15 +00002078#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002079static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002080_default_cmp(const DBT *leftKey,
2081 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002082{
2083 int res;
2084 int lsize = leftKey->size, rsize = rightKey->size;
2085
Georg Brandlef1701f2006-03-07 14:57:48 +00002086 res = memcmp(leftKey->data, rightKey->data,
2087 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002088
2089 if (res == 0) {
2090 if (lsize < rsize) {
2091 res = -1;
2092 }
2093 else if (lsize > rsize) {
2094 res = 1;
2095 }
2096 }
2097 return res;
2098}
2099
2100static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002101_db_compareCallback(DB* db,
2102 const DBT *leftKey,
2103 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104{
2105 int res = 0;
2106 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002107 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109
2110 if (self == NULL || self->btCompareCallback == NULL) {
2111 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 PyErr_SetString(PyExc_TypeError,
2113 (self == 0
2114 ? "DB_bt_compare db is NULL."
2115 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002116 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002117 PyErr_Print();
2118 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002119 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002121 MYDB_BEGIN_BLOCK_THREADS;
2122
Thomas Woutersb3153832006-03-08 01:47:19 +00002123 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2124 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002126 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002129 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 PyErr_Print();
2133 res = _default_cmp(leftKey, rightKey);
2134 } else if (PyInt_Check(result)) {
2135 res = PyInt_AsLong(result);
2136 } else {
2137 PyErr_SetString(PyExc_TypeError,
2138 "DB_bt_compare callback MUST return an int.");
2139 /* we're in a callback within the DB code, we can't raise */
2140 PyErr_Print();
2141 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142 }
2143
Thomas Woutersb3153832006-03-08 01:47:19 +00002144 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146
2147 MYDB_END_BLOCK_THREADS;
2148 }
2149 return res;
2150}
2151
2152static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002153DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002154{
2155 int err;
2156 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002157 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158
Georg Brandlef1701f2006-03-07 14:57:48 +00002159 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160 return NULL;
2161
Georg Brandlef1701f2006-03-07 14:57:48 +00002162 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163
Georg Brandlef1701f2006-03-07 14:57:48 +00002164 if (!PyCallable_Check(comparator)) {
2165 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166 return NULL;
2167 }
2168
2169 /*
2170 * Perform a test call of the comparator function with two empty
2171 * string objects here. verify that it returns an int (0).
2172 * err if not.
2173 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002174 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002175 result = PyEval_CallObject(comparator, tuple);
2176 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002177 if (result == NULL)
2178 return NULL;
2179 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 PyErr_SetString(PyExc_TypeError,
2181 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 } else if (PyInt_AsLong(result) != 0) {
2184 PyErr_SetString(PyExc_TypeError,
2185 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002186 return NULL;
2187 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002188 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002189
2190 /* We don't accept multiple set_bt_compare operations, in order to
2191 * simplify the code. This would have no real use, as one cannot
2192 * change the function once the db is opened anyway */
2193 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002194 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002195 return NULL;
2196 }
2197
Georg Brandlef1701f2006-03-07 14:57:48 +00002198 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002199 self->btCompareCallback = comparator;
2200
2201 /* This is to workaround a problem with un-initialized threads (see
2202 comment in DB_associate) */
2203#ifdef WITH_THREAD
2204 PyEval_InitThreads();
2205#endif
2206
Thomas Woutersb3153832006-03-08 01:47:19 +00002207 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002208
2209 if (err) {
2210 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002211 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002212 self->btCompareCallback = NULL;
2213 }
2214
Georg Brandlef1701f2006-03-07 14:57:48 +00002215 RETURN_IF_ERR();
2216 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002217}
Neal Norwitz84562352005-10-20 04:30:15 +00002218#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002220
2221static PyObject*
2222DB_set_cachesize(DBObject* self, PyObject* args)
2223{
2224 int err;
2225 int gbytes = 0, bytes = 0, ncache = 0;
2226
2227 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2228 &gbytes,&bytes,&ncache))
2229 return NULL;
2230 CHECK_DB_NOT_CLOSED(self);
2231
2232 MYDB_BEGIN_ALLOW_THREADS;
2233 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2234 MYDB_END_ALLOW_THREADS;
2235 RETURN_IF_ERR();
2236 RETURN_NONE();
2237}
2238
2239
2240static PyObject*
2241DB_set_flags(DBObject* self, PyObject* args)
2242{
2243 int err, flags;
2244
2245 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2246 return NULL;
2247 CHECK_DB_NOT_CLOSED(self);
2248
2249 MYDB_BEGIN_ALLOW_THREADS;
2250 err = self->db->set_flags(self->db, flags);
2251 MYDB_END_ALLOW_THREADS;
2252 RETURN_IF_ERR();
2253
2254 self->setflags |= flags;
2255 RETURN_NONE();
2256}
2257
2258
2259static PyObject*
2260DB_set_h_ffactor(DBObject* self, PyObject* args)
2261{
2262 int err, ffactor;
2263
2264 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2265 return NULL;
2266 CHECK_DB_NOT_CLOSED(self);
2267
2268 MYDB_BEGIN_ALLOW_THREADS;
2269 err = self->db->set_h_ffactor(self->db, ffactor);
2270 MYDB_END_ALLOW_THREADS;
2271 RETURN_IF_ERR();
2272 RETURN_NONE();
2273}
2274
2275
2276static PyObject*
2277DB_set_h_nelem(DBObject* self, PyObject* args)
2278{
2279 int err, nelem;
2280
2281 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2282 return NULL;
2283 CHECK_DB_NOT_CLOSED(self);
2284
2285 MYDB_BEGIN_ALLOW_THREADS;
2286 err = self->db->set_h_nelem(self->db, nelem);
2287 MYDB_END_ALLOW_THREADS;
2288 RETURN_IF_ERR();
2289 RETURN_NONE();
2290}
2291
2292
2293static PyObject*
2294DB_set_lorder(DBObject* self, PyObject* args)
2295{
2296 int err, lorder;
2297
2298 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2299 return NULL;
2300 CHECK_DB_NOT_CLOSED(self);
2301
2302 MYDB_BEGIN_ALLOW_THREADS;
2303 err = self->db->set_lorder(self->db, lorder);
2304 MYDB_END_ALLOW_THREADS;
2305 RETURN_IF_ERR();
2306 RETURN_NONE();
2307}
2308
2309
2310static PyObject*
2311DB_set_pagesize(DBObject* self, PyObject* args)
2312{
2313 int err, pagesize;
2314
2315 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2316 return NULL;
2317 CHECK_DB_NOT_CLOSED(self);
2318
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->set_pagesize(self->db, pagesize);
2321 MYDB_END_ALLOW_THREADS;
2322 RETURN_IF_ERR();
2323 RETURN_NONE();
2324}
2325
2326
2327static PyObject*
2328DB_set_re_delim(DBObject* self, PyObject* args)
2329{
2330 int err;
2331 char delim;
2332
2333 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2334 PyErr_Clear();
2335 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2336 return NULL;
2337 }
2338
2339 CHECK_DB_NOT_CLOSED(self);
2340
2341 MYDB_BEGIN_ALLOW_THREADS;
2342 err = self->db->set_re_delim(self->db, delim);
2343 MYDB_END_ALLOW_THREADS;
2344 RETURN_IF_ERR();
2345 RETURN_NONE();
2346}
2347
2348static PyObject*
2349DB_set_re_len(DBObject* self, PyObject* args)
2350{
2351 int err, len;
2352
2353 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2354 return NULL;
2355 CHECK_DB_NOT_CLOSED(self);
2356
2357 MYDB_BEGIN_ALLOW_THREADS;
2358 err = self->db->set_re_len(self->db, len);
2359 MYDB_END_ALLOW_THREADS;
2360 RETURN_IF_ERR();
2361 RETURN_NONE();
2362}
2363
2364
2365static PyObject*
2366DB_set_re_pad(DBObject* self, PyObject* args)
2367{
2368 int err;
2369 char pad;
2370
2371 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2372 PyErr_Clear();
2373 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2374 return NULL;
2375 }
2376 CHECK_DB_NOT_CLOSED(self);
2377
2378 MYDB_BEGIN_ALLOW_THREADS;
2379 err = self->db->set_re_pad(self->db, pad);
2380 MYDB_END_ALLOW_THREADS;
2381 RETURN_IF_ERR();
2382 RETURN_NONE();
2383}
2384
2385
2386static PyObject*
2387DB_set_re_source(DBObject* self, PyObject* args)
2388{
2389 int err;
2390 char *re_source;
2391
2392 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2393 return NULL;
2394 CHECK_DB_NOT_CLOSED(self);
2395
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_re_source(self->db, re_source);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2400 RETURN_NONE();
2401}
2402
2403
2404#if (DBVER >= 32)
2405static PyObject*
2406DB_set_q_extentsize(DBObject* self, PyObject* args)
2407{
2408 int err;
2409 int extentsize;
2410
2411 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2412 return NULL;
2413 CHECK_DB_NOT_CLOSED(self);
2414
2415 MYDB_BEGIN_ALLOW_THREADS;
2416 err = self->db->set_q_extentsize(self->db, extentsize);
2417 MYDB_END_ALLOW_THREADS;
2418 RETURN_IF_ERR();
2419 RETURN_NONE();
2420}
2421#endif
2422
2423static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002424DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002425{
2426 int err, flags = 0, type;
2427 void* sp;
2428 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002429#if (DBVER >= 43)
2430 PyObject* txnobj = NULL;
2431 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002432 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002433#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002434 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002436
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002437#if (DBVER >= 43)
2438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2439 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002440 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002441 if (!checkTxnObj(txnobj, &txn))
2442 return NULL;
2443#else
2444 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2445 return NULL;
2446#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002447 CHECK_DB_NOT_CLOSED(self);
2448
2449 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002450#if (DBVER >= 43)
2451 err = self->db->stat(self->db, txn, &sp, flags);
2452#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002453 err = self->db->stat(self->db, &sp, flags);
2454#else
2455 err = self->db->stat(self->db, &sp, NULL, flags);
2456#endif
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459
2460 self->haveStat = 1;
2461
2462 /* Turn the stat structure into a dictionary */
2463 type = _DB_get_type(self);
2464 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2465 free(sp);
2466 return NULL;
2467 }
2468
2469#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2470#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2471#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2472
2473 switch (type) {
2474 case DB_HASH:
2475 MAKE_HASH_ENTRY(magic);
2476 MAKE_HASH_ENTRY(version);
2477 MAKE_HASH_ENTRY(nkeys);
2478 MAKE_HASH_ENTRY(ndata);
2479 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002480#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002481 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002482#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002483 MAKE_HASH_ENTRY(ffactor);
2484 MAKE_HASH_ENTRY(buckets);
2485 MAKE_HASH_ENTRY(free);
2486 MAKE_HASH_ENTRY(bfree);
2487 MAKE_HASH_ENTRY(bigpages);
2488 MAKE_HASH_ENTRY(big_bfree);
2489 MAKE_HASH_ENTRY(overflows);
2490 MAKE_HASH_ENTRY(ovfl_free);
2491 MAKE_HASH_ENTRY(dup);
2492 MAKE_HASH_ENTRY(dup_free);
2493 break;
2494
2495 case DB_BTREE:
2496 case DB_RECNO:
2497 MAKE_BT_ENTRY(magic);
2498 MAKE_BT_ENTRY(version);
2499 MAKE_BT_ENTRY(nkeys);
2500 MAKE_BT_ENTRY(ndata);
2501 MAKE_BT_ENTRY(pagesize);
2502 MAKE_BT_ENTRY(minkey);
2503 MAKE_BT_ENTRY(re_len);
2504 MAKE_BT_ENTRY(re_pad);
2505 MAKE_BT_ENTRY(levels);
2506 MAKE_BT_ENTRY(int_pg);
2507 MAKE_BT_ENTRY(leaf_pg);
2508 MAKE_BT_ENTRY(dup_pg);
2509 MAKE_BT_ENTRY(over_pg);
2510 MAKE_BT_ENTRY(free);
2511 MAKE_BT_ENTRY(int_pgfree);
2512 MAKE_BT_ENTRY(leaf_pgfree);
2513 MAKE_BT_ENTRY(dup_pgfree);
2514 MAKE_BT_ENTRY(over_pgfree);
2515 break;
2516
2517 case DB_QUEUE:
2518 MAKE_QUEUE_ENTRY(magic);
2519 MAKE_QUEUE_ENTRY(version);
2520 MAKE_QUEUE_ENTRY(nkeys);
2521 MAKE_QUEUE_ENTRY(ndata);
2522 MAKE_QUEUE_ENTRY(pagesize);
2523 MAKE_QUEUE_ENTRY(pages);
2524 MAKE_QUEUE_ENTRY(re_len);
2525 MAKE_QUEUE_ENTRY(re_pad);
2526 MAKE_QUEUE_ENTRY(pgfree);
2527#if (DBVER == 31)
2528 MAKE_QUEUE_ENTRY(start);
2529#endif
2530 MAKE_QUEUE_ENTRY(first_recno);
2531 MAKE_QUEUE_ENTRY(cur_recno);
2532 break;
2533
2534 default:
2535 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2536 Py_DECREF(d);
2537 d = NULL;
2538 }
2539
2540#undef MAKE_HASH_ENTRY
2541#undef MAKE_BT_ENTRY
2542#undef MAKE_QUEUE_ENTRY
2543
2544 free(sp);
2545 return d;
2546}
2547
2548static PyObject*
2549DB_sync(DBObject* self, PyObject* args)
2550{
2551 int err;
2552 int flags = 0;
2553
2554 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2555 return NULL;
2556 CHECK_DB_NOT_CLOSED(self);
2557
2558 MYDB_BEGIN_ALLOW_THREADS;
2559 err = self->db->sync(self->db, flags);
2560 MYDB_END_ALLOW_THREADS;
2561 RETURN_IF_ERR();
2562 RETURN_NONE();
2563}
2564
2565
2566#if (DBVER >= 33)
2567static PyObject*
2568DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2569{
2570 int err, flags=0;
2571 u_int32_t count=0;
2572 PyObject* txnobj = NULL;
2573 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002574 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002575
2576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2577 &txnobj, &flags))
2578 return NULL;
2579 CHECK_DB_NOT_CLOSED(self);
2580 if (!checkTxnObj(txnobj, &txn))
2581 return NULL;
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
2584 err = self->db->truncate(self->db, txn, &count, flags);
2585 MYDB_END_ALLOW_THREADS;
2586 RETURN_IF_ERR();
2587 return PyInt_FromLong(count);
2588}
2589#endif
2590
2591
2592static PyObject*
2593DB_upgrade(DBObject* self, PyObject* args)
2594{
2595 int err, flags=0;
2596 char *filename;
2597
2598 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2599 return NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601
2602 MYDB_BEGIN_ALLOW_THREADS;
2603 err = self->db->upgrade(self->db, filename, flags);
2604 MYDB_END_ALLOW_THREADS;
2605 RETURN_IF_ERR();
2606 RETURN_NONE();
2607}
2608
2609
2610static PyObject*
2611DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2612{
2613 int err, flags=0;
2614 char* fileName;
2615 char* dbName=NULL;
2616 char* outFileName=NULL;
2617 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002618 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002619 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002620
2621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2622 &fileName, &dbName, &outFileName, &flags))
2623 return NULL;
2624
2625 CHECK_DB_NOT_CLOSED(self);
2626 if (outFileName)
2627 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002628 /* XXX(nnorwitz): it should probably be an exception if outFile
2629 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002630
2631 MYDB_BEGIN_ALLOW_THREADS;
2632 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2633 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002634 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002635 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002636
2637 /* DB.verify acts as a DB handle destructor (like close); this was
2638 * documented in BerkeleyDB 4.2 but had the undocumented effect
2639 * of not being safe in prior versions while still requiring an explicit
2640 * DB.close call afterwards. Lets call close for the user to emulate
2641 * the safe 4.2 behaviour. */
2642#if (DBVER <= 41)
2643 self->db->close(self->db, 0);
2644#endif
2645 self->db = NULL;
2646
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002647 RETURN_IF_ERR();
2648 RETURN_NONE();
2649}
2650
2651
2652static PyObject*
2653DB_set_get_returns_none(DBObject* self, PyObject* args)
2654{
2655 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002656 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002657
2658 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2659 return NULL;
2660 CHECK_DB_NOT_CLOSED(self);
2661
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002662 if (self->moduleFlags.getReturnsNone)
2663 ++oldValue;
2664 if (self->moduleFlags.cursorSetReturnsNone)
2665 ++oldValue;
2666 self->moduleFlags.getReturnsNone = (flags >= 1);
2667 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002668 return PyInt_FromLong(oldValue);
2669}
2670
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002671#if (DBVER >= 41)
2672static PyObject*
2673DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2674{
2675 int err;
2676 u_int32_t flags=0;
2677 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002678 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002679
2680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2681 &passwd, &flags)) {
2682 return NULL;
2683 }
2684
2685 MYDB_BEGIN_ALLOW_THREADS;
2686 err = self->db->set_encrypt(self->db, passwd, flags);
2687 MYDB_END_ALLOW_THREADS;
2688
2689 RETURN_IF_ERR();
2690 RETURN_NONE();
2691}
2692#endif /* DBVER >= 41 */
2693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002694
2695/*-------------------------------------------------------------- */
2696/* Mapping and Dictionary-like access routines */
2697
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002698Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699{
2700 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002701 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 int flags = 0;
2703 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002704 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002705
2706 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002707 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2708 PyErr_SetObject(DBError, t);
2709 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710 return -1;
2711 }
2712
2713 if (self->haveStat) { /* Has the stat function been called recently? If
2714 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002715 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716 }
2717
2718 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002719redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002720#if (DBVER >= 43)
2721 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2722#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723 err = self->db->stat(self->db, &sp, flags);
2724#else
2725 err = self->db->stat(self->db, &sp, NULL, flags);
2726#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002727
2728 /* All the stat structures have matching fields upto the ndata field,
2729 so we can use any of them for the type cast */
2730 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2731
2732 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2733 * redo a full stat to make sure.
2734 * Fixes SF python bug 1493322, pybsddb bug 1184012
2735 */
2736 if (size == 0 && (flags & DB_FAST_STAT)) {
2737 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002738 if (!err)
2739 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002740 goto redo_stat_for_length;
2741 }
2742
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002743 MYDB_END_ALLOW_THREADS;
2744
2745 if (err)
2746 return -1;
2747
2748 self->haveStat = 1;
2749
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750 free(sp);
2751 return size;
2752}
2753
2754
2755PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2756{
2757 int err;
2758 PyObject* retval;
2759 DBT key;
2760 DBT data;
2761
2762 CHECK_DB_NOT_CLOSED(self);
2763 if (!make_key_dbt(self, keyobj, &key, NULL))
2764 return NULL;
2765
2766 CLEAR_DBT(data);
2767 if (CHECK_DBFLAG(self, DB_THREAD)) {
2768 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2769 data.flags = DB_DBT_MALLOC;
2770 }
2771 MYDB_BEGIN_ALLOW_THREADS;
2772 err = self->db->get(self->db, NULL, &key, &data, 0);
2773 MYDB_END_ALLOW_THREADS;
2774 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2775 PyErr_SetObject(PyExc_KeyError, keyobj);
2776 retval = NULL;
2777 }
2778 else if (makeDBError(err)) {
2779 retval = NULL;
2780 }
2781 else {
2782 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2783 FREE_DBT(data);
2784 }
2785
2786 FREE_DBT(key);
2787 return retval;
2788}
2789
2790
2791static int
2792DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2793{
2794 DBT key, data;
2795 int retval;
2796 int flags = 0;
2797
2798 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002799 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2800 PyErr_SetObject(DBError, t);
2801 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802 return -1;
2803 }
2804
2805 if (!make_key_dbt(self, keyobj, &key, NULL))
2806 return -1;
2807
2808 if (dataobj != NULL) {
2809 if (!make_dbt(dataobj, &data))
2810 retval = -1;
2811 else {
2812 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002813 /* dictionaries shouldn't have duplicate keys */
2814 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002815 retval = _DB_put(self, NULL, &key, &data, flags);
2816
2817 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002818 /* try deleting any old record that matches and then PUT it
2819 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002820 _DB_delete(self, NULL, &key, 0);
2821 PyErr_Clear();
2822 retval = _DB_put(self, NULL, &key, &data, flags);
2823 }
2824 }
2825 }
2826 else {
2827 /* dataobj == NULL, so delete the key */
2828 retval = _DB_delete(self, NULL, &key, 0);
2829 }
2830 FREE_DBT(key);
2831 return retval;
2832}
2833
2834
2835static PyObject*
2836DB_has_key(DBObject* self, PyObject* args)
2837{
2838 int err;
2839 PyObject* keyobj;
2840 DBT key, data;
2841 PyObject* txnobj = NULL;
2842 DB_TXN *txn = NULL;
2843
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002844 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002845 return NULL;
2846 CHECK_DB_NOT_CLOSED(self);
2847 if (!make_key_dbt(self, keyobj, &key, NULL))
2848 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002849 if (!checkTxnObj(txnobj, &txn)) {
2850 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002852 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002854 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855 it has a record but can't allocate a buffer for the data. This saves
2856 having to deal with data we won't be using.
2857 */
2858 CLEAR_DBT(data);
2859 data.flags = DB_DBT_USERMEM;
2860
2861 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002862 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002863 MYDB_END_ALLOW_THREADS;
2864 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002865
2866 if (err == DB_BUFFER_SMALL || err == 0) {
2867 return PyInt_FromLong(1);
2868 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2869 return PyInt_FromLong(0);
2870 }
2871
2872 makeDBError(err);
2873 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002874}
2875
2876
2877#define _KEYS_LIST 1
2878#define _VALUES_LIST 2
2879#define _ITEMS_LIST 3
2880
2881static PyObject*
2882_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2883{
2884 int err, dbtype;
2885 DBT key;
2886 DBT data;
2887 DBC *cursor;
2888 PyObject* list;
2889 PyObject* item = NULL;
2890
2891 CHECK_DB_NOT_CLOSED(self);
2892 CLEAR_DBT(key);
2893 CLEAR_DBT(data);
2894
2895 dbtype = _DB_get_type(self);
2896 if (dbtype == -1)
2897 return NULL;
2898
2899 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002900 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002902
2903 /* get a cursor */
2904 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002905 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002907 if (makeDBError(err)) {
2908 Py_DECREF(list);
2909 return NULL;
2910 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002911
2912 if (CHECK_DBFLAG(self, DB_THREAD)) {
2913 key.flags = DB_DBT_REALLOC;
2914 data.flags = DB_DBT_REALLOC;
2915 }
2916
2917 while (1) { /* use the cursor to traverse the DB, collecting items */
2918 MYDB_BEGIN_ALLOW_THREADS;
2919 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2920 MYDB_END_ALLOW_THREADS;
2921
2922 if (err) {
2923 /* for any error, break out of the loop */
2924 break;
2925 }
2926
2927 switch (type) {
2928 case _KEYS_LIST:
2929 switch(dbtype) {
2930 case DB_BTREE:
2931 case DB_HASH:
2932 default:
2933 item = PyString_FromStringAndSize((char*)key.data, key.size);
2934 break;
2935 case DB_RECNO:
2936 case DB_QUEUE:
2937 item = PyInt_FromLong(*((db_recno_t*)key.data));
2938 break;
2939 }
2940 break;
2941
2942 case _VALUES_LIST:
2943 item = PyString_FromStringAndSize((char*)data.data, data.size);
2944 break;
2945
2946 case _ITEMS_LIST:
2947 switch(dbtype) {
2948 case DB_BTREE:
2949 case DB_HASH:
2950 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002951 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2952 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002953 break;
2954 case DB_RECNO:
2955 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002956 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2957 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002958 break;
2959 }
2960 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002961 default:
2962 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2963 item = NULL;
2964 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965 }
2966 if (item == NULL) {
2967 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002968 list = NULL;
2969 goto done;
2970 }
2971 PyList_Append(list, item);
2972 Py_DECREF(item);
2973 }
2974
Gregory P. Smithe9477062005-06-04 06:46:59 +00002975 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2976 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002977 Py_DECREF(list);
2978 list = NULL;
2979 }
2980
2981 done:
2982 FREE_DBT(key);
2983 FREE_DBT(data);
2984 MYDB_BEGIN_ALLOW_THREADS;
2985 cursor->c_close(cursor);
2986 MYDB_END_ALLOW_THREADS;
2987 return list;
2988}
2989
2990
2991static PyObject*
2992DB_keys(DBObject* self, PyObject* args)
2993{
2994 PyObject* txnobj = NULL;
2995 DB_TXN *txn = NULL;
2996
Georg Brandl96a8c392006-05-29 21:04:52 +00002997 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998 return NULL;
2999 if (!checkTxnObj(txnobj, &txn))
3000 return NULL;
3001 return _DB_make_list(self, txn, _KEYS_LIST);
3002}
3003
3004
3005static PyObject*
3006DB_items(DBObject* self, PyObject* args)
3007{
3008 PyObject* txnobj = NULL;
3009 DB_TXN *txn = NULL;
3010
Georg Brandl96a8c392006-05-29 21:04:52 +00003011 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003012 return NULL;
3013 if (!checkTxnObj(txnobj, &txn))
3014 return NULL;
3015 return _DB_make_list(self, txn, _ITEMS_LIST);
3016}
3017
3018
3019static PyObject*
3020DB_values(DBObject* self, PyObject* args)
3021{
3022 PyObject* txnobj = NULL;
3023 DB_TXN *txn = NULL;
3024
Georg Brandl96a8c392006-05-29 21:04:52 +00003025 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003026 return NULL;
3027 if (!checkTxnObj(txnobj, &txn))
3028 return NULL;
3029 return _DB_make_list(self, txn, _VALUES_LIST);
3030}
3031
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003032/* --------------------------------------------------------------------- */
3033/* DBCursor methods */
3034
3035
3036static PyObject*
3037DBC_close(DBCursorObject* self, PyObject* args)
3038{
3039 int err = 0;
3040
3041 if (!PyArg_ParseTuple(args, ":close"))
3042 return NULL;
3043
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 if (self->dbc != NULL) {
3045 MYDB_BEGIN_ALLOW_THREADS;
3046 err = self->dbc->c_close(self->dbc);
3047 self->dbc = NULL;
3048 MYDB_END_ALLOW_THREADS;
3049 }
3050 RETURN_IF_ERR();
3051 RETURN_NONE();
3052}
3053
3054
3055static PyObject*
3056DBC_count(DBCursorObject* self, PyObject* args)
3057{
3058 int err = 0;
3059 db_recno_t count;
3060 int flags = 0;
3061
3062 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3063 return NULL;
3064
3065 CHECK_CURSOR_NOT_CLOSED(self);
3066
3067 MYDB_BEGIN_ALLOW_THREADS;
3068 err = self->dbc->c_count(self->dbc, &count, flags);
3069 MYDB_END_ALLOW_THREADS;
3070 RETURN_IF_ERR();
3071
3072 return PyInt_FromLong(count);
3073}
3074
3075
3076static PyObject*
3077DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3078{
3079 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3080}
3081
3082
3083static PyObject*
3084DBC_delete(DBCursorObject* self, PyObject* args)
3085{
3086 int err, flags=0;
3087
3088 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3089 return NULL;
3090
3091 CHECK_CURSOR_NOT_CLOSED(self);
3092
3093 MYDB_BEGIN_ALLOW_THREADS;
3094 err = self->dbc->c_del(self->dbc, flags);
3095 MYDB_END_ALLOW_THREADS;
3096 RETURN_IF_ERR();
3097
3098 self->mydb->haveStat = 0;
3099 RETURN_NONE();
3100}
3101
3102
3103static PyObject*
3104DBC_dup(DBCursorObject* self, PyObject* args)
3105{
3106 int err, flags =0;
3107 DBC* dbc = NULL;
3108
3109 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3110 return NULL;
3111
3112 CHECK_CURSOR_NOT_CLOSED(self);
3113
3114 MYDB_BEGIN_ALLOW_THREADS;
3115 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3116 MYDB_END_ALLOW_THREADS;
3117 RETURN_IF_ERR();
3118
3119 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3120}
3121
3122static PyObject*
3123DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3124{
3125 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3126}
3127
3128
3129static PyObject*
3130DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3131{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003132 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003133 PyObject* keyobj = NULL;
3134 PyObject* dataobj = NULL;
3135 PyObject* retval = NULL;
3136 int dlen = -1;
3137 int doff = -1;
3138 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003139 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003140 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141
3142 CLEAR_DBT(key);
3143 CLEAR_DBT(data);
3144 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003145 &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, "Oi|ii:get",
3149 &kwnames[1],
3150 &keyobj, &flags, &dlen, &doff))
3151 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3154 kwnames, &keyobj, &dataobj,
3155 &flags, &dlen, &doff))
3156 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157 return NULL;
3158 }
3159 }
3160 }
3161
3162 CHECK_CURSOR_NOT_CLOSED(self);
3163
3164 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3165 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003166 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3167 (!add_partial_dbt(&data, dlen, doff)) )
3168 {
3169 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003171 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172
3173 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3174 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003175 if (!(key.flags & DB_DBT_REALLOC)) {
3176 key.flags |= DB_DBT_MALLOC;
3177 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003178 }
3179
3180 MYDB_BEGIN_ALLOW_THREADS;
3181 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3182 MYDB_END_ALLOW_THREADS;
3183
Gregory P. Smithe9477062005-06-04 06:46:59 +00003184 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3185 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 Py_INCREF(Py_None);
3187 retval = Py_None;
3188 }
3189 else if (makeDBError(err)) {
3190 retval = NULL;
3191 }
3192 else {
3193 switch (_DB_get_type(self->mydb)) {
3194 case -1:
3195 retval = NULL;
3196 break;
3197 case DB_BTREE:
3198 case DB_HASH:
3199 default:
3200 retval = Py_BuildValue("s#s#", key.data, key.size,
3201 data.data, data.size);
3202 break;
3203 case DB_RECNO:
3204 case DB_QUEUE:
3205 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3206 data.data, data.size);
3207 break;
3208 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003209 FREE_DBT(data);
3210 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003211 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003212 return retval;
3213}
3214
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003215#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003216static PyObject*
3217DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3218{
3219 int err, flags=0;
3220 PyObject* keyobj = NULL;
3221 PyObject* dataobj = NULL;
3222 PyObject* retval = NULL;
3223 int dlen = -1;
3224 int doff = -1;
3225 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003226 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3227 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003228
3229 CLEAR_DBT(key);
3230 CLEAR_DBT(data);
3231 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3232 &flags, &dlen, &doff))
3233 {
3234 PyErr_Clear();
3235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003236 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003237 &keyobj, &flags, &dlen, &doff))
3238 {
3239 PyErr_Clear();
3240 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3241 kwnames, &keyobj, &dataobj,
3242 &flags, &dlen, &doff))
3243 {
3244 return NULL;
3245 }
3246 }
3247 }
3248
3249 CHECK_CURSOR_NOT_CLOSED(self);
3250
3251 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3252 return NULL;
3253 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3254 (!add_partial_dbt(&data, dlen, doff)) ) {
3255 FREE_DBT(key);
3256 return NULL;
3257 }
3258
3259 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3260 data.flags = DB_DBT_MALLOC;
3261 if (!(key.flags & DB_DBT_REALLOC)) {
3262 key.flags |= DB_DBT_MALLOC;
3263 }
3264 }
3265
3266 CLEAR_DBT(pkey);
3267 pkey.flags = DB_DBT_MALLOC;
3268
3269 MYDB_BEGIN_ALLOW_THREADS;
3270 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3271 MYDB_END_ALLOW_THREADS;
3272
Gregory P. Smithe9477062005-06-04 06:46:59 +00003273 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3274 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003275 Py_INCREF(Py_None);
3276 retval = Py_None;
3277 }
3278 else if (makeDBError(err)) {
3279 retval = NULL;
3280 }
3281 else {
3282 PyObject *pkeyObj;
3283 PyObject *dataObj;
3284 dataObj = PyString_FromStringAndSize(data.data, data.size);
3285
3286 if (self->mydb->primaryDBType == DB_RECNO ||
3287 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003288 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003289 else
3290 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3291
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003292 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293 {
3294 PyObject *keyObj;
3295 int type = _DB_get_type(self->mydb);
3296 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003297 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003298 else
3299 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003300#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003301 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003302#else
3303 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3304#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003305 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003306 FREE_DBT(key);
3307 }
3308 else /* return just the pkey and data */
3309 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003310#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003311 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003312#else
3313 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3314#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003316 Py_DECREF(dataObj);
3317 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003318 FREE_DBT(pkey);
3319 FREE_DBT(data);
3320 }
3321 /* the only time REALLOC should be set is if we used an integer
3322 * key that make_key_dbt malloc'd for us. always free these. */
3323 if (key.flags & DB_DBT_REALLOC) {
3324 FREE_DBT(key);
3325 }
3326 return retval;
3327}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003328#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003329
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003330
3331static PyObject*
3332DBC_get_recno(DBCursorObject* self, PyObject* args)
3333{
3334 int err;
3335 db_recno_t recno;
3336 DBT key;
3337 DBT data;
3338
3339 if (!PyArg_ParseTuple(args, ":get_recno"))
3340 return NULL;
3341
3342 CHECK_CURSOR_NOT_CLOSED(self);
3343
3344 CLEAR_DBT(key);
3345 CLEAR_DBT(data);
3346 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3347 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3348 data.flags = DB_DBT_MALLOC;
3349 key.flags = DB_DBT_MALLOC;
3350 }
3351
3352 MYDB_BEGIN_ALLOW_THREADS;
3353 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3354 MYDB_END_ALLOW_THREADS;
3355 RETURN_IF_ERR();
3356
3357 recno = *((db_recno_t*)data.data);
3358 FREE_DBT(key);
3359 FREE_DBT(data);
3360 return PyInt_FromLong(recno);
3361}
3362
3363
3364static PyObject*
3365DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3366{
3367 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3368}
3369
3370
3371static PyObject*
3372DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3373{
3374 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3375}
3376
3377
3378static PyObject*
3379DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3380{
3381 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3382}
3383
3384
3385static PyObject*
3386DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3387{
3388 int err, flags = 0;
3389 PyObject* keyobj, *dataobj;
3390 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003391 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003392 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393 int dlen = -1;
3394 int doff = -1;
3395
3396 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3397 &keyobj, &dataobj, &flags, &dlen, &doff))
3398 return NULL;
3399
3400 CHECK_CURSOR_NOT_CLOSED(self);
3401
3402 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3403 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003404 if (!make_dbt(dataobj, &data) ||
3405 !add_partial_dbt(&data, dlen, doff) )
3406 {
3407 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003409 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410
3411 MYDB_BEGIN_ALLOW_THREADS;
3412 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3413 MYDB_END_ALLOW_THREADS;
3414 FREE_DBT(key);
3415 RETURN_IF_ERR();
3416 self->mydb->haveStat = 0;
3417 RETURN_NONE();
3418}
3419
3420
3421static PyObject*
3422DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3423{
3424 int err, flags = 0;
3425 DBT key, data;
3426 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003427 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 int dlen = -1;
3429 int doff = -1;
3430
3431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3432 &keyobj, &flags, &dlen, &doff))
3433 return NULL;
3434
3435 CHECK_CURSOR_NOT_CLOSED(self);
3436
3437 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3438 return NULL;
3439
3440 CLEAR_DBT(data);
3441 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3442 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3443 data.flags = DB_DBT_MALLOC;
3444 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003445 if (!add_partial_dbt(&data, dlen, doff)) {
3446 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003448 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449
3450 MYDB_BEGIN_ALLOW_THREADS;
3451 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3452 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003453 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3454 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003455 Py_INCREF(Py_None);
3456 retval = Py_None;
3457 }
3458 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459 retval = NULL;
3460 }
3461 else {
3462 switch (_DB_get_type(self->mydb)) {
3463 case -1:
3464 retval = NULL;
3465 break;
3466 case DB_BTREE:
3467 case DB_HASH:
3468 default:
3469 retval = Py_BuildValue("s#s#", key.data, key.size,
3470 data.data, data.size);
3471 break;
3472 case DB_RECNO:
3473 case DB_QUEUE:
3474 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3475 data.data, data.size);
3476 break;
3477 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003478 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003479 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003481 /* the only time REALLOC should be set is if we used an integer
3482 * key that make_key_dbt malloc'd for us. always free these. */
3483 if (key.flags & DB_DBT_REALLOC) {
3484 FREE_DBT(key);
3485 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003486
3487 return retval;
3488}
3489
3490
3491static PyObject*
3492DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3493{
3494 int err, flags = 0;
3495 DBT key, data;
3496 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003497 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498 int dlen = -1;
3499 int doff = -1;
3500
3501 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3502 &keyobj, &flags, &dlen, &doff))
3503 return NULL;
3504
3505 CHECK_CURSOR_NOT_CLOSED(self);
3506
3507 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3508 return NULL;
3509
3510 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003511 if (!add_partial_dbt(&data, dlen, doff)) {
3512 FREE_DBT(key);
3513 return NULL;
3514 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003515 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3516 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003517 data.flags |= DB_DBT_MALLOC;
3518 /* only BTREE databases will return anything in the key */
3519 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3520 key.flags |= DB_DBT_MALLOC;
3521 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003522 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003523 MYDB_BEGIN_ALLOW_THREADS;
3524 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3525 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003526 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3527 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003528 Py_INCREF(Py_None);
3529 retval = Py_None;
3530 }
3531 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003532 retval = NULL;
3533 }
3534 else {
3535 switch (_DB_get_type(self->mydb)) {
3536 case -1:
3537 retval = NULL;
3538 break;
3539 case DB_BTREE:
3540 case DB_HASH:
3541 default:
3542 retval = Py_BuildValue("s#s#", key.data, key.size,
3543 data.data, data.size);
3544 break;
3545 case DB_RECNO:
3546 case DB_QUEUE:
3547 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3548 data.data, data.size);
3549 break;
3550 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003551 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552 FREE_DBT(data);
3553 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003554 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003555 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003556 if (key.flags & DB_DBT_REALLOC) {
3557 FREE_DBT(key);
3558 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003559
3560 return retval;
3561}
3562
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003563static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003564_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3565 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003567 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003568 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003569 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570
Gregory P. Smith7441e652003-11-03 21:35:31 +00003571 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3573 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003574 if (!make_dbt(dataobj, &data)) {
3575 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003577 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578
3579 MYDB_BEGIN_ALLOW_THREADS;
3580 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3581 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003582 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003583 Py_INCREF(Py_None);
3584 retval = Py_None;
3585 }
3586 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587 retval = NULL;
3588 }
3589 else {
3590 switch (_DB_get_type(self->mydb)) {
3591 case -1:
3592 retval = NULL;
3593 break;
3594 case DB_BTREE:
3595 case DB_HASH:
3596 default:
3597 retval = Py_BuildValue("s#s#", key.data, key.size,
3598 data.data, data.size);
3599 break;
3600 case DB_RECNO:
3601 case DB_QUEUE:
3602 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3603 data.data, data.size);
3604 break;
3605 }
3606 }
3607
3608 FREE_DBT(key);
3609 return retval;
3610}
3611
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003612static PyObject*
3613DBC_get_both(DBCursorObject* self, PyObject* args)
3614{
3615 int flags=0;
3616 PyObject *keyobj, *dataobj;
3617
3618 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3619 return NULL;
3620
Gregory P. Smith7441e652003-11-03 21:35:31 +00003621 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003622 CHECK_CURSOR_NOT_CLOSED(self);
3623
3624 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3625 self->mydb->moduleFlags.getReturnsNone);
3626}
3627
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003628/* Return size of entry */
3629static PyObject*
3630DBC_get_current_size(DBCursorObject* self, PyObject* args)
3631{
3632 int err, flags=DB_CURRENT;
3633 PyObject* retval = NULL;
3634 DBT key, data;
3635
3636 if (!PyArg_ParseTuple(args, ":get_current_size"))
3637 return NULL;
3638 CHECK_CURSOR_NOT_CLOSED(self);
3639 CLEAR_DBT(key);
3640 CLEAR_DBT(data);
3641
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003642 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003643 getting the record size. */
3644 data.flags = DB_DBT_USERMEM;
3645 data.ulen = 0;
3646 MYDB_BEGIN_ALLOW_THREADS;
3647 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3648 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003649 if (err == DB_BUFFER_SMALL || !err) {
3650 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003651 retval = PyInt_FromLong((long)data.size);
3652 err = 0;
3653 }
3654
3655 FREE_DBT(key);
3656 FREE_DBT(data);
3657 RETURN_IF_ERR();
3658 return retval;
3659}
3660
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003661static PyObject*
3662DBC_set_both(DBCursorObject* self, PyObject* args)
3663{
3664 int flags=0;
3665 PyObject *keyobj, *dataobj;
3666
3667 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3668 return NULL;
3669
Gregory P. Smith7441e652003-11-03 21:35:31 +00003670 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671 CHECK_CURSOR_NOT_CLOSED(self);
3672
3673 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3674 self->mydb->moduleFlags.cursorSetReturnsNone);
3675}
3676
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677
3678static PyObject*
3679DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3680{
3681 int err, irecno, flags=0;
3682 db_recno_t recno;
3683 DBT key, data;
3684 PyObject* retval;
3685 int dlen = -1;
3686 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003687 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003688
3689 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3690 &irecno, &flags, &dlen, &doff))
3691 return NULL;
3692
3693 CHECK_CURSOR_NOT_CLOSED(self);
3694
3695 CLEAR_DBT(key);
3696 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003697 /* use allocated space so DB will be able to realloc room for the real
3698 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699 key.data = malloc(sizeof(db_recno_t));
3700 if (key.data == NULL) {
3701 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3702 return NULL;
3703 }
3704 key.size = sizeof(db_recno_t);
3705 key.ulen = key.size;
3706 memcpy(key.data, &recno, sizeof(db_recno_t));
3707 key.flags = DB_DBT_REALLOC;
3708
3709 CLEAR_DBT(data);
3710 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3711 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3712 data.flags = DB_DBT_MALLOC;
3713 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003714 if (!add_partial_dbt(&data, dlen, doff)) {
3715 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003717 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003718
3719 MYDB_BEGIN_ALLOW_THREADS;
3720 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3721 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003722 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3723 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003724 Py_INCREF(Py_None);
3725 retval = Py_None;
3726 }
3727 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003728 retval = NULL;
3729 }
3730 else { /* Can only be used for BTrees, so no need to return int key */
3731 retval = Py_BuildValue("s#s#", key.data, key.size,
3732 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003733 FREE_DBT(data);
3734 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003735 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736
3737 return retval;
3738}
3739
3740
3741static PyObject*
3742DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3743{
3744 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3745}
3746
3747
3748static PyObject*
3749DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3750{
3751 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3752}
3753
3754
3755static PyObject*
3756DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3757{
3758 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3759}
3760
3761
3762static PyObject*
3763DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3764{
3765 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3766}
3767
3768
3769static PyObject*
3770DBC_join_item(DBCursorObject* self, PyObject* args)
3771{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003772 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003773 DBT key, data;
3774 PyObject* retval;
3775
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003776 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003777 return NULL;
3778
3779 CHECK_CURSOR_NOT_CLOSED(self);
3780
3781 CLEAR_DBT(key);
3782 CLEAR_DBT(data);
3783 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3784 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3785 key.flags = DB_DBT_MALLOC;
3786 }
3787
3788 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003789 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003791 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3792 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 Py_INCREF(Py_None);
3794 retval = Py_None;
3795 }
3796 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003797 retval = NULL;
3798 }
3799 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003800 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003801 FREE_DBT(key);
3802 }
3803
3804 return retval;
3805}
3806
3807
3808
3809/* --------------------------------------------------------------------- */
3810/* DBEnv methods */
3811
3812
3813static PyObject*
3814DBEnv_close(DBEnvObject* self, PyObject* args)
3815{
3816 int err, flags = 0;
3817
3818 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3819 return NULL;
3820 if (!self->closed) { /* Don't close more than once */
3821 MYDB_BEGIN_ALLOW_THREADS;
3822 err = self->db_env->close(self->db_env, flags);
3823 MYDB_END_ALLOW_THREADS;
3824 /* after calling DBEnv->close, regardless of error, this DBEnv
3825 * may not be accessed again (BerkeleyDB docs). */
3826 self->closed = 1;
3827 self->db_env = NULL;
3828 RETURN_IF_ERR();
3829 }
3830 RETURN_NONE();
3831}
3832
3833
3834static PyObject*
3835DBEnv_open(DBEnvObject* self, PyObject* args)
3836{
3837 int err, flags=0, mode=0660;
3838 char *db_home;
3839
3840 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3841 return NULL;
3842
3843 CHECK_ENV_NOT_CLOSED(self);
3844
3845 MYDB_BEGIN_ALLOW_THREADS;
3846 err = self->db_env->open(self->db_env, db_home, flags, mode);
3847 MYDB_END_ALLOW_THREADS;
3848 RETURN_IF_ERR();
3849 self->closed = 0;
3850 self->flags = flags;
3851 RETURN_NONE();
3852}
3853
3854
3855static PyObject*
3856DBEnv_remove(DBEnvObject* self, PyObject* args)
3857{
3858 int err, flags=0;
3859 char *db_home;
3860
3861 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3862 return NULL;
3863 CHECK_ENV_NOT_CLOSED(self);
3864 MYDB_BEGIN_ALLOW_THREADS;
3865 err = self->db_env->remove(self->db_env, db_home, flags);
3866 MYDB_END_ALLOW_THREADS;
3867 RETURN_IF_ERR();
3868 RETURN_NONE();
3869}
3870
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003871#if (DBVER >= 41)
3872static PyObject*
3873DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3874{
3875 int err;
3876 u_int32_t flags=0;
3877 char *file = NULL;
3878 char *database = NULL;
3879 PyObject *txnobj = NULL;
3880 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003881 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003882 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003883
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003884 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003885 &file, &database, &txnobj, &flags)) {
3886 return NULL;
3887 }
3888 if (!checkTxnObj(txnobj, &txn)) {
3889 return NULL;
3890 }
3891 CHECK_ENV_NOT_CLOSED(self);
3892 MYDB_BEGIN_ALLOW_THREADS;
3893 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3894 MYDB_END_ALLOW_THREADS;
3895 RETURN_IF_ERR();
3896 RETURN_NONE();
3897}
3898
3899static PyObject*
3900DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3901{
3902 int err;
3903 u_int32_t flags=0;
3904 char *file = NULL;
3905 char *database = NULL;
3906 char *newname = NULL;
3907 PyObject *txnobj = NULL;
3908 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003909 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003910 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003911
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003912 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003913 &file, &database, &newname, &txnobj, &flags)) {
3914 return NULL;
3915 }
3916 if (!checkTxnObj(txnobj, &txn)) {
3917 return NULL;
3918 }
3919 CHECK_ENV_NOT_CLOSED(self);
3920 MYDB_BEGIN_ALLOW_THREADS;
3921 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3922 flags);
3923 MYDB_END_ALLOW_THREADS;
3924 RETURN_IF_ERR();
3925 RETURN_NONE();
3926}
3927
3928static PyObject*
3929DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3930{
3931 int err;
3932 u_int32_t flags=0;
3933 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003934 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003935
3936 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3937 &passwd, &flags)) {
3938 return NULL;
3939 }
3940
3941 MYDB_BEGIN_ALLOW_THREADS;
3942 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3943 MYDB_END_ALLOW_THREADS;
3944
3945 RETURN_IF_ERR();
3946 RETURN_NONE();
3947}
3948#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003949
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003950#if (DBVER >= 40)
3951static PyObject*
3952DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3953{
3954 int err;
3955 u_int32_t flags=0;
3956 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003957 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003958
3959 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3960 &timeout, &flags)) {
3961 return NULL;
3962 }
3963
3964 MYDB_BEGIN_ALLOW_THREADS;
3965 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3966 MYDB_END_ALLOW_THREADS;
3967
3968 RETURN_IF_ERR();
3969 RETURN_NONE();
3970}
3971#endif /* DBVER >= 40 */
3972
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003973static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003974DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3975{
3976 int err;
3977 long shm_key = 0;
3978
3979 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3980 return NULL;
3981 CHECK_ENV_NOT_CLOSED(self);
3982
3983 err = self->db_env->set_shm_key(self->db_env, shm_key);
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3986}
3987
3988static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3990{
3991 int err, gbytes=0, bytes=0, ncache=0;
3992
3993 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3994 &gbytes, &bytes, &ncache))
3995 return NULL;
3996 CHECK_ENV_NOT_CLOSED(self);
3997
3998 MYDB_BEGIN_ALLOW_THREADS;
3999 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4000 MYDB_END_ALLOW_THREADS;
4001 RETURN_IF_ERR();
4002 RETURN_NONE();
4003}
4004
4005
4006#if (DBVER >= 32)
4007static PyObject*
4008DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4009{
4010 int err, flags=0, onoff=0;
4011
4012 if (!PyArg_ParseTuple(args, "ii:set_flags",
4013 &flags, &onoff))
4014 return NULL;
4015 CHECK_ENV_NOT_CLOSED(self);
4016
4017 MYDB_BEGIN_ALLOW_THREADS;
4018 err = self->db_env->set_flags(self->db_env, flags, onoff);
4019 MYDB_END_ALLOW_THREADS;
4020 RETURN_IF_ERR();
4021 RETURN_NONE();
4022}
4023#endif
4024
4025
4026static PyObject*
4027DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4028{
4029 int err;
4030 char *dir;
4031
4032 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4033 return NULL;
4034 CHECK_ENV_NOT_CLOSED(self);
4035
4036 MYDB_BEGIN_ALLOW_THREADS;
4037 err = self->db_env->set_data_dir(self->db_env, dir);
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4041}
4042
4043
4044static PyObject*
4045DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4046{
4047 int err, lg_bsize;
4048
4049 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4050 return NULL;
4051 CHECK_ENV_NOT_CLOSED(self);
4052
4053 MYDB_BEGIN_ALLOW_THREADS;
4054 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4055 MYDB_END_ALLOW_THREADS;
4056 RETURN_IF_ERR();
4057 RETURN_NONE();
4058}
4059
4060
4061static PyObject*
4062DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4063{
4064 int err;
4065 char *dir;
4066
4067 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_dir(self->db_env, dir);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078static PyObject*
4079DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4080{
4081 int err, lg_max;
4082
4083 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4084 return NULL;
4085 CHECK_ENV_NOT_CLOSED(self);
4086
4087 MYDB_BEGIN_ALLOW_THREADS;
4088 err = self->db_env->set_lg_max(self->db_env, lg_max);
4089 MYDB_END_ALLOW_THREADS;
4090 RETURN_IF_ERR();
4091 RETURN_NONE();
4092}
4093
4094
Neal Norwitz84562352005-10-20 04:30:15 +00004095#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004096static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004097DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4098{
4099 int err, lg_max;
4100
4101 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4102 return NULL;
4103 CHECK_ENV_NOT_CLOSED(self);
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4107 MYDB_END_ALLOW_THREADS;
4108 RETURN_IF_ERR();
4109 RETURN_NONE();
4110}
Neal Norwitz84562352005-10-20 04:30:15 +00004111#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004112
4113
4114static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004115DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4116{
4117 int err, lk_detect;
4118
4119 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
4129
4130
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004131#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004132static PyObject*
4133DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4134{
4135 int err, max;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_max(self->db_env, max);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004147#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004148
4149
4150#if (DBVER >= 32)
4151
4152static PyObject*
4153DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4154{
4155 int err, max;
4156
4157 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4158 return NULL;
4159 CHECK_ENV_NOT_CLOSED(self);
4160
4161 MYDB_BEGIN_ALLOW_THREADS;
4162 err = self->db_env->set_lk_max_locks(self->db_env, max);
4163 MYDB_END_ALLOW_THREADS;
4164 RETURN_IF_ERR();
4165 RETURN_NONE();
4166}
4167
4168
4169static PyObject*
4170DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4171{
4172 int err, max;
4173
4174 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
4178 MYDB_BEGIN_ALLOW_THREADS;
4179 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4180 MYDB_END_ALLOW_THREADS;
4181 RETURN_IF_ERR();
4182 RETURN_NONE();
4183}
4184
4185
4186static PyObject*
4187DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4188{
4189 int err, max;
4190
4191 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4194
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_lk_max_objects(self->db_env, max);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
4201
4202#endif
4203
4204
4205static PyObject*
4206DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4207{
4208 int err, mp_mmapsize;
4209
4210 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4211 return NULL;
4212 CHECK_ENV_NOT_CLOSED(self);
4213
4214 MYDB_BEGIN_ALLOW_THREADS;
4215 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4216 MYDB_END_ALLOW_THREADS;
4217 RETURN_IF_ERR();
4218 RETURN_NONE();
4219}
4220
4221
4222static PyObject*
4223DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4224{
4225 int err;
4226 char *dir;
4227
4228 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4229 return NULL;
4230 CHECK_ENV_NOT_CLOSED(self);
4231
4232 MYDB_BEGIN_ALLOW_THREADS;
4233 err = self->db_env->set_tmp_dir(self->db_env, dir);
4234 MYDB_END_ALLOW_THREADS;
4235 RETURN_IF_ERR();
4236 RETURN_NONE();
4237}
4238
4239
4240static PyObject*
4241DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4242{
4243 int flags = 0;
4244 PyObject* txnobj = NULL;
4245 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004246 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004247
4248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4249 &txnobj, &flags))
4250 return NULL;
4251
4252 if (!checkTxnObj(txnobj, &txn))
4253 return NULL;
4254 CHECK_ENV_NOT_CLOSED(self);
4255
4256 return (PyObject*)newDBTxnObject(self, txn, flags);
4257}
4258
4259
4260static PyObject*
4261DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4262{
4263 int err, kbyte=0, min=0, flags=0;
4264
4265 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4266 return NULL;
4267 CHECK_ENV_NOT_CLOSED(self);
4268
4269 MYDB_BEGIN_ALLOW_THREADS;
4270#if (DBVER >= 40)
4271 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4272#else
4273 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4274#endif
4275 MYDB_END_ALLOW_THREADS;
4276 RETURN_IF_ERR();
4277 RETURN_NONE();
4278}
4279
4280
4281static PyObject*
4282DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4283{
4284 int err, max;
4285
4286 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4287 return NULL;
4288 CHECK_ENV_NOT_CLOSED(self);
4289
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004290 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004291 RETURN_IF_ERR();
4292 RETURN_NONE();
4293}
4294
4295
4296static PyObject*
4297DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4298{
4299 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004300 long stamp;
4301 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004302
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004303 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004304 return NULL;
4305 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004306 timestamp = (time_t)stamp;
4307 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004308 RETURN_IF_ERR();
4309 RETURN_NONE();
4310}
4311
4312
4313static PyObject*
4314DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4315{
4316 int err, atype, flags=0;
4317 int aborted = 0;
4318
4319 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4320 return NULL;
4321 CHECK_ENV_NOT_CLOSED(self);
4322
4323 MYDB_BEGIN_ALLOW_THREADS;
4324#if (DBVER >= 40)
4325 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4326#else
4327 err = lock_detect(self->db_env, flags, atype, &aborted);
4328#endif
4329 MYDB_END_ALLOW_THREADS;
4330 RETURN_IF_ERR();
4331 return PyInt_FromLong(aborted);
4332}
4333
4334
4335static PyObject*
4336DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4337{
4338 int flags=0;
4339 int locker, lock_mode;
4340 DBT obj;
4341 PyObject* objobj;
4342
4343 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4344 return NULL;
4345
4346
4347 if (!make_dbt(objobj, &obj))
4348 return NULL;
4349
4350 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4351}
4352
4353
4354static PyObject*
4355DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4356{
4357 int err;
4358 u_int32_t theID;
4359
4360 if (!PyArg_ParseTuple(args, ":lock_id"))
4361 return NULL;
4362
4363 CHECK_ENV_NOT_CLOSED(self);
4364 MYDB_BEGIN_ALLOW_THREADS;
4365#if (DBVER >= 40)
4366 err = self->db_env->lock_id(self->db_env, &theID);
4367#else
4368 err = lock_id(self->db_env, &theID);
4369#endif
4370 MYDB_END_ALLOW_THREADS;
4371 RETURN_IF_ERR();
4372
4373 return PyInt_FromLong((long)theID);
4374}
4375
4376
4377static PyObject*
4378DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4379{
4380 int err;
4381 DBLockObject* dblockobj;
4382
4383 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4384 return NULL;
4385
4386 CHECK_ENV_NOT_CLOSED(self);
4387 MYDB_BEGIN_ALLOW_THREADS;
4388#if (DBVER >= 40)
4389 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4390#else
4391 err = lock_put(self->db_env, &dblockobj->lock);
4392#endif
4393 MYDB_END_ALLOW_THREADS;
4394 RETURN_IF_ERR();
4395 RETURN_NONE();
4396}
4397
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004398#if (DBVER >= 44)
4399static PyObject*
4400DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4401{
4402 int err;
4403 char *file;
4404 u_int32_t flags = 0;
4405 static char* kwnames[] = { "file", "flags", NULL};
4406
4407 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4408 &file, &flags))
4409 return NULL;
4410 CHECK_ENV_NOT_CLOSED(self);
4411
4412 MYDB_BEGIN_ALLOW_THREADS;
4413 err = self->db_env->lsn_reset(self->db_env, file, flags);
4414 MYDB_END_ALLOW_THREADS;
4415 RETURN_IF_ERR();
4416 RETURN_NONE();
4417}
4418#endif /* DBVER >= 4.4 */
4419
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004420#if (DBVER >= 40)
4421static PyObject*
4422DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4423{
4424 int err;
4425 DB_LOG_STAT* statp = NULL;
4426 PyObject* d = NULL;
4427 u_int32_t flags = 0;
4428
4429 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4430 return NULL;
4431 CHECK_ENV_NOT_CLOSED(self);
4432
4433 MYDB_BEGIN_ALLOW_THREADS;
4434 err = self->db_env->log_stat(self->db_env, &statp, flags);
4435 MYDB_END_ALLOW_THREADS;
4436 RETURN_IF_ERR();
4437
4438 /* Turn the stat structure into a dictionary */
4439 d = PyDict_New();
4440 if (d == NULL) {
4441 if (statp)
4442 free(statp);
4443 return NULL;
4444 }
4445
4446#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4447
4448 MAKE_ENTRY(magic);
4449 MAKE_ENTRY(version);
4450 MAKE_ENTRY(mode);
4451 MAKE_ENTRY(lg_bsize);
4452#if (DBVER >= 44)
4453 MAKE_ENTRY(lg_size);
4454 MAKE_ENTRY(record);
4455#endif
4456#if (DBVER <= 40)
4457 MAKE_ENTRY(lg_max);
4458#endif
4459 MAKE_ENTRY(w_mbytes);
4460 MAKE_ENTRY(w_bytes);
4461 MAKE_ENTRY(wc_mbytes);
4462 MAKE_ENTRY(wc_bytes);
4463 MAKE_ENTRY(wcount);
4464 MAKE_ENTRY(wcount_fill);
4465#if (DBVER >= 44)
4466 MAKE_ENTRY(rcount);
4467#endif
4468 MAKE_ENTRY(scount);
4469 MAKE_ENTRY(cur_file);
4470 MAKE_ENTRY(cur_offset);
4471 MAKE_ENTRY(disk_file);
4472 MAKE_ENTRY(disk_offset);
4473 MAKE_ENTRY(maxcommitperflush);
4474 MAKE_ENTRY(mincommitperflush);
4475 MAKE_ENTRY(regsize);
4476 MAKE_ENTRY(region_wait);
4477 MAKE_ENTRY(region_nowait);
4478
4479#undef MAKE_ENTRY
4480 free(statp);
4481 return d;
4482} /* DBEnv_log_stat */
4483#endif /* DBVER >= 4.0 for log_stat method */
4484
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004485
4486static PyObject*
4487DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4488{
4489 int err;
4490 DB_LOCK_STAT* sp;
4491 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004492 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004493
4494 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4495 return NULL;
4496 CHECK_ENV_NOT_CLOSED(self);
4497
4498 MYDB_BEGIN_ALLOW_THREADS;
4499#if (DBVER >= 40)
4500 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4501#else
4502#if (DBVER >= 33)
4503 err = lock_stat(self->db_env, &sp);
4504#else
4505 err = lock_stat(self->db_env, &sp, NULL);
4506#endif
4507#endif
4508 MYDB_END_ALLOW_THREADS;
4509 RETURN_IF_ERR();
4510
4511 /* Turn the stat structure into a dictionary */
4512 d = PyDict_New();
4513 if (d == NULL) {
4514 free(sp);
4515 return NULL;
4516 }
4517
4518#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4519
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004520#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004521 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004522#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004523 MAKE_ENTRY(nmodes);
4524#if (DBVER >= 32)
4525 MAKE_ENTRY(maxlocks);
4526 MAKE_ENTRY(maxlockers);
4527 MAKE_ENTRY(maxobjects);
4528 MAKE_ENTRY(nlocks);
4529 MAKE_ENTRY(maxnlocks);
4530#endif
4531 MAKE_ENTRY(nlockers);
4532 MAKE_ENTRY(maxnlockers);
4533#if (DBVER >= 32)
4534 MAKE_ENTRY(nobjects);
4535 MAKE_ENTRY(maxnobjects);
4536#endif
4537 MAKE_ENTRY(nrequests);
4538 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004539#if (DBVER < 44)
4540 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004542#else
4543 MAKE_ENTRY(lock_nowait);
4544 MAKE_ENTRY(lock_wait);
4545#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546 MAKE_ENTRY(ndeadlocks);
4547 MAKE_ENTRY(regsize);
4548 MAKE_ENTRY(region_wait);
4549 MAKE_ENTRY(region_nowait);
4550
4551#undef MAKE_ENTRY
4552 free(sp);
4553 return d;
4554}
4555
4556
4557static PyObject*
4558DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4559{
4560 int flags=0;
4561 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004562 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 PyObject* list;
4564 PyObject* item = NULL;
4565
4566 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4567 return NULL;
4568
4569 CHECK_ENV_NOT_CLOSED(self);
4570 MYDB_BEGIN_ALLOW_THREADS;
4571#if (DBVER >= 40)
4572 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4573#elif (DBVER == 33)
4574 err = log_archive(self->db_env, &log_list, flags);
4575#else
4576 err = log_archive(self->db_env, &log_list, flags, NULL);
4577#endif
4578 MYDB_END_ALLOW_THREADS;
4579 RETURN_IF_ERR();
4580
Gregory P. Smithbad47452006-06-05 00:33:35 +00004581 list = PyList_New(0);
4582 if (list == NULL) {
4583 if (log_list)
4584 free(log_list);
4585 return NULL;
4586 }
4587
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004588 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004589 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004590 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4591 item = PyString_FromString (*log_list);
4592 if (item == NULL) {
4593 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004594 list = NULL;
4595 break;
4596 }
4597 PyList_Append(list, item);
4598 Py_DECREF(item);
4599 }
4600 free(log_list_start);
4601 }
4602 return list;
4603}
4604
4605
4606static PyObject*
4607DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4608{
4609 int err;
4610 DB_TXN_STAT* sp;
4611 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004612 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613
4614 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4615 return NULL;
4616 CHECK_ENV_NOT_CLOSED(self);
4617
4618 MYDB_BEGIN_ALLOW_THREADS;
4619#if (DBVER >= 40)
4620 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4621#elif (DBVER == 33)
4622 err = txn_stat(self->db_env, &sp);
4623#else
4624 err = txn_stat(self->db_env, &sp, NULL);
4625#endif
4626 MYDB_END_ALLOW_THREADS;
4627 RETURN_IF_ERR();
4628
4629 /* Turn the stat structure into a dictionary */
4630 d = PyDict_New();
4631 if (d == NULL) {
4632 free(sp);
4633 return NULL;
4634 }
4635
4636#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4637
4638 MAKE_ENTRY(time_ckp);
4639 MAKE_ENTRY(last_txnid);
4640 MAKE_ENTRY(maxtxns);
4641 MAKE_ENTRY(nactive);
4642 MAKE_ENTRY(maxnactive);
4643 MAKE_ENTRY(nbegins);
4644 MAKE_ENTRY(naborts);
4645 MAKE_ENTRY(ncommits);
4646 MAKE_ENTRY(regsize);
4647 MAKE_ENTRY(region_wait);
4648 MAKE_ENTRY(region_nowait);
4649
4650#undef MAKE_ENTRY
4651 free(sp);
4652 return d;
4653}
4654
4655
4656static PyObject*
4657DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4658{
4659 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004660 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661
4662 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4663 return NULL;
4664 CHECK_ENV_NOT_CLOSED(self);
4665
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004666 if (self->moduleFlags.getReturnsNone)
4667 ++oldValue;
4668 if (self->moduleFlags.cursorSetReturnsNone)
4669 ++oldValue;
4670 self->moduleFlags.getReturnsNone = (flags >= 1);
4671 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004672 return PyInt_FromLong(oldValue);
4673}
4674
4675
4676/* --------------------------------------------------------------------- */
4677/* DBTxn methods */
4678
4679
4680static PyObject*
4681DBTxn_commit(DBTxnObject* self, PyObject* args)
4682{
4683 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004685
4686 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4687 return NULL;
4688
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004689 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004690 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4691 "after txn_commit or txn_abort");
4692 PyErr_SetObject(DBError, t);
4693 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004694 return NULL;
4695 }
4696 txn = self->txn;
4697 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004698 MYDB_BEGIN_ALLOW_THREADS;
4699#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004700 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004701#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004702 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004703#endif
4704 MYDB_END_ALLOW_THREADS;
4705 RETURN_IF_ERR();
4706 RETURN_NONE();
4707}
4708
4709static PyObject*
4710DBTxn_prepare(DBTxnObject* self, PyObject* args)
4711{
4712#if (DBVER >= 33)
4713 int err;
4714 char* gid=NULL;
4715 int gid_size=0;
4716
4717 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4718 return NULL;
4719
4720 if (gid_size != DB_XIDDATASIZE) {
4721 PyErr_SetString(PyExc_TypeError,
4722 "gid must be DB_XIDDATASIZE bytes long");
4723 return NULL;
4724 }
4725
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004726 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004727 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4728 "after txn_commit or txn_abort");
4729 PyErr_SetObject(DBError, t);
4730 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004731 return NULL;
4732 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004733 MYDB_BEGIN_ALLOW_THREADS;
4734#if (DBVER >= 40)
4735 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4736#else
4737 err = txn_prepare(self->txn, (u_int8_t*)gid);
4738#endif
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4742#else
4743 int err;
4744
4745 if (!PyArg_ParseTuple(args, ":prepare"))
4746 return NULL;
4747
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004748 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004749 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4750 "after txn_commit or txn_abort");
4751 PyErr_SetObject(DBError, t);
4752 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004753 return NULL;
4754 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004755 MYDB_BEGIN_ALLOW_THREADS;
4756 err = txn_prepare(self->txn);
4757 MYDB_END_ALLOW_THREADS;
4758 RETURN_IF_ERR();
4759 RETURN_NONE();
4760#endif
4761}
4762
4763
4764static PyObject*
4765DBTxn_abort(DBTxnObject* self, PyObject* args)
4766{
4767 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769
4770 if (!PyArg_ParseTuple(args, ":abort"))
4771 return NULL;
4772
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004773 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004774 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4775 "after txn_commit or txn_abort");
4776 PyErr_SetObject(DBError, t);
4777 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004778 return NULL;
4779 }
4780 txn = self->txn;
4781 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004782 MYDB_BEGIN_ALLOW_THREADS;
4783#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004784 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004786 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004787#endif
4788 MYDB_END_ALLOW_THREADS;
4789 RETURN_IF_ERR();
4790 RETURN_NONE();
4791}
4792
4793
4794static PyObject*
4795DBTxn_id(DBTxnObject* self, PyObject* args)
4796{
4797 int id;
4798
4799 if (!PyArg_ParseTuple(args, ":id"))
4800 return NULL;
4801
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004802 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004803 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4804 "after txn_commit or txn_abort");
4805 PyErr_SetObject(DBError, t);
4806 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004807 return NULL;
4808 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809 MYDB_BEGIN_ALLOW_THREADS;
4810#if (DBVER >= 40)
4811 id = self->txn->id(self->txn);
4812#else
4813 id = txn_id(self->txn);
4814#endif
4815 MYDB_END_ALLOW_THREADS;
4816 return PyInt_FromLong(id);
4817}
4818
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004819#if (DBVER >= 43)
4820/* --------------------------------------------------------------------- */
4821/* DBSequence methods */
4822
4823
4824static PyObject*
4825DBSequence_close(DBSequenceObject* self, PyObject* args)
4826{
4827 int err, flags=0;
4828 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4829 return NULL;
4830 CHECK_SEQUENCE_NOT_CLOSED(self)
4831
4832 MYDB_BEGIN_ALLOW_THREADS
4833 err = self->sequence->close(self->sequence, flags);
4834 self->sequence = NULL;
4835 MYDB_END_ALLOW_THREADS
4836
4837 RETURN_IF_ERR();
4838
4839 RETURN_NONE();
4840}
4841
4842static PyObject*
4843DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4844{
4845 int err, flags = 0;
4846 int delta = 1;
4847 db_seq_t value;
4848 PyObject *txnobj = NULL;
4849 DB_TXN *txn = NULL;
4850 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4851 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4852 return NULL;
4853 CHECK_SEQUENCE_NOT_CLOSED(self)
4854
4855 if (!checkTxnObj(txnobj, &txn))
4856 return NULL;
4857
4858 MYDB_BEGIN_ALLOW_THREADS
4859 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4860 MYDB_END_ALLOW_THREADS
4861
4862 RETURN_IF_ERR();
4863 return PyLong_FromLongLong(value);
4864
4865}
4866
4867static PyObject*
4868DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4869{
4870 if (!PyArg_ParseTuple(args,":get_dbp"))
4871 return NULL;
4872 CHECK_SEQUENCE_NOT_CLOSED(self)
4873 Py_INCREF(self->mydb);
4874 return (PyObject* )self->mydb;
4875}
4876
4877static PyObject*
4878DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4879{
4880 int err;
4881 DBT key;
4882 CHECK_SEQUENCE_NOT_CLOSED(self)
4883 MYDB_BEGIN_ALLOW_THREADS
4884 err = self->sequence->get_key(self->sequence, &key);
4885 MYDB_END_ALLOW_THREADS
4886
4887 RETURN_IF_ERR();
4888
4889 return PyString_FromStringAndSize(key.data, key.size);
4890}
4891
4892static PyObject*
4893DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4894{
4895 int err;
4896 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004897 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004898 return NULL;
4899 CHECK_SEQUENCE_NOT_CLOSED(self)
4900
4901 MYDB_BEGIN_ALLOW_THREADS
4902 err = self->sequence->initial_value(self->sequence, value);
4903 MYDB_END_ALLOW_THREADS
4904
4905 RETURN_IF_ERR();
4906
4907 RETURN_NONE();
4908}
4909
4910static PyObject*
4911DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4912{
4913 int err, flags = 0;
4914 PyObject* keyobj;
4915 PyObject *txnobj = NULL;
4916 DB_TXN *txn = NULL;
4917 DBT key;
4918
4919 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004920 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004921 return NULL;
4922
4923 if (!checkTxnObj(txnobj, &txn))
4924 return NULL;
4925
4926 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4927 return NULL;
4928
4929 MYDB_BEGIN_ALLOW_THREADS
4930 err = self->sequence->open(self->sequence, txn, &key, flags);
4931 MYDB_END_ALLOW_THREADS
4932
4933 CLEAR_DBT(key);
4934 RETURN_IF_ERR();
4935
4936 RETURN_NONE();
4937}
4938
4939static PyObject*
4940DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4941{
4942 int err, flags = 0;
4943 PyObject *txnobj = NULL;
4944 DB_TXN *txn = NULL;
4945
4946 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004947 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004948 return NULL;
4949
4950 if (!checkTxnObj(txnobj, &txn))
4951 return NULL;
4952
4953 CHECK_SEQUENCE_NOT_CLOSED(self)
4954
4955 MYDB_BEGIN_ALLOW_THREADS
4956 err = self->sequence->remove(self->sequence, txn, flags);
4957 MYDB_END_ALLOW_THREADS
4958
4959 RETURN_IF_ERR();
4960 RETURN_NONE();
4961}
4962
4963static PyObject*
4964DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4965{
4966 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004967 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004968 return NULL;
4969 CHECK_SEQUENCE_NOT_CLOSED(self)
4970
4971 MYDB_BEGIN_ALLOW_THREADS
4972 err = self->sequence->set_cachesize(self->sequence, size);
4973 MYDB_END_ALLOW_THREADS
4974
4975 RETURN_IF_ERR();
4976 RETURN_NONE();
4977}
4978
4979static PyObject*
4980DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4981{
4982 int err, size;
4983 if (!PyArg_ParseTuple(args,":get_cachesize"))
4984 return NULL;
4985 CHECK_SEQUENCE_NOT_CLOSED(self)
4986
4987 MYDB_BEGIN_ALLOW_THREADS
4988 err = self->sequence->get_cachesize(self->sequence, &size);
4989 MYDB_END_ALLOW_THREADS
4990
4991 RETURN_IF_ERR();
4992 return PyInt_FromLong(size);
4993}
4994
4995static PyObject*
4996DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4997{
4998 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004999 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005000 return NULL;
5001 CHECK_SEQUENCE_NOT_CLOSED(self)
5002
5003 MYDB_BEGIN_ALLOW_THREADS
5004 err = self->sequence->set_flags(self->sequence, flags);
5005 MYDB_END_ALLOW_THREADS
5006
5007 RETURN_IF_ERR();
5008 RETURN_NONE();
5009
5010}
5011
5012static PyObject*
5013DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5014{
5015 unsigned int flags;
5016 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005017 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005018 return NULL;
5019 CHECK_SEQUENCE_NOT_CLOSED(self)
5020
5021 MYDB_BEGIN_ALLOW_THREADS
5022 err = self->sequence->get_flags(self->sequence, &flags);
5023 MYDB_END_ALLOW_THREADS
5024
5025 RETURN_IF_ERR();
5026 return PyInt_FromLong((int)flags);
5027}
5028
5029static PyObject*
5030DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5031{
5032 int err;
5033 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005034 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005035 return NULL;
5036 CHECK_SEQUENCE_NOT_CLOSED(self)
5037
5038 MYDB_BEGIN_ALLOW_THREADS
5039 err = self->sequence->set_range(self->sequence, min, max);
5040 MYDB_END_ALLOW_THREADS
5041
5042 RETURN_IF_ERR();
5043 RETURN_NONE();
5044}
5045
5046static PyObject*
5047DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5048{
5049 int err;
5050 db_seq_t min, max;
5051 if (!PyArg_ParseTuple(args,":get_range"))
5052 return NULL;
5053 CHECK_SEQUENCE_NOT_CLOSED(self)
5054
5055 MYDB_BEGIN_ALLOW_THREADS
5056 err = self->sequence->get_range(self->sequence, &min, &max);
5057 MYDB_END_ALLOW_THREADS
5058
5059 RETURN_IF_ERR();
5060 return Py_BuildValue("(LL)", min, max);
5061}
5062
5063static PyObject*
5064DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5065{
5066 int err, flags = 0;
5067 DB_SEQUENCE_STAT* sp = NULL;
5068 PyObject* dict_stat;
5069 static char* kwnames[] = {"flags", NULL };
5070 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5071 return NULL;
5072 CHECK_SEQUENCE_NOT_CLOSED(self);
5073
5074 MYDB_BEGIN_ALLOW_THREADS;
5075 err = self->sequence->stat(self->sequence, &sp, flags);
5076 MYDB_END_ALLOW_THREADS;
5077 RETURN_IF_ERR();
5078
5079 if ((dict_stat = PyDict_New()) == NULL) {
5080 free(sp);
5081 return NULL;
5082 }
5083
5084
5085#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5086#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5087
5088 MAKE_INT_ENTRY(wait);
5089 MAKE_INT_ENTRY(nowait);
5090 MAKE_LONG_LONG_ENTRY(current);
5091 MAKE_LONG_LONG_ENTRY(value);
5092 MAKE_LONG_LONG_ENTRY(last_value);
5093 MAKE_LONG_LONG_ENTRY(min);
5094 MAKE_LONG_LONG_ENTRY(max);
5095 MAKE_INT_ENTRY(cache_size);
5096 MAKE_INT_ENTRY(flags);
5097
5098#undef MAKE_INT_ENTRY
5099#undef MAKE_LONG_LONG_ENTRY
5100
5101 free(sp);
5102 return dict_stat;
5103}
5104#endif
5105
5106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005107/* --------------------------------------------------------------------- */
5108/* Method definition tables and type objects */
5109
5110static PyMethodDef DB_methods[] = {
5111 {"append", (PyCFunction)DB_append, METH_VARARGS},
5112#if (DBVER >= 33)
5113 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5114#endif
5115 {"close", (PyCFunction)DB_close, METH_VARARGS},
5116#if (DBVER >= 32)
5117 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5118 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5119#endif
5120 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5121 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5122 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5123 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005124#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005125 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005126#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005127 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5128 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5129 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5130 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5131 {"join", (PyCFunction)DB_join, METH_VARARGS},
5132 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5133 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5134 {"items", (PyCFunction)DB_items, METH_VARARGS},
5135 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5136 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5137 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5138 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5139 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5140 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005141#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005142 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005143#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005144 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005145#if (DBVER >= 41)
5146 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5147#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005148 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5149 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5150 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5151 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5152 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5153 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5154 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5155 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5156 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5157#if (DBVER >= 32)
5158 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5159#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005160 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005161 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5162#if (DBVER >= 33)
5163 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5164#endif
5165 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5166 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5167 {"values", (PyCFunction)DB_values, METH_VARARGS},
5168 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5169 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5170 {NULL, NULL} /* sentinel */
5171};
5172
5173
5174static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005175 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 (binaryfunc)DB_subscript, /*mp_subscript*/
5177 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5178};
5179
5180
5181static PyMethodDef DBCursor_methods[] = {
5182 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5183 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5184 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5185 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5186 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5187 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5188 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005189#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005190 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005191#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005192 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5193 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5194 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5195 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5196 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5197 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5198 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5199 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005200 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005201 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005202 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5203 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5204 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5205 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5206 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5207 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5208 {NULL, NULL} /* sentinel */
5209};
5210
5211
5212static PyMethodDef DBEnv_methods[] = {
5213 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5214 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5215 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005216#if (DBVER >= 41)
5217 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5218 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5219 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5220#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005221#if (DBVER >= 40)
5222 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5223#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005224 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005225 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5226 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5227#if (DBVER >= 32)
5228 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5229#endif
5230 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5231 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5232 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005233#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005234 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005236 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005237#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005238 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005239#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005240#if (DBVER >= 32)
5241 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5242 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5243 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5244#endif
5245 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5246 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5247 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5248 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5249 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5250 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005251 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005252 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5253 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5254 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5255 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5256 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5257 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005258#if (DBVER >= 40)
5259 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5260#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005261#if (DBVER >= 44)
5262 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5265 {NULL, NULL} /* sentinel */
5266};
5267
5268
5269static PyMethodDef DBTxn_methods[] = {
5270 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5271 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5272 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5273 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5274 {NULL, NULL} /* sentinel */
5275};
5276
5277
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005278#if (DBVER >= 43)
5279static PyMethodDef DBSequence_methods[] = {
5280 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5281 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5282 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5283 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005284 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5285 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5286 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5287 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5288 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5289 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5290 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5291 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5292 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5293 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5294 {NULL, NULL} /* sentinel */
5295};
5296#endif
5297
5298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005299static PyObject*
5300DB_getattr(DBObject* self, char *name)
5301{
5302 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5303}
5304
5305
5306static PyObject*
5307DBEnv_getattr(DBEnvObject* self, char *name)
5308{
5309 if (!strcmp(name, "db_home")) {
5310 CHECK_ENV_NOT_CLOSED(self);
5311 if (self->db_env->db_home == NULL) {
5312 RETURN_NONE();
5313 }
5314 return PyString_FromString(self->db_env->db_home);
5315 }
5316
5317 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5318}
5319
5320
5321static PyObject*
5322DBCursor_getattr(DBCursorObject* self, char *name)
5323{
5324 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5325}
5326
5327static PyObject*
5328DBTxn_getattr(DBTxnObject* self, char *name)
5329{
5330 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5331}
5332
5333static PyObject*
5334DBLock_getattr(DBLockObject* self, char *name)
5335{
5336 return NULL;
5337}
5338
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005339#if (DBVER >= 43)
5340static PyObject*
5341DBSequence_getattr(DBSequenceObject* self, char *name)
5342{
5343 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5344}
5345#endif
5346
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005347statichere PyTypeObject DB_Type = {
5348 PyObject_HEAD_INIT(NULL)
5349 0, /*ob_size*/
5350 "DB", /*tp_name*/
5351 sizeof(DBObject), /*tp_basicsize*/
5352 0, /*tp_itemsize*/
5353 /* methods */
5354 (destructor)DB_dealloc, /*tp_dealloc*/
5355 0, /*tp_print*/
5356 (getattrfunc)DB_getattr, /*tp_getattr*/
5357 0, /*tp_setattr*/
5358 0, /*tp_compare*/
5359 0, /*tp_repr*/
5360 0, /*tp_as_number*/
5361 0, /*tp_as_sequence*/
5362 &DB_mapping,/*tp_as_mapping*/
5363 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005364#ifdef HAVE_WEAKREF
5365 0, /* tp_call */
5366 0, /* tp_str */
5367 0, /* tp_getattro */
5368 0, /* tp_setattro */
5369 0, /* tp_as_buffer */
5370 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5371 0, /* tp_doc */
5372 0, /* tp_traverse */
5373 0, /* tp_clear */
5374 0, /* tp_richcompare */
5375 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5376#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005377};
5378
5379
5380statichere PyTypeObject DBCursor_Type = {
5381 PyObject_HEAD_INIT(NULL)
5382 0, /*ob_size*/
5383 "DBCursor", /*tp_name*/
5384 sizeof(DBCursorObject), /*tp_basicsize*/
5385 0, /*tp_itemsize*/
5386 /* methods */
5387 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5388 0, /*tp_print*/
5389 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5390 0, /*tp_setattr*/
5391 0, /*tp_compare*/
5392 0, /*tp_repr*/
5393 0, /*tp_as_number*/
5394 0, /*tp_as_sequence*/
5395 0, /*tp_as_mapping*/
5396 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005397#ifdef HAVE_WEAKREF
5398 0, /* tp_call */
5399 0, /* tp_str */
5400 0, /* tp_getattro */
5401 0, /* tp_setattro */
5402 0, /* tp_as_buffer */
5403 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5404 0, /* tp_doc */
5405 0, /* tp_traverse */
5406 0, /* tp_clear */
5407 0, /* tp_richcompare */
5408 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5409#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005410};
5411
5412
5413statichere PyTypeObject DBEnv_Type = {
5414 PyObject_HEAD_INIT(NULL)
5415 0, /*ob_size*/
5416 "DBEnv", /*tp_name*/
5417 sizeof(DBEnvObject), /*tp_basicsize*/
5418 0, /*tp_itemsize*/
5419 /* methods */
5420 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5421 0, /*tp_print*/
5422 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5423 0, /*tp_setattr*/
5424 0, /*tp_compare*/
5425 0, /*tp_repr*/
5426 0, /*tp_as_number*/
5427 0, /*tp_as_sequence*/
5428 0, /*tp_as_mapping*/
5429 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005430#ifdef HAVE_WEAKREF
5431 0, /* tp_call */
5432 0, /* tp_str */
5433 0, /* tp_getattro */
5434 0, /* tp_setattro */
5435 0, /* tp_as_buffer */
5436 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5437 0, /* tp_doc */
5438 0, /* tp_traverse */
5439 0, /* tp_clear */
5440 0, /* tp_richcompare */
5441 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5442#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005443};
5444
5445statichere PyTypeObject DBTxn_Type = {
5446 PyObject_HEAD_INIT(NULL)
5447 0, /*ob_size*/
5448 "DBTxn", /*tp_name*/
5449 sizeof(DBTxnObject), /*tp_basicsize*/
5450 0, /*tp_itemsize*/
5451 /* methods */
5452 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5453 0, /*tp_print*/
5454 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5455 0, /*tp_setattr*/
5456 0, /*tp_compare*/
5457 0, /*tp_repr*/
5458 0, /*tp_as_number*/
5459 0, /*tp_as_sequence*/
5460 0, /*tp_as_mapping*/
5461 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005462#ifdef HAVE_WEAKREF
5463 0, /* tp_call */
5464 0, /* tp_str */
5465 0, /* tp_getattro */
5466 0, /* tp_setattro */
5467 0, /* tp_as_buffer */
5468 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5469 0, /* tp_doc */
5470 0, /* tp_traverse */
5471 0, /* tp_clear */
5472 0, /* tp_richcompare */
5473 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5474#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005475};
5476
5477
5478statichere PyTypeObject DBLock_Type = {
5479 PyObject_HEAD_INIT(NULL)
5480 0, /*ob_size*/
5481 "DBLock", /*tp_name*/
5482 sizeof(DBLockObject), /*tp_basicsize*/
5483 0, /*tp_itemsize*/
5484 /* methods */
5485 (destructor)DBLock_dealloc, /*tp_dealloc*/
5486 0, /*tp_print*/
5487 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5488 0, /*tp_setattr*/
5489 0, /*tp_compare*/
5490 0, /*tp_repr*/
5491 0, /*tp_as_number*/
5492 0, /*tp_as_sequence*/
5493 0, /*tp_as_mapping*/
5494 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005495#ifdef HAVE_WEAKREF
5496 0, /* tp_call */
5497 0, /* tp_str */
5498 0, /* tp_getattro */
5499 0, /* tp_setattro */
5500 0, /* tp_as_buffer */
5501 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5502 0, /* tp_doc */
5503 0, /* tp_traverse */
5504 0, /* tp_clear */
5505 0, /* tp_richcompare */
5506 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5507#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005508};
5509
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005510#if (DBVER >= 43)
5511statichere PyTypeObject DBSequence_Type = {
5512 PyObject_HEAD_INIT(NULL)
5513 0, /*ob_size*/
5514 "DBSequence", /*tp_name*/
5515 sizeof(DBSequenceObject), /*tp_basicsize*/
5516 0, /*tp_itemsize*/
5517 /* methods */
5518 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5519 0, /*tp_print*/
5520 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5521 0, /*tp_setattr*/
5522 0, /*tp_compare*/
5523 0, /*tp_repr*/
5524 0, /*tp_as_number*/
5525 0, /*tp_as_sequence*/
5526 0, /*tp_as_mapping*/
5527 0, /*tp_hash*/
5528#ifdef HAVE_WEAKREF
5529 0, /* tp_call */
5530 0, /* tp_str */
5531 0, /* tp_getattro */
5532 0, /* tp_setattro */
5533 0, /* tp_as_buffer */
5534 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5535 0, /* tp_doc */
5536 0, /* tp_traverse */
5537 0, /* tp_clear */
5538 0, /* tp_richcompare */
5539 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5540#endif
5541};
5542#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005543
5544/* --------------------------------------------------------------------- */
5545/* Module-level functions */
5546
5547static PyObject*
5548DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5549{
5550 PyObject* dbenvobj = NULL;
5551 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005552 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005553
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5555 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005556 return NULL;
5557 if (dbenvobj == Py_None)
5558 dbenvobj = NULL;
5559 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5560 makeTypeError("DBEnv", dbenvobj);
5561 return NULL;
5562 }
5563
5564 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5565}
5566
5567
5568static PyObject*
5569DBEnv_construct(PyObject* self, PyObject* args)
5570{
5571 int flags = 0;
5572 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5573 return (PyObject* )newDBEnvObject(flags);
5574}
5575
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005576#if (DBVER >= 43)
5577static PyObject*
5578DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5579{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005580 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005581 int flags = 0;
5582 static char* kwnames[] = { "db", "flags", NULL};
5583
5584 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5585 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005586 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005587 makeTypeError("DB", dbobj);
5588 return NULL;
5589 }
5590 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5591}
5592#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005593
5594static char bsddb_version_doc[] =
5595"Returns a tuple of major, minor, and patch release numbers of the\n\
5596underlying DB library.";
5597
5598static PyObject*
5599bsddb_version(PyObject* self, PyObject* args)
5600{
5601 int major, minor, patch;
5602
5603 if (!PyArg_ParseTuple(args, ":version"))
5604 return NULL;
5605 db_version(&major, &minor, &patch);
5606 return Py_BuildValue("(iii)", major, minor, patch);
5607}
5608
5609
5610/* List of functions defined in the module */
5611
5612static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005613 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5614 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5615#if (DBVER >= 43)
5616 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5617#endif
5618 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005619 {NULL, NULL} /* sentinel */
5620};
5621
5622
5623/* --------------------------------------------------------------------- */
5624/* Module initialization */
5625
5626
5627/* Convenience routine to export an integer value.
5628 * Errors are silently ignored, for better or for worse...
5629 */
5630#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5631
Gregory P. Smith41631e82003-09-21 00:08:14 +00005632#define MODULE_NAME_MAX_LEN 11
5633static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005634
5635DL_EXPORT(void) init_bsddb(void)
5636{
5637 PyObject* m;
5638 PyObject* d;
5639 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5640 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5641 PyObject* cvsid_s = PyString_FromString( rcs_id );
5642
5643 /* Initialize the type of the new type objects here; doing it here
5644 is required for portability to Windows without requiring C++. */
5645 DB_Type.ob_type = &PyType_Type;
5646 DBCursor_Type.ob_type = &PyType_Type;
5647 DBEnv_Type.ob_type = &PyType_Type;
5648 DBTxn_Type.ob_type = &PyType_Type;
5649 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005650#if (DBVER >= 43)
5651 DBSequence_Type.ob_type = &PyType_Type;
5652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653
5654
Mark Hammonda69d4092003-04-22 23:13:27 +00005655#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005657 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005658#endif
5659
5660 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005661 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005662 if (m == NULL)
5663 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664
5665 /* Add some symbolic constants to the module */
5666 d = PyModule_GetDict(m);
5667 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5668 PyDict_SetItemString(d, "cvsid", cvsid_s);
5669 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5670 Py_DECREF(pybsddb_version_s);
5671 pybsddb_version_s = NULL;
5672 Py_DECREF(cvsid_s);
5673 cvsid_s = NULL;
5674 Py_DECREF(db_version_s);
5675 db_version_s = NULL;
5676
5677 ADD_INT(d, DB_VERSION_MAJOR);
5678 ADD_INT(d, DB_VERSION_MINOR);
5679 ADD_INT(d, DB_VERSION_PATCH);
5680
5681 ADD_INT(d, DB_MAX_PAGES);
5682 ADD_INT(d, DB_MAX_RECORDS);
5683
Gregory P. Smith41631e82003-09-21 00:08:14 +00005684#if (DBVER >= 42)
5685 ADD_INT(d, DB_RPCCLIENT);
5686#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005687 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005688 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5689 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5690#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005691 ADD_INT(d, DB_XA_CREATE);
5692
5693 ADD_INT(d, DB_CREATE);
5694 ADD_INT(d, DB_NOMMAP);
5695 ADD_INT(d, DB_THREAD);
5696
5697 ADD_INT(d, DB_FORCE);
5698 ADD_INT(d, DB_INIT_CDB);
5699 ADD_INT(d, DB_INIT_LOCK);
5700 ADD_INT(d, DB_INIT_LOG);
5701 ADD_INT(d, DB_INIT_MPOOL);
5702 ADD_INT(d, DB_INIT_TXN);
5703#if (DBVER >= 32)
5704 ADD_INT(d, DB_JOINENV);
5705#endif
5706
5707 ADD_INT(d, DB_RECOVER);
5708 ADD_INT(d, DB_RECOVER_FATAL);
5709 ADD_INT(d, DB_TXN_NOSYNC);
5710 ADD_INT(d, DB_USE_ENVIRON);
5711 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5712
5713 ADD_INT(d, DB_LOCKDOWN);
5714 ADD_INT(d, DB_PRIVATE);
5715 ADD_INT(d, DB_SYSTEM_MEM);
5716
5717 ADD_INT(d, DB_TXN_SYNC);
5718 ADD_INT(d, DB_TXN_NOWAIT);
5719
5720 ADD_INT(d, DB_EXCL);
5721 ADD_INT(d, DB_FCNTL_LOCKING);
5722 ADD_INT(d, DB_ODDFILESIZE);
5723 ADD_INT(d, DB_RDWRMASTER);
5724 ADD_INT(d, DB_RDONLY);
5725 ADD_INT(d, DB_TRUNCATE);
5726#if (DBVER >= 32)
5727 ADD_INT(d, DB_EXTENT);
5728 ADD_INT(d, DB_CDB_ALLDB);
5729 ADD_INT(d, DB_VERIFY);
5730#endif
5731 ADD_INT(d, DB_UPGRADE);
5732
5733 ADD_INT(d, DB_AGGRESSIVE);
5734 ADD_INT(d, DB_NOORDERCHK);
5735 ADD_INT(d, DB_ORDERCHKONLY);
5736 ADD_INT(d, DB_PR_PAGE);
5737#if ! (DBVER >= 33)
5738 ADD_INT(d, DB_VRFY_FLAGMASK);
5739 ADD_INT(d, DB_PR_HEADERS);
5740#endif
5741 ADD_INT(d, DB_PR_RECOVERYTEST);
5742 ADD_INT(d, DB_SALVAGE);
5743
5744 ADD_INT(d, DB_LOCK_NORUN);
5745 ADD_INT(d, DB_LOCK_DEFAULT);
5746 ADD_INT(d, DB_LOCK_OLDEST);
5747 ADD_INT(d, DB_LOCK_RANDOM);
5748 ADD_INT(d, DB_LOCK_YOUNGEST);
5749#if (DBVER >= 33)
5750 ADD_INT(d, DB_LOCK_MAXLOCKS);
5751 ADD_INT(d, DB_LOCK_MINLOCKS);
5752 ADD_INT(d, DB_LOCK_MINWRITE);
5753#endif
5754
5755
5756#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005757 /* docs say to use zero instead */
5758 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005759#else
5760 ADD_INT(d, DB_LOCK_CONFLICT);
5761#endif
5762
5763 ADD_INT(d, DB_LOCK_DUMP);
5764 ADD_INT(d, DB_LOCK_GET);
5765 ADD_INT(d, DB_LOCK_INHERIT);
5766 ADD_INT(d, DB_LOCK_PUT);
5767 ADD_INT(d, DB_LOCK_PUT_ALL);
5768 ADD_INT(d, DB_LOCK_PUT_OBJ);
5769
5770 ADD_INT(d, DB_LOCK_NG);
5771 ADD_INT(d, DB_LOCK_READ);
5772 ADD_INT(d, DB_LOCK_WRITE);
5773 ADD_INT(d, DB_LOCK_NOWAIT);
5774#if (DBVER >= 32)
5775 ADD_INT(d, DB_LOCK_WAIT);
5776#endif
5777 ADD_INT(d, DB_LOCK_IWRITE);
5778 ADD_INT(d, DB_LOCK_IREAD);
5779 ADD_INT(d, DB_LOCK_IWR);
5780#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005781#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005782 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005783#else
5784 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5785#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005786 ADD_INT(d, DB_LOCK_WWRITE);
5787#endif
5788
5789 ADD_INT(d, DB_LOCK_RECORD);
5790 ADD_INT(d, DB_LOCK_UPGRADE);
5791#if (DBVER >= 32)
5792 ADD_INT(d, DB_LOCK_SWITCH);
5793#endif
5794#if (DBVER >= 33)
5795 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5796#endif
5797
5798 ADD_INT(d, DB_LOCK_NOWAIT);
5799 ADD_INT(d, DB_LOCK_RECORD);
5800 ADD_INT(d, DB_LOCK_UPGRADE);
5801
5802#if (DBVER >= 33)
5803 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005804#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005805 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005806#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005807 ADD_INT(d, DB_LSTAT_FREE);
5808 ADD_INT(d, DB_LSTAT_HELD);
5809#if (DBVER == 33)
5810 ADD_INT(d, DB_LSTAT_NOGRANT);
5811#endif
5812 ADD_INT(d, DB_LSTAT_PENDING);
5813 ADD_INT(d, DB_LSTAT_WAITING);
5814#endif
5815
5816 ADD_INT(d, DB_ARCH_ABS);
5817 ADD_INT(d, DB_ARCH_DATA);
5818 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005819#if (DBVER >= 42)
5820 ADD_INT(d, DB_ARCH_REMOVE);
5821#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005822
5823 ADD_INT(d, DB_BTREE);
5824 ADD_INT(d, DB_HASH);
5825 ADD_INT(d, DB_RECNO);
5826 ADD_INT(d, DB_QUEUE);
5827 ADD_INT(d, DB_UNKNOWN);
5828
5829 ADD_INT(d, DB_DUP);
5830 ADD_INT(d, DB_DUPSORT);
5831 ADD_INT(d, DB_RECNUM);
5832 ADD_INT(d, DB_RENUMBER);
5833 ADD_INT(d, DB_REVSPLITOFF);
5834 ADD_INT(d, DB_SNAPSHOT);
5835
5836 ADD_INT(d, DB_JOIN_NOSORT);
5837
5838 ADD_INT(d, DB_AFTER);
5839 ADD_INT(d, DB_APPEND);
5840 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005841#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005842 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005843#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005844#if (DBVER >= 41)
5845 _addIntToDict(d, "DB_CHECKPOINT", 0);
5846#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005847 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005848 ADD_INT(d, DB_CURLSN);
5849#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005850#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005851 ADD_INT(d, DB_COMMIT);
5852#endif
5853 ADD_INT(d, DB_CONSUME);
5854#if (DBVER >= 32)
5855 ADD_INT(d, DB_CONSUME_WAIT);
5856#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_CURRENT);
5858#if (DBVER >= 33)
5859 ADD_INT(d, DB_FAST_STAT);
5860#endif
5861 ADD_INT(d, DB_FIRST);
5862 ADD_INT(d, DB_FLUSH);
5863 ADD_INT(d, DB_GET_BOTH);
5864 ADD_INT(d, DB_GET_RECNO);
5865 ADD_INT(d, DB_JOIN_ITEM);
5866 ADD_INT(d, DB_KEYFIRST);
5867 ADD_INT(d, DB_KEYLAST);
5868 ADD_INT(d, DB_LAST);
5869 ADD_INT(d, DB_NEXT);
5870 ADD_INT(d, DB_NEXT_DUP);
5871 ADD_INT(d, DB_NEXT_NODUP);
5872 ADD_INT(d, DB_NODUPDATA);
5873 ADD_INT(d, DB_NOOVERWRITE);
5874 ADD_INT(d, DB_NOSYNC);
5875 ADD_INT(d, DB_POSITION);
5876 ADD_INT(d, DB_PREV);
5877 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005878#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005880#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881 ADD_INT(d, DB_SET);
5882 ADD_INT(d, DB_SET_RANGE);
5883 ADD_INT(d, DB_SET_RECNO);
5884 ADD_INT(d, DB_WRITECURSOR);
5885
5886 ADD_INT(d, DB_OPFLAGS_MASK);
5887 ADD_INT(d, DB_RMW);
5888#if (DBVER >= 33)
5889 ADD_INT(d, DB_DIRTY_READ);
5890 ADD_INT(d, DB_MULTIPLE);
5891 ADD_INT(d, DB_MULTIPLE_KEY);
5892#endif
5893
Gregory P. Smith29602d22006-01-24 09:46:48 +00005894#if (DBVER >= 44)
5895 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5896 ADD_INT(d, DB_READ_COMMITTED);
5897#endif
5898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899#if (DBVER >= 33)
5900 ADD_INT(d, DB_DONOTINDEX);
5901#endif
5902
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005903#if (DBVER >= 41)
5904 _addIntToDict(d, "DB_INCOMPLETE", 0);
5905#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005906 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005907#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005908 ADD_INT(d, DB_KEYEMPTY);
5909 ADD_INT(d, DB_KEYEXIST);
5910 ADD_INT(d, DB_LOCK_DEADLOCK);
5911 ADD_INT(d, DB_LOCK_NOTGRANTED);
5912 ADD_INT(d, DB_NOSERVER);
5913 ADD_INT(d, DB_NOSERVER_HOME);
5914 ADD_INT(d, DB_NOSERVER_ID);
5915 ADD_INT(d, DB_NOTFOUND);
5916 ADD_INT(d, DB_OLD_VERSION);
5917 ADD_INT(d, DB_RUNRECOVERY);
5918 ADD_INT(d, DB_VERIFY_BAD);
5919#if (DBVER >= 33)
5920 ADD_INT(d, DB_PAGE_NOTFOUND);
5921 ADD_INT(d, DB_SECONDARY_BAD);
5922#endif
5923#if (DBVER >= 40)
5924 ADD_INT(d, DB_STAT_CLEAR);
5925 ADD_INT(d, DB_REGION_INIT);
5926 ADD_INT(d, DB_NOLOCKING);
5927 ADD_INT(d, DB_YIELDCPU);
5928 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5929 ADD_INT(d, DB_NOPANIC);
5930#endif
5931
Gregory P. Smith41631e82003-09-21 00:08:14 +00005932#if (DBVER >= 42)
5933 ADD_INT(d, DB_TIME_NOTGRANTED);
5934 ADD_INT(d, DB_TXN_NOT_DURABLE);
5935 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5936 ADD_INT(d, DB_LOG_AUTOREMOVE);
5937 ADD_INT(d, DB_DIRECT_LOG);
5938 ADD_INT(d, DB_DIRECT_DB);
5939 ADD_INT(d, DB_INIT_REP);
5940 ADD_INT(d, DB_ENCRYPT);
5941 ADD_INT(d, DB_CHKSUM);
5942#endif
5943
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005944#if (DBVER >= 43)
5945 ADD_INT(d, DB_LOG_INMEMORY);
5946 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005947 ADD_INT(d, DB_SEQ_DEC);
5948 ADD_INT(d, DB_SEQ_INC);
5949 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005950#endif
5951
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005952#if (DBVER >= 41)
5953 ADD_INT(d, DB_ENCRYPT_AES);
5954 ADD_INT(d, DB_AUTO_COMMIT);
5955#else
5956 /* allow berkeleydb 4.1 aware apps to run on older versions */
5957 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5958#endif
5959
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005960 ADD_INT(d, EINVAL);
5961 ADD_INT(d, EACCES);
5962 ADD_INT(d, ENOSPC);
5963 ADD_INT(d, ENOMEM);
5964 ADD_INT(d, EAGAIN);
5965 ADD_INT(d, EBUSY);
5966 ADD_INT(d, EEXIST);
5967 ADD_INT(d, ENOENT);
5968 ADD_INT(d, EPERM);
5969
Barry Warsaw1baa9822003-03-31 19:51:29 +00005970#if (DBVER >= 40)
5971 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5972 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5973#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005974
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005975 /* The exception name must be correct for pickled exception *
5976 * objects to unpickle properly. */
5977#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5978#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5979#else
5980#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5981#endif
5982
5983 /* All the rest of the exceptions derive only from DBError */
5984#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5985 PyDict_SetItemString(d, #name, name)
5986
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005987 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005988 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5989 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005990
Gregory P. Smithe9477062005-06-04 06:46:59 +00005991 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5992 * from both DBError and KeyError, since the API only supports
5993 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005994 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005995 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5996 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005997 Py_file_input, d, d);
5998 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005999 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000 PyDict_DelItemString(d, "KeyError");
6001
6002
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006003#if !INCOMPLETE_IS_WARNING
6004 MAKE_EX(DBIncompleteError);
6005#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006006 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 MAKE_EX(DBKeyEmptyError);
6008 MAKE_EX(DBKeyExistError);
6009 MAKE_EX(DBLockDeadlockError);
6010 MAKE_EX(DBLockNotGrantedError);
6011 MAKE_EX(DBOldVersionError);
6012 MAKE_EX(DBRunRecoveryError);
6013 MAKE_EX(DBVerifyBadError);
6014 MAKE_EX(DBNoServerError);
6015 MAKE_EX(DBNoServerHomeError);
6016 MAKE_EX(DBNoServerIDError);
6017#if (DBVER >= 33)
6018 MAKE_EX(DBPageNotFoundError);
6019 MAKE_EX(DBSecondaryBadError);
6020#endif
6021
6022 MAKE_EX(DBInvalidArgError);
6023 MAKE_EX(DBAccessError);
6024 MAKE_EX(DBNoSpaceError);
6025 MAKE_EX(DBNoMemoryError);
6026 MAKE_EX(DBAgainError);
6027 MAKE_EX(DBBusyError);
6028 MAKE_EX(DBFileExistsError);
6029 MAKE_EX(DBNoSuchFileError);
6030 MAKE_EX(DBPermissionsError);
6031
6032#undef MAKE_EX
6033
6034 /* Check for errors */
6035 if (PyErr_Occurred()) {
6036 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006037 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006038 }
6039}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006040
6041/* allow this module to be named _pybsddb so that it can be installed
6042 * and imported on top of python >= 2.3 that includes its own older
6043 * copy of the library named _bsddb without importing the old version. */
6044DL_EXPORT(void) init_pybsddb(void)
6045{
6046 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6047 init_bsddb();
6048}