blob: 7b3105496703f45b48ae5ddaa98ad45c50a17f70 [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;
Neal Norwitzdf738022007-05-20 02:14:48 +00001698 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001699 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001700 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001701
1702
1703 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1704 &keyobj, &dataobj, &txnobj, &flags))
1705 return NULL;
1706
1707 CHECK_DB_NOT_CLOSED(self);
1708 if (!make_key_dbt(self, keyobj, &key, NULL))
1709 return NULL;
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;
Neal Norwitzdf738022007-05-20 02:14:48 +00001718 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719
1720 if (CHECK_DBFLAG(self, DB_THREAD)) {
1721 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitzdf738022007-05-20 02:14:48 +00001722 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001724 }
1725
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1729
Gregory P. Smithe9477062005-06-04 06:46:59 +00001730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1735 }
1736 else if (!err) {
Neal Norwitzdf738022007-05-20 02:14:48 +00001737 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001738 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitzdf738022007-05-20 02:14:48 +00001739
1740 /* Even though the flags require DB_DBT_MALLOC, data is not always
1741 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1742 if (data.data != orig_data)
1743 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001744 }
1745
1746 FREE_DBT(key);
1747 RETURN_IF_ERR();
1748 return retval;
1749}
1750
1751
1752static PyObject*
1753DB_get_byteswapped(DBObject* self, PyObject* args)
1754{
1755#if (DBVER >= 33)
1756 int err = 0;
1757#endif
1758 int retval = -1;
1759
1760 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1761 return NULL;
1762 CHECK_DB_NOT_CLOSED(self);
1763
1764#if (DBVER >= 33)
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 err = self->db->get_byteswapped(self->db, &retval);
1767 MYDB_END_ALLOW_THREADS;
1768 RETURN_IF_ERR();
1769#else
1770 MYDB_BEGIN_ALLOW_THREADS;
1771 retval = self->db->get_byteswapped(self->db);
1772 MYDB_END_ALLOW_THREADS;
1773#endif
1774 return PyInt_FromLong(retval);
1775}
1776
1777
1778static PyObject*
1779DB_get_type(DBObject* self, PyObject* args)
1780{
1781 int type;
1782
1783 if (!PyArg_ParseTuple(args,":get_type"))
1784 return NULL;
1785 CHECK_DB_NOT_CLOSED(self);
1786
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001787 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001788 if (type == -1)
1789 return NULL;
1790 return PyInt_FromLong(type);
1791}
1792
1793
1794static PyObject*
1795DB_join(DBObject* self, PyObject* args)
1796{
1797 int err, flags=0;
1798 int length, x;
1799 PyObject* cursorsObj;
1800 DBC** cursors;
1801 DBC* dbc;
1802
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001803 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1804 return NULL;
1805
1806 CHECK_DB_NOT_CLOSED(self);
1807
1808 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001809 PyErr_SetString(PyExc_TypeError,
1810 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001811 return NULL;
1812 }
1813
1814 length = PyObject_Length(cursorsObj);
1815 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001816 if (!cursors) {
1817 PyErr_NoMemory();
1818 return NULL;
1819 }
1820
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 cursors[length] = NULL;
1822 for (x=0; x<length; x++) {
1823 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001824 if (item == NULL) {
1825 free(cursors);
1826 return NULL;
1827 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001829 PyErr_SetString(PyExc_TypeError,
1830 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 free(cursors);
1832 return NULL;
1833 }
1834 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001835 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001836 }
1837
1838 MYDB_BEGIN_ALLOW_THREADS;
1839 err = self->db->join(self->db, cursors, &dbc, flags);
1840 MYDB_END_ALLOW_THREADS;
1841 free(cursors);
1842 RETURN_IF_ERR();
1843
Gregory P. Smith7441e652003-11-03 21:35:31 +00001844 /* FIXME: this is a buggy interface. The returned cursor
1845 contains internal references to the passed in cursors
1846 but does not hold python references to them or prevent
1847 them from being closed prematurely. This can cause
1848 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849 return (PyObject*) newDBCursorObject(dbc, self);
1850}
1851
1852
1853static PyObject*
1854DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1855{
1856 int err, flags=0;
1857 PyObject* txnobj = NULL;
1858 PyObject* keyobj;
1859 DBT key;
1860 DB_TXN *txn = NULL;
1861 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001862 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863
1864 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1865 &keyobj, &txnobj, &flags))
1866 return NULL;
1867 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001868 if (!make_dbt(keyobj, &key))
1869 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001870 return NULL;
1871 if (!checkTxnObj(txnobj, &txn))
1872 return NULL;
1873
1874 MYDB_BEGIN_ALLOW_THREADS;
1875 err = self->db->key_range(self->db, txn, &key, &range, flags);
1876 MYDB_END_ALLOW_THREADS;
1877
1878 RETURN_IF_ERR();
1879 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1880}
1881
1882
1883static PyObject*
1884DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1885{
1886 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1887 char* filename = NULL;
1888 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001889#if (DBVER >= 41)
1890 PyObject *txnobj = NULL;
1891 DB_TXN *txn = NULL;
1892 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001893 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001894 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1895 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001896 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001897 "filename", "dbtype", "flags", "mode", "txn", NULL};
1898#else
1899 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001900 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001901 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1902 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001903 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001904 "filename", "dbtype", "flags", "mode", NULL};
1905#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001906
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001907#if (DBVER >= 41)
1908 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1909 &filename, &dbname, &type, &flags, &mode,
1910 &txnobj))
1911#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001912 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001913 &filename, &dbname, &type, &flags,
1914 &mode))
1915#endif
1916 {
1917 PyErr_Clear();
1918 type = DB_UNKNOWN; flags = 0; mode = 0660;
1919 filename = NULL; dbname = NULL;
1920#if (DBVER >= 41)
1921 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1922 kwnames_basic,
1923 &filename, &type, &flags, &mode,
1924 &txnobj))
1925 return NULL;
1926#else
1927 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1928 kwnames_basic,
1929 &filename, &type, &flags, &mode))
1930 return NULL;
1931#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 }
1933
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001934#if (DBVER >= 41)
1935 if (!checkTxnObj(txnobj, &txn)) return NULL;
1936#endif
1937
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001938 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001939 PyObject *t = Py_BuildValue("(is)", 0,
1940 "Cannot call open() twice for DB object");
1941 PyErr_SetObject(DBError, t);
1942 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001943 return NULL;
1944 }
1945
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946#if 0 && (DBVER >= 41)
1947 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1948 && (self->myenvobj->flags & DB_INIT_TXN))
1949 {
1950 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1951 * explicitly passed) but we are in a transaction ready environment:
1952 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1953 * to work on BerkeleyDB 4.1 without needing to modify their
1954 * DBEnv or DB open calls.
1955 * TODO make this behaviour of the library configurable.
1956 */
1957 flags |= DB_AUTO_COMMIT;
1958 }
1959#endif
1960
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001962#if (DBVER >= 41)
1963 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1964#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001966#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 MYDB_END_ALLOW_THREADS;
1968 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001969 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001970 self->db = NULL;
1971 return NULL;
1972 }
1973
1974 self->flags = flags;
1975 RETURN_NONE();
1976}
1977
1978
1979static PyObject*
1980DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1981{
1982 int flags=0;
1983 PyObject* txnobj = NULL;
1984 int dlen = -1;
1985 int doff = -1;
1986 PyObject* keyobj, *dataobj, *retval;
1987 DBT key, data;
1988 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001989 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001990 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001991
1992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1993 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1994 return NULL;
1995
1996 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001997 if (!make_key_dbt(self, keyobj, &key, NULL))
1998 return NULL;
1999 if ( !make_dbt(dataobj, &data) ||
2000 !add_partial_dbt(&data, dlen, doff) ||
2001 !checkTxnObj(txnobj, &txn) )
2002 {
2003 FREE_DBT(key);
2004 return NULL;
2005 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002006
2007 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2008 FREE_DBT(key);
2009 return NULL;
2010 }
2011
2012 if (flags & DB_APPEND)
2013 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2014 else {
2015 retval = Py_None;
2016 Py_INCREF(retval);
2017 }
2018 FREE_DBT(key);
2019 return retval;
2020}
2021
2022
2023
2024static PyObject*
2025DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2026{
2027 char* filename;
2028 char* database = NULL;
2029 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002030 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002031
2032 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2033 &filename, &database, &flags))
2034 return NULL;
2035 CHECK_DB_NOT_CLOSED(self);
2036
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002037 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002038 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002039 RETURN_IF_ERR();
2040 RETURN_NONE();
2041}
2042
2043
2044
2045static PyObject*
2046DB_rename(DBObject* self, PyObject* args)
2047{
2048 char* filename;
2049 char* database;
2050 char* newname;
2051 int err, flags=0;
2052
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002053 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2054 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002055 return NULL;
2056 CHECK_DB_NOT_CLOSED(self);
2057
2058 MYDB_BEGIN_ALLOW_THREADS;
2059 err = self->db->rename(self->db, filename, database, newname, flags);
2060 MYDB_END_ALLOW_THREADS;
2061 RETURN_IF_ERR();
2062 RETURN_NONE();
2063}
2064
2065
2066static PyObject*
2067DB_set_bt_minkey(DBObject* self, PyObject* args)
2068{
2069 int err, minkey;
2070
2071 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2072 return NULL;
2073 CHECK_DB_NOT_CLOSED(self);
2074
2075 MYDB_BEGIN_ALLOW_THREADS;
2076 err = self->db->set_bt_minkey(self->db, minkey);
2077 MYDB_END_ALLOW_THREADS;
2078 RETURN_IF_ERR();
2079 RETURN_NONE();
2080}
2081
Neal Norwitz84562352005-10-20 04:30:15 +00002082#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002083static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002084_default_cmp(const DBT *leftKey,
2085 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002086{
2087 int res;
2088 int lsize = leftKey->size, rsize = rightKey->size;
2089
Georg Brandlef1701f2006-03-07 14:57:48 +00002090 res = memcmp(leftKey->data, rightKey->data,
2091 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002092
2093 if (res == 0) {
2094 if (lsize < rsize) {
2095 res = -1;
2096 }
2097 else if (lsize > rsize) {
2098 res = 1;
2099 }
2100 }
2101 return res;
2102}
2103
2104static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002105_db_compareCallback(DB* db,
2106 const DBT *leftKey,
2107 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108{
2109 int res = 0;
2110 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002111 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002113
2114 if (self == NULL || self->btCompareCallback == NULL) {
2115 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 PyErr_SetString(PyExc_TypeError,
2117 (self == 0
2118 ? "DB_bt_compare db is NULL."
2119 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002121 PyErr_Print();
2122 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002123 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125 MYDB_BEGIN_BLOCK_THREADS;
2126
Thomas Woutersb3153832006-03-08 01:47:19 +00002127 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2128 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002130 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002133 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002135 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002136 PyErr_Print();
2137 res = _default_cmp(leftKey, rightKey);
2138 } else if (PyInt_Check(result)) {
2139 res = PyInt_AsLong(result);
2140 } else {
2141 PyErr_SetString(PyExc_TypeError,
2142 "DB_bt_compare callback MUST return an int.");
2143 /* we're in a callback within the DB code, we can't raise */
2144 PyErr_Print();
2145 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146 }
2147
Thomas Woutersb3153832006-03-08 01:47:19 +00002148 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002149 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002150
2151 MYDB_END_BLOCK_THREADS;
2152 }
2153 return res;
2154}
2155
2156static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002157DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158{
2159 int err;
2160 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002161 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164 return NULL;
2165
Georg Brandlef1701f2006-03-07 14:57:48 +00002166 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002167
Georg Brandlef1701f2006-03-07 14:57:48 +00002168 if (!PyCallable_Check(comparator)) {
2169 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002170 return NULL;
2171 }
2172
2173 /*
2174 * Perform a test call of the comparator function with two empty
2175 * string objects here. verify that it returns an int (0).
2176 * err if not.
2177 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002178 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002179 result = PyEval_CallObject(comparator, tuple);
2180 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002181 if (result == NULL)
2182 return NULL;
2183 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002184 PyErr_SetString(PyExc_TypeError,
2185 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002186 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002187 } else if (PyInt_AsLong(result) != 0) {
2188 PyErr_SetString(PyExc_TypeError,
2189 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002190 return NULL;
2191 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002192 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002193
2194 /* We don't accept multiple set_bt_compare operations, in order to
2195 * simplify the code. This would have no real use, as one cannot
2196 * change the function once the db is opened anyway */
2197 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002198 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002199 return NULL;
2200 }
2201
Georg Brandlef1701f2006-03-07 14:57:48 +00002202 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002203 self->btCompareCallback = comparator;
2204
2205 /* This is to workaround a problem with un-initialized threads (see
2206 comment in DB_associate) */
2207#ifdef WITH_THREAD
2208 PyEval_InitThreads();
2209#endif
2210
Thomas Woutersb3153832006-03-08 01:47:19 +00002211 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002212
2213 if (err) {
2214 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002215 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216 self->btCompareCallback = NULL;
2217 }
2218
Georg Brandlef1701f2006-03-07 14:57:48 +00002219 RETURN_IF_ERR();
2220 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002221}
Neal Norwitz84562352005-10-20 04:30:15 +00002222#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002223
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002224
2225static PyObject*
2226DB_set_cachesize(DBObject* self, PyObject* args)
2227{
2228 int err;
2229 int gbytes = 0, bytes = 0, ncache = 0;
2230
2231 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2232 &gbytes,&bytes,&ncache))
2233 return NULL;
2234 CHECK_DB_NOT_CLOSED(self);
2235
2236 MYDB_BEGIN_ALLOW_THREADS;
2237 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2238 MYDB_END_ALLOW_THREADS;
2239 RETURN_IF_ERR();
2240 RETURN_NONE();
2241}
2242
2243
2244static PyObject*
2245DB_set_flags(DBObject* self, PyObject* args)
2246{
2247 int err, flags;
2248
2249 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2250 return NULL;
2251 CHECK_DB_NOT_CLOSED(self);
2252
2253 MYDB_BEGIN_ALLOW_THREADS;
2254 err = self->db->set_flags(self->db, flags);
2255 MYDB_END_ALLOW_THREADS;
2256 RETURN_IF_ERR();
2257
2258 self->setflags |= flags;
2259 RETURN_NONE();
2260}
2261
2262
2263static PyObject*
2264DB_set_h_ffactor(DBObject* self, PyObject* args)
2265{
2266 int err, ffactor;
2267
2268 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2269 return NULL;
2270 CHECK_DB_NOT_CLOSED(self);
2271
2272 MYDB_BEGIN_ALLOW_THREADS;
2273 err = self->db->set_h_ffactor(self->db, ffactor);
2274 MYDB_END_ALLOW_THREADS;
2275 RETURN_IF_ERR();
2276 RETURN_NONE();
2277}
2278
2279
2280static PyObject*
2281DB_set_h_nelem(DBObject* self, PyObject* args)
2282{
2283 int err, nelem;
2284
2285 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2286 return NULL;
2287 CHECK_DB_NOT_CLOSED(self);
2288
2289 MYDB_BEGIN_ALLOW_THREADS;
2290 err = self->db->set_h_nelem(self->db, nelem);
2291 MYDB_END_ALLOW_THREADS;
2292 RETURN_IF_ERR();
2293 RETURN_NONE();
2294}
2295
2296
2297static PyObject*
2298DB_set_lorder(DBObject* self, PyObject* args)
2299{
2300 int err, lorder;
2301
2302 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2303 return NULL;
2304 CHECK_DB_NOT_CLOSED(self);
2305
2306 MYDB_BEGIN_ALLOW_THREADS;
2307 err = self->db->set_lorder(self->db, lorder);
2308 MYDB_END_ALLOW_THREADS;
2309 RETURN_IF_ERR();
2310 RETURN_NONE();
2311}
2312
2313
2314static PyObject*
2315DB_set_pagesize(DBObject* self, PyObject* args)
2316{
2317 int err, pagesize;
2318
2319 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2320 return NULL;
2321 CHECK_DB_NOT_CLOSED(self);
2322
2323 MYDB_BEGIN_ALLOW_THREADS;
2324 err = self->db->set_pagesize(self->db, pagesize);
2325 MYDB_END_ALLOW_THREADS;
2326 RETURN_IF_ERR();
2327 RETURN_NONE();
2328}
2329
2330
2331static PyObject*
2332DB_set_re_delim(DBObject* self, PyObject* args)
2333{
2334 int err;
2335 char delim;
2336
2337 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2338 PyErr_Clear();
2339 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2340 return NULL;
2341 }
2342
2343 CHECK_DB_NOT_CLOSED(self);
2344
2345 MYDB_BEGIN_ALLOW_THREADS;
2346 err = self->db->set_re_delim(self->db, delim);
2347 MYDB_END_ALLOW_THREADS;
2348 RETURN_IF_ERR();
2349 RETURN_NONE();
2350}
2351
2352static PyObject*
2353DB_set_re_len(DBObject* self, PyObject* args)
2354{
2355 int err, len;
2356
2357 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2358 return NULL;
2359 CHECK_DB_NOT_CLOSED(self);
2360
2361 MYDB_BEGIN_ALLOW_THREADS;
2362 err = self->db->set_re_len(self->db, len);
2363 MYDB_END_ALLOW_THREADS;
2364 RETURN_IF_ERR();
2365 RETURN_NONE();
2366}
2367
2368
2369static PyObject*
2370DB_set_re_pad(DBObject* self, PyObject* args)
2371{
2372 int err;
2373 char pad;
2374
2375 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2376 PyErr_Clear();
2377 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2378 return NULL;
2379 }
2380 CHECK_DB_NOT_CLOSED(self);
2381
2382 MYDB_BEGIN_ALLOW_THREADS;
2383 err = self->db->set_re_pad(self->db, pad);
2384 MYDB_END_ALLOW_THREADS;
2385 RETURN_IF_ERR();
2386 RETURN_NONE();
2387}
2388
2389
2390static PyObject*
2391DB_set_re_source(DBObject* self, PyObject* args)
2392{
2393 int err;
2394 char *re_source;
2395
2396 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2397 return NULL;
2398 CHECK_DB_NOT_CLOSED(self);
2399
2400 MYDB_BEGIN_ALLOW_THREADS;
2401 err = self->db->set_re_source(self->db, re_source);
2402 MYDB_END_ALLOW_THREADS;
2403 RETURN_IF_ERR();
2404 RETURN_NONE();
2405}
2406
2407
2408#if (DBVER >= 32)
2409static PyObject*
2410DB_set_q_extentsize(DBObject* self, PyObject* args)
2411{
2412 int err;
2413 int extentsize;
2414
2415 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2416 return NULL;
2417 CHECK_DB_NOT_CLOSED(self);
2418
2419 MYDB_BEGIN_ALLOW_THREADS;
2420 err = self->db->set_q_extentsize(self->db, extentsize);
2421 MYDB_END_ALLOW_THREADS;
2422 RETURN_IF_ERR();
2423 RETURN_NONE();
2424}
2425#endif
2426
2427static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002428DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002429{
2430 int err, flags = 0, type;
2431 void* sp;
2432 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002433#if (DBVER >= 43)
2434 PyObject* txnobj = NULL;
2435 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002436 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002437#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002438 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002439#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002440
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002441#if (DBVER >= 43)
2442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2443 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002445 if (!checkTxnObj(txnobj, &txn))
2446 return NULL;
2447#else
2448 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2449 return NULL;
2450#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002451 CHECK_DB_NOT_CLOSED(self);
2452
2453 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002454#if (DBVER >= 43)
2455 err = self->db->stat(self->db, txn, &sp, flags);
2456#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002457 err = self->db->stat(self->db, &sp, flags);
2458#else
2459 err = self->db->stat(self->db, &sp, NULL, flags);
2460#endif
2461 MYDB_END_ALLOW_THREADS;
2462 RETURN_IF_ERR();
2463
2464 self->haveStat = 1;
2465
2466 /* Turn the stat structure into a dictionary */
2467 type = _DB_get_type(self);
2468 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2469 free(sp);
2470 return NULL;
2471 }
2472
2473#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2474#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2475#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2476
2477 switch (type) {
2478 case DB_HASH:
2479 MAKE_HASH_ENTRY(magic);
2480 MAKE_HASH_ENTRY(version);
2481 MAKE_HASH_ENTRY(nkeys);
2482 MAKE_HASH_ENTRY(ndata);
2483 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002484#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002485 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002486#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002487 MAKE_HASH_ENTRY(ffactor);
2488 MAKE_HASH_ENTRY(buckets);
2489 MAKE_HASH_ENTRY(free);
2490 MAKE_HASH_ENTRY(bfree);
2491 MAKE_HASH_ENTRY(bigpages);
2492 MAKE_HASH_ENTRY(big_bfree);
2493 MAKE_HASH_ENTRY(overflows);
2494 MAKE_HASH_ENTRY(ovfl_free);
2495 MAKE_HASH_ENTRY(dup);
2496 MAKE_HASH_ENTRY(dup_free);
2497 break;
2498
2499 case DB_BTREE:
2500 case DB_RECNO:
2501 MAKE_BT_ENTRY(magic);
2502 MAKE_BT_ENTRY(version);
2503 MAKE_BT_ENTRY(nkeys);
2504 MAKE_BT_ENTRY(ndata);
2505 MAKE_BT_ENTRY(pagesize);
2506 MAKE_BT_ENTRY(minkey);
2507 MAKE_BT_ENTRY(re_len);
2508 MAKE_BT_ENTRY(re_pad);
2509 MAKE_BT_ENTRY(levels);
2510 MAKE_BT_ENTRY(int_pg);
2511 MAKE_BT_ENTRY(leaf_pg);
2512 MAKE_BT_ENTRY(dup_pg);
2513 MAKE_BT_ENTRY(over_pg);
2514 MAKE_BT_ENTRY(free);
2515 MAKE_BT_ENTRY(int_pgfree);
2516 MAKE_BT_ENTRY(leaf_pgfree);
2517 MAKE_BT_ENTRY(dup_pgfree);
2518 MAKE_BT_ENTRY(over_pgfree);
2519 break;
2520
2521 case DB_QUEUE:
2522 MAKE_QUEUE_ENTRY(magic);
2523 MAKE_QUEUE_ENTRY(version);
2524 MAKE_QUEUE_ENTRY(nkeys);
2525 MAKE_QUEUE_ENTRY(ndata);
2526 MAKE_QUEUE_ENTRY(pagesize);
2527 MAKE_QUEUE_ENTRY(pages);
2528 MAKE_QUEUE_ENTRY(re_len);
2529 MAKE_QUEUE_ENTRY(re_pad);
2530 MAKE_QUEUE_ENTRY(pgfree);
2531#if (DBVER == 31)
2532 MAKE_QUEUE_ENTRY(start);
2533#endif
2534 MAKE_QUEUE_ENTRY(first_recno);
2535 MAKE_QUEUE_ENTRY(cur_recno);
2536 break;
2537
2538 default:
2539 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2540 Py_DECREF(d);
2541 d = NULL;
2542 }
2543
2544#undef MAKE_HASH_ENTRY
2545#undef MAKE_BT_ENTRY
2546#undef MAKE_QUEUE_ENTRY
2547
2548 free(sp);
2549 return d;
2550}
2551
2552static PyObject*
2553DB_sync(DBObject* self, PyObject* args)
2554{
2555 int err;
2556 int flags = 0;
2557
2558 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2559 return NULL;
2560 CHECK_DB_NOT_CLOSED(self);
2561
2562 MYDB_BEGIN_ALLOW_THREADS;
2563 err = self->db->sync(self->db, flags);
2564 MYDB_END_ALLOW_THREADS;
2565 RETURN_IF_ERR();
2566 RETURN_NONE();
2567}
2568
2569
2570#if (DBVER >= 33)
2571static PyObject*
2572DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2573{
2574 int err, flags=0;
2575 u_int32_t count=0;
2576 PyObject* txnobj = NULL;
2577 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002578 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002579
2580 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2581 &txnobj, &flags))
2582 return NULL;
2583 CHECK_DB_NOT_CLOSED(self);
2584 if (!checkTxnObj(txnobj, &txn))
2585 return NULL;
2586
2587 MYDB_BEGIN_ALLOW_THREADS;
2588 err = self->db->truncate(self->db, txn, &count, flags);
2589 MYDB_END_ALLOW_THREADS;
2590 RETURN_IF_ERR();
2591 return PyInt_FromLong(count);
2592}
2593#endif
2594
2595
2596static PyObject*
2597DB_upgrade(DBObject* self, PyObject* args)
2598{
2599 int err, flags=0;
2600 char *filename;
2601
2602 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2603 return NULL;
2604 CHECK_DB_NOT_CLOSED(self);
2605
2606 MYDB_BEGIN_ALLOW_THREADS;
2607 err = self->db->upgrade(self->db, filename, flags);
2608 MYDB_END_ALLOW_THREADS;
2609 RETURN_IF_ERR();
2610 RETURN_NONE();
2611}
2612
2613
2614static PyObject*
2615DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2616{
2617 int err, flags=0;
2618 char* fileName;
2619 char* dbName=NULL;
2620 char* outFileName=NULL;
2621 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002622 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002623 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002624
2625 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2626 &fileName, &dbName, &outFileName, &flags))
2627 return NULL;
2628
2629 CHECK_DB_NOT_CLOSED(self);
2630 if (outFileName)
2631 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002632 /* XXX(nnorwitz): it should probably be an exception if outFile
2633 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002634
2635 MYDB_BEGIN_ALLOW_THREADS;
2636 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2637 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002638 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002639 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002640
2641 /* DB.verify acts as a DB handle destructor (like close); this was
2642 * documented in BerkeleyDB 4.2 but had the undocumented effect
2643 * of not being safe in prior versions while still requiring an explicit
2644 * DB.close call afterwards. Lets call close for the user to emulate
2645 * the safe 4.2 behaviour. */
2646#if (DBVER <= 41)
2647 self->db->close(self->db, 0);
2648#endif
2649 self->db = NULL;
2650
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651 RETURN_IF_ERR();
2652 RETURN_NONE();
2653}
2654
2655
2656static PyObject*
2657DB_set_get_returns_none(DBObject* self, PyObject* args)
2658{
2659 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002660 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002661
2662 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2663 return NULL;
2664 CHECK_DB_NOT_CLOSED(self);
2665
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002666 if (self->moduleFlags.getReturnsNone)
2667 ++oldValue;
2668 if (self->moduleFlags.cursorSetReturnsNone)
2669 ++oldValue;
2670 self->moduleFlags.getReturnsNone = (flags >= 1);
2671 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002672 return PyInt_FromLong(oldValue);
2673}
2674
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002675#if (DBVER >= 41)
2676static PyObject*
2677DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2678{
2679 int err;
2680 u_int32_t flags=0;
2681 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002682 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002683
2684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2685 &passwd, &flags)) {
2686 return NULL;
2687 }
2688
2689 MYDB_BEGIN_ALLOW_THREADS;
2690 err = self->db->set_encrypt(self->db, passwd, flags);
2691 MYDB_END_ALLOW_THREADS;
2692
2693 RETURN_IF_ERR();
2694 RETURN_NONE();
2695}
2696#endif /* DBVER >= 41 */
2697
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002698
2699/*-------------------------------------------------------------- */
2700/* Mapping and Dictionary-like access routines */
2701
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002702Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703{
2704 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002705 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 int flags = 0;
2707 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002708 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709
2710 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002711 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2712 PyErr_SetObject(DBError, t);
2713 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002714 return -1;
2715 }
2716
2717 if (self->haveStat) { /* Has the stat function been called recently? If
2718 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002719 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720 }
2721
2722 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002723redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002724#if (DBVER >= 43)
2725 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2726#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 err = self->db->stat(self->db, &sp, flags);
2728#else
2729 err = self->db->stat(self->db, &sp, NULL, flags);
2730#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002731
2732 /* All the stat structures have matching fields upto the ndata field,
2733 so we can use any of them for the type cast */
2734 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2735
2736 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2737 * redo a full stat to make sure.
2738 * Fixes SF python bug 1493322, pybsddb bug 1184012
2739 */
2740 if (size == 0 && (flags & DB_FAST_STAT)) {
2741 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002742 if (!err)
2743 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002744 goto redo_stat_for_length;
2745 }
2746
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 MYDB_END_ALLOW_THREADS;
2748
2749 if (err)
2750 return -1;
2751
2752 self->haveStat = 1;
2753
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754 free(sp);
2755 return size;
2756}
2757
2758
2759PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2760{
2761 int err;
2762 PyObject* retval;
2763 DBT key;
2764 DBT data;
2765
2766 CHECK_DB_NOT_CLOSED(self);
2767 if (!make_key_dbt(self, keyobj, &key, NULL))
2768 return NULL;
2769
2770 CLEAR_DBT(data);
2771 if (CHECK_DBFLAG(self, DB_THREAD)) {
2772 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2773 data.flags = DB_DBT_MALLOC;
2774 }
2775 MYDB_BEGIN_ALLOW_THREADS;
2776 err = self->db->get(self->db, NULL, &key, &data, 0);
2777 MYDB_END_ALLOW_THREADS;
2778 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2779 PyErr_SetObject(PyExc_KeyError, keyobj);
2780 retval = NULL;
2781 }
2782 else if (makeDBError(err)) {
2783 retval = NULL;
2784 }
2785 else {
2786 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2787 FREE_DBT(data);
2788 }
2789
2790 FREE_DBT(key);
2791 return retval;
2792}
2793
2794
2795static int
2796DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2797{
2798 DBT key, data;
2799 int retval;
2800 int flags = 0;
2801
2802 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002803 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2804 PyErr_SetObject(DBError, t);
2805 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806 return -1;
2807 }
2808
2809 if (!make_key_dbt(self, keyobj, &key, NULL))
2810 return -1;
2811
2812 if (dataobj != NULL) {
2813 if (!make_dbt(dataobj, &data))
2814 retval = -1;
2815 else {
2816 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002817 /* dictionaries shouldn't have duplicate keys */
2818 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002819 retval = _DB_put(self, NULL, &key, &data, flags);
2820
2821 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002822 /* try deleting any old record that matches and then PUT it
2823 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824 _DB_delete(self, NULL, &key, 0);
2825 PyErr_Clear();
2826 retval = _DB_put(self, NULL, &key, &data, flags);
2827 }
2828 }
2829 }
2830 else {
2831 /* dataobj == NULL, so delete the key */
2832 retval = _DB_delete(self, NULL, &key, 0);
2833 }
2834 FREE_DBT(key);
2835 return retval;
2836}
2837
2838
2839static PyObject*
2840DB_has_key(DBObject* self, PyObject* args)
2841{
2842 int err;
2843 PyObject* keyobj;
2844 DBT key, data;
2845 PyObject* txnobj = NULL;
2846 DB_TXN *txn = NULL;
2847
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002848 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849 return NULL;
2850 CHECK_DB_NOT_CLOSED(self);
2851 if (!make_key_dbt(self, keyobj, &key, NULL))
2852 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002853 if (!checkTxnObj(txnobj, &txn)) {
2854 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002856 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002858 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002859 it has a record but can't allocate a buffer for the data. This saves
2860 having to deal with data we won't be using.
2861 */
2862 CLEAR_DBT(data);
2863 data.flags = DB_DBT_USERMEM;
2864
2865 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002866 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002867 MYDB_END_ALLOW_THREADS;
2868 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002869
2870 if (err == DB_BUFFER_SMALL || err == 0) {
2871 return PyInt_FromLong(1);
2872 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2873 return PyInt_FromLong(0);
2874 }
2875
2876 makeDBError(err);
2877 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002878}
2879
2880
2881#define _KEYS_LIST 1
2882#define _VALUES_LIST 2
2883#define _ITEMS_LIST 3
2884
2885static PyObject*
2886_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2887{
2888 int err, dbtype;
2889 DBT key;
2890 DBT data;
2891 DBC *cursor;
2892 PyObject* list;
2893 PyObject* item = NULL;
2894
2895 CHECK_DB_NOT_CLOSED(self);
2896 CLEAR_DBT(key);
2897 CLEAR_DBT(data);
2898
2899 dbtype = _DB_get_type(self);
2900 if (dbtype == -1)
2901 return NULL;
2902
2903 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002904 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906
2907 /* get a cursor */
2908 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002909 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002911 if (makeDBError(err)) {
2912 Py_DECREF(list);
2913 return NULL;
2914 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915
2916 if (CHECK_DBFLAG(self, DB_THREAD)) {
2917 key.flags = DB_DBT_REALLOC;
2918 data.flags = DB_DBT_REALLOC;
2919 }
2920
2921 while (1) { /* use the cursor to traverse the DB, collecting items */
2922 MYDB_BEGIN_ALLOW_THREADS;
2923 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2924 MYDB_END_ALLOW_THREADS;
2925
2926 if (err) {
2927 /* for any error, break out of the loop */
2928 break;
2929 }
2930
2931 switch (type) {
2932 case _KEYS_LIST:
2933 switch(dbtype) {
2934 case DB_BTREE:
2935 case DB_HASH:
2936 default:
2937 item = PyString_FromStringAndSize((char*)key.data, key.size);
2938 break;
2939 case DB_RECNO:
2940 case DB_QUEUE:
2941 item = PyInt_FromLong(*((db_recno_t*)key.data));
2942 break;
2943 }
2944 break;
2945
2946 case _VALUES_LIST:
2947 item = PyString_FromStringAndSize((char*)data.data, data.size);
2948 break;
2949
2950 case _ITEMS_LIST:
2951 switch(dbtype) {
2952 case DB_BTREE:
2953 case DB_HASH:
2954 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002955 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2956 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002957 break;
2958 case DB_RECNO:
2959 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002960 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2961 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002962 break;
2963 }
2964 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002965 default:
2966 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2967 item = NULL;
2968 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002969 }
2970 if (item == NULL) {
2971 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002972 list = NULL;
2973 goto done;
2974 }
2975 PyList_Append(list, item);
2976 Py_DECREF(item);
2977 }
2978
Gregory P. Smithe9477062005-06-04 06:46:59 +00002979 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2980 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002981 Py_DECREF(list);
2982 list = NULL;
2983 }
2984
2985 done:
2986 FREE_DBT(key);
2987 FREE_DBT(data);
2988 MYDB_BEGIN_ALLOW_THREADS;
2989 cursor->c_close(cursor);
2990 MYDB_END_ALLOW_THREADS;
2991 return list;
2992}
2993
2994
2995static PyObject*
2996DB_keys(DBObject* self, PyObject* args)
2997{
2998 PyObject* txnobj = NULL;
2999 DB_TXN *txn = NULL;
3000
Georg Brandl96a8c392006-05-29 21:04:52 +00003001 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003002 return NULL;
3003 if (!checkTxnObj(txnobj, &txn))
3004 return NULL;
3005 return _DB_make_list(self, txn, _KEYS_LIST);
3006}
3007
3008
3009static PyObject*
3010DB_items(DBObject* self, PyObject* args)
3011{
3012 PyObject* txnobj = NULL;
3013 DB_TXN *txn = NULL;
3014
Georg Brandl96a8c392006-05-29 21:04:52 +00003015 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016 return NULL;
3017 if (!checkTxnObj(txnobj, &txn))
3018 return NULL;
3019 return _DB_make_list(self, txn, _ITEMS_LIST);
3020}
3021
3022
3023static PyObject*
3024DB_values(DBObject* self, PyObject* args)
3025{
3026 PyObject* txnobj = NULL;
3027 DB_TXN *txn = NULL;
3028
Georg Brandl96a8c392006-05-29 21:04:52 +00003029 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030 return NULL;
3031 if (!checkTxnObj(txnobj, &txn))
3032 return NULL;
3033 return _DB_make_list(self, txn, _VALUES_LIST);
3034}
3035
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036/* --------------------------------------------------------------------- */
3037/* DBCursor methods */
3038
3039
3040static PyObject*
3041DBC_close(DBCursorObject* self, PyObject* args)
3042{
3043 int err = 0;
3044
3045 if (!PyArg_ParseTuple(args, ":close"))
3046 return NULL;
3047
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003048 if (self->dbc != NULL) {
3049 MYDB_BEGIN_ALLOW_THREADS;
3050 err = self->dbc->c_close(self->dbc);
3051 self->dbc = NULL;
3052 MYDB_END_ALLOW_THREADS;
3053 }
3054 RETURN_IF_ERR();
3055 RETURN_NONE();
3056}
3057
3058
3059static PyObject*
3060DBC_count(DBCursorObject* self, PyObject* args)
3061{
3062 int err = 0;
3063 db_recno_t count;
3064 int flags = 0;
3065
3066 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3067 return NULL;
3068
3069 CHECK_CURSOR_NOT_CLOSED(self);
3070
3071 MYDB_BEGIN_ALLOW_THREADS;
3072 err = self->dbc->c_count(self->dbc, &count, flags);
3073 MYDB_END_ALLOW_THREADS;
3074 RETURN_IF_ERR();
3075
3076 return PyInt_FromLong(count);
3077}
3078
3079
3080static PyObject*
3081DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3082{
3083 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3084}
3085
3086
3087static PyObject*
3088DBC_delete(DBCursorObject* self, PyObject* args)
3089{
3090 int err, flags=0;
3091
3092 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3093 return NULL;
3094
3095 CHECK_CURSOR_NOT_CLOSED(self);
3096
3097 MYDB_BEGIN_ALLOW_THREADS;
3098 err = self->dbc->c_del(self->dbc, flags);
3099 MYDB_END_ALLOW_THREADS;
3100 RETURN_IF_ERR();
3101
3102 self->mydb->haveStat = 0;
3103 RETURN_NONE();
3104}
3105
3106
3107static PyObject*
3108DBC_dup(DBCursorObject* self, PyObject* args)
3109{
3110 int err, flags =0;
3111 DBC* dbc = NULL;
3112
3113 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3114 return NULL;
3115
3116 CHECK_CURSOR_NOT_CLOSED(self);
3117
3118 MYDB_BEGIN_ALLOW_THREADS;
3119 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3120 MYDB_END_ALLOW_THREADS;
3121 RETURN_IF_ERR();
3122
3123 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3124}
3125
3126static PyObject*
3127DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3128{
3129 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3130}
3131
3132
3133static PyObject*
3134DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3135{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003136 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003137 PyObject* keyobj = NULL;
3138 PyObject* dataobj = NULL;
3139 PyObject* retval = NULL;
3140 int dlen = -1;
3141 int doff = -1;
3142 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003143 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003144 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145
3146 CLEAR_DBT(key);
3147 CLEAR_DBT(data);
3148 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003149 &flags, &dlen, &doff))
3150 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3153 &kwnames[1],
3154 &keyobj, &flags, &dlen, &doff))
3155 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003157 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3158 kwnames, &keyobj, &dataobj,
3159 &flags, &dlen, &doff))
3160 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003161 return NULL;
3162 }
3163 }
3164 }
3165
3166 CHECK_CURSOR_NOT_CLOSED(self);
3167
3168 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3169 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003170 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3171 (!add_partial_dbt(&data, dlen, doff)) )
3172 {
3173 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003175 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176
3177 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3178 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003179 if (!(key.flags & DB_DBT_REALLOC)) {
3180 key.flags |= DB_DBT_MALLOC;
3181 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003182 }
3183
3184 MYDB_BEGIN_ALLOW_THREADS;
3185 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3186 MYDB_END_ALLOW_THREADS;
3187
Gregory P. Smithe9477062005-06-04 06:46:59 +00003188 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3189 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190 Py_INCREF(Py_None);
3191 retval = Py_None;
3192 }
3193 else if (makeDBError(err)) {
3194 retval = NULL;
3195 }
3196 else {
3197 switch (_DB_get_type(self->mydb)) {
3198 case -1:
3199 retval = NULL;
3200 break;
3201 case DB_BTREE:
3202 case DB_HASH:
3203 default:
3204 retval = Py_BuildValue("s#s#", key.data, key.size,
3205 data.data, data.size);
3206 break;
3207 case DB_RECNO:
3208 case DB_QUEUE:
3209 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3210 data.data, data.size);
3211 break;
3212 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003213 FREE_DBT(data);
3214 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003215 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003216 return retval;
3217}
3218
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003219#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003220static PyObject*
3221DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3222{
3223 int err, flags=0;
3224 PyObject* keyobj = NULL;
3225 PyObject* dataobj = NULL;
3226 PyObject* retval = NULL;
3227 int dlen = -1;
3228 int doff = -1;
3229 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003230 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3231 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003232
3233 CLEAR_DBT(key);
3234 CLEAR_DBT(data);
3235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3236 &flags, &dlen, &doff))
3237 {
3238 PyErr_Clear();
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003240 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003241 &keyobj, &flags, &dlen, &doff))
3242 {
3243 PyErr_Clear();
3244 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3245 kwnames, &keyobj, &dataobj,
3246 &flags, &dlen, &doff))
3247 {
3248 return NULL;
3249 }
3250 }
3251 }
3252
3253 CHECK_CURSOR_NOT_CLOSED(self);
3254
3255 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3256 return NULL;
3257 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3258 (!add_partial_dbt(&data, dlen, doff)) ) {
3259 FREE_DBT(key);
3260 return NULL;
3261 }
3262
3263 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3264 data.flags = DB_DBT_MALLOC;
3265 if (!(key.flags & DB_DBT_REALLOC)) {
3266 key.flags |= DB_DBT_MALLOC;
3267 }
3268 }
3269
3270 CLEAR_DBT(pkey);
3271 pkey.flags = DB_DBT_MALLOC;
3272
3273 MYDB_BEGIN_ALLOW_THREADS;
3274 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3275 MYDB_END_ALLOW_THREADS;
3276
Gregory P. Smithe9477062005-06-04 06:46:59 +00003277 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3278 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003279 Py_INCREF(Py_None);
3280 retval = Py_None;
3281 }
3282 else if (makeDBError(err)) {
3283 retval = NULL;
3284 }
3285 else {
3286 PyObject *pkeyObj;
3287 PyObject *dataObj;
3288 dataObj = PyString_FromStringAndSize(data.data, data.size);
3289
3290 if (self->mydb->primaryDBType == DB_RECNO ||
3291 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003292 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293 else
3294 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3295
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003296 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003297 {
3298 PyObject *keyObj;
3299 int type = _DB_get_type(self->mydb);
3300 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003301 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302 else
3303 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003304#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003305 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003306#else
3307 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3308#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003309 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003310 FREE_DBT(key);
3311 }
3312 else /* return just the pkey and data */
3313 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003314#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003315 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003316#else
3317 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3318#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003319 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003320 Py_DECREF(dataObj);
3321 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003322 FREE_DBT(pkey);
3323 FREE_DBT(data);
3324 }
3325 /* the only time REALLOC should be set is if we used an integer
3326 * key that make_key_dbt malloc'd for us. always free these. */
3327 if (key.flags & DB_DBT_REALLOC) {
3328 FREE_DBT(key);
3329 }
3330 return retval;
3331}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003332#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003333
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003334
3335static PyObject*
3336DBC_get_recno(DBCursorObject* self, PyObject* args)
3337{
3338 int err;
3339 db_recno_t recno;
3340 DBT key;
3341 DBT data;
3342
3343 if (!PyArg_ParseTuple(args, ":get_recno"))
3344 return NULL;
3345
3346 CHECK_CURSOR_NOT_CLOSED(self);
3347
3348 CLEAR_DBT(key);
3349 CLEAR_DBT(data);
3350 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3351 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3352 data.flags = DB_DBT_MALLOC;
3353 key.flags = DB_DBT_MALLOC;
3354 }
3355
3356 MYDB_BEGIN_ALLOW_THREADS;
3357 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3358 MYDB_END_ALLOW_THREADS;
3359 RETURN_IF_ERR();
3360
3361 recno = *((db_recno_t*)data.data);
3362 FREE_DBT(key);
3363 FREE_DBT(data);
3364 return PyInt_FromLong(recno);
3365}
3366
3367
3368static PyObject*
3369DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3370{
3371 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3372}
3373
3374
3375static PyObject*
3376DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3377{
3378 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3379}
3380
3381
3382static PyObject*
3383DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3384{
3385 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3386}
3387
3388
3389static PyObject*
3390DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3391{
3392 int err, flags = 0;
3393 PyObject* keyobj, *dataobj;
3394 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003395 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003396 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003397 int dlen = -1;
3398 int doff = -1;
3399
3400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3401 &keyobj, &dataobj, &flags, &dlen, &doff))
3402 return NULL;
3403
3404 CHECK_CURSOR_NOT_CLOSED(self);
3405
3406 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3407 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003408 if (!make_dbt(dataobj, &data) ||
3409 !add_partial_dbt(&data, dlen, doff) )
3410 {
3411 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003413 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414
3415 MYDB_BEGIN_ALLOW_THREADS;
3416 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3417 MYDB_END_ALLOW_THREADS;
3418 FREE_DBT(key);
3419 RETURN_IF_ERR();
3420 self->mydb->haveStat = 0;
3421 RETURN_NONE();
3422}
3423
3424
3425static PyObject*
3426DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3427{
3428 int err, flags = 0;
3429 DBT key, data;
3430 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003431 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432 int dlen = -1;
3433 int doff = -1;
3434
3435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3436 &keyobj, &flags, &dlen, &doff))
3437 return NULL;
3438
3439 CHECK_CURSOR_NOT_CLOSED(self);
3440
3441 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3442 return NULL;
3443
3444 CLEAR_DBT(data);
3445 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3446 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3447 data.flags = DB_DBT_MALLOC;
3448 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 if (!add_partial_dbt(&data, dlen, doff)) {
3450 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003452 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003453
3454 MYDB_BEGIN_ALLOW_THREADS;
3455 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3456 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003457 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3458 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003459 Py_INCREF(Py_None);
3460 retval = Py_None;
3461 }
3462 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 retval = NULL;
3464 }
3465 else {
3466 switch (_DB_get_type(self->mydb)) {
3467 case -1:
3468 retval = NULL;
3469 break;
3470 case DB_BTREE:
3471 case DB_HASH:
3472 default:
3473 retval = Py_BuildValue("s#s#", key.data, key.size,
3474 data.data, data.size);
3475 break;
3476 case DB_RECNO:
3477 case DB_QUEUE:
3478 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3479 data.data, data.size);
3480 break;
3481 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003483 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003485 /* the only time REALLOC should be set is if we used an integer
3486 * key that make_key_dbt malloc'd for us. always free these. */
3487 if (key.flags & DB_DBT_REALLOC) {
3488 FREE_DBT(key);
3489 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003490
3491 return retval;
3492}
3493
3494
3495static PyObject*
3496DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3497{
3498 int err, flags = 0;
3499 DBT key, data;
3500 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003501 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003502 int dlen = -1;
3503 int doff = -1;
3504
3505 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3506 &keyobj, &flags, &dlen, &doff))
3507 return NULL;
3508
3509 CHECK_CURSOR_NOT_CLOSED(self);
3510
3511 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3512 return NULL;
3513
3514 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003515 if (!add_partial_dbt(&data, dlen, doff)) {
3516 FREE_DBT(key);
3517 return NULL;
3518 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003519 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3520 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003521 data.flags |= DB_DBT_MALLOC;
3522 /* only BTREE databases will return anything in the key */
3523 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3524 key.flags |= DB_DBT_MALLOC;
3525 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003526 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003527 MYDB_BEGIN_ALLOW_THREADS;
3528 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3529 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003530 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3531 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003532 Py_INCREF(Py_None);
3533 retval = Py_None;
3534 }
3535 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 retval = NULL;
3537 }
3538 else {
3539 switch (_DB_get_type(self->mydb)) {
3540 case -1:
3541 retval = NULL;
3542 break;
3543 case DB_BTREE:
3544 case DB_HASH:
3545 default:
3546 retval = Py_BuildValue("s#s#", key.data, key.size,
3547 data.data, data.size);
3548 break;
3549 case DB_RECNO:
3550 case DB_QUEUE:
3551 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3552 data.data, data.size);
3553 break;
3554 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003555 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556 FREE_DBT(data);
3557 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003558 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003559 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003560 if (key.flags & DB_DBT_REALLOC) {
3561 FREE_DBT(key);
3562 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003563
3564 return retval;
3565}
3566
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003568_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3569 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003571 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003573 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003574
Gregory P. Smith7441e652003-11-03 21:35:31 +00003575 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3577 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003578 if (!make_dbt(dataobj, &data)) {
3579 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003581 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582
3583 MYDB_BEGIN_ALLOW_THREADS;
3584 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3585 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003586 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003587 Py_INCREF(Py_None);
3588 retval = Py_None;
3589 }
3590 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003591 retval = NULL;
3592 }
3593 else {
3594 switch (_DB_get_type(self->mydb)) {
3595 case -1:
3596 retval = NULL;
3597 break;
3598 case DB_BTREE:
3599 case DB_HASH:
3600 default:
3601 retval = Py_BuildValue("s#s#", key.data, key.size,
3602 data.data, data.size);
3603 break;
3604 case DB_RECNO:
3605 case DB_QUEUE:
3606 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3607 data.data, data.size);
3608 break;
3609 }
3610 }
3611
3612 FREE_DBT(key);
3613 return retval;
3614}
3615
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003616static PyObject*
3617DBC_get_both(DBCursorObject* self, PyObject* args)
3618{
3619 int flags=0;
3620 PyObject *keyobj, *dataobj;
3621
3622 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3623 return NULL;
3624
Gregory P. Smith7441e652003-11-03 21:35:31 +00003625 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003626 CHECK_CURSOR_NOT_CLOSED(self);
3627
3628 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3629 self->mydb->moduleFlags.getReturnsNone);
3630}
3631
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003632/* Return size of entry */
3633static PyObject*
3634DBC_get_current_size(DBCursorObject* self, PyObject* args)
3635{
3636 int err, flags=DB_CURRENT;
3637 PyObject* retval = NULL;
3638 DBT key, data;
3639
3640 if (!PyArg_ParseTuple(args, ":get_current_size"))
3641 return NULL;
3642 CHECK_CURSOR_NOT_CLOSED(self);
3643 CLEAR_DBT(key);
3644 CLEAR_DBT(data);
3645
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003646 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003647 getting the record size. */
3648 data.flags = DB_DBT_USERMEM;
3649 data.ulen = 0;
3650 MYDB_BEGIN_ALLOW_THREADS;
3651 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3652 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003653 if (err == DB_BUFFER_SMALL || !err) {
3654 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003655 retval = PyInt_FromLong((long)data.size);
3656 err = 0;
3657 }
3658
3659 FREE_DBT(key);
3660 FREE_DBT(data);
3661 RETURN_IF_ERR();
3662 return retval;
3663}
3664
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665static PyObject*
3666DBC_set_both(DBCursorObject* self, PyObject* args)
3667{
3668 int flags=0;
3669 PyObject *keyobj, *dataobj;
3670
3671 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3672 return NULL;
3673
Gregory P. Smith7441e652003-11-03 21:35:31 +00003674 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003675 CHECK_CURSOR_NOT_CLOSED(self);
3676
3677 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3678 self->mydb->moduleFlags.cursorSetReturnsNone);
3679}
3680
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003681
3682static PyObject*
3683DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3684{
3685 int err, irecno, flags=0;
3686 db_recno_t recno;
3687 DBT key, data;
3688 PyObject* retval;
3689 int dlen = -1;
3690 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003691 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692
3693 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3694 &irecno, &flags, &dlen, &doff))
3695 return NULL;
3696
3697 CHECK_CURSOR_NOT_CLOSED(self);
3698
3699 CLEAR_DBT(key);
3700 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003701 /* use allocated space so DB will be able to realloc room for the real
3702 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003703 key.data = malloc(sizeof(db_recno_t));
3704 if (key.data == NULL) {
3705 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3706 return NULL;
3707 }
3708 key.size = sizeof(db_recno_t);
3709 key.ulen = key.size;
3710 memcpy(key.data, &recno, sizeof(db_recno_t));
3711 key.flags = DB_DBT_REALLOC;
3712
3713 CLEAR_DBT(data);
3714 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3715 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3716 data.flags = DB_DBT_MALLOC;
3717 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003718 if (!add_partial_dbt(&data, dlen, doff)) {
3719 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003720 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003721 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003722
3723 MYDB_BEGIN_ALLOW_THREADS;
3724 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3725 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003726 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3727 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003728 Py_INCREF(Py_None);
3729 retval = Py_None;
3730 }
3731 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732 retval = NULL;
3733 }
3734 else { /* Can only be used for BTrees, so no need to return int key */
3735 retval = Py_BuildValue("s#s#", key.data, key.size,
3736 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003737 FREE_DBT(data);
3738 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003739 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003740
3741 return retval;
3742}
3743
3744
3745static PyObject*
3746DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3747{
3748 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3749}
3750
3751
3752static PyObject*
3753DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3754{
3755 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3756}
3757
3758
3759static PyObject*
3760DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3761{
3762 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3763}
3764
3765
3766static PyObject*
3767DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3768{
3769 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3770}
3771
3772
3773static PyObject*
3774DBC_join_item(DBCursorObject* self, PyObject* args)
3775{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003776 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003777 DBT key, data;
3778 PyObject* retval;
3779
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003780 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003781 return NULL;
3782
3783 CHECK_CURSOR_NOT_CLOSED(self);
3784
3785 CLEAR_DBT(key);
3786 CLEAR_DBT(data);
3787 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3788 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3789 key.flags = DB_DBT_MALLOC;
3790 }
3791
3792 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003795 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3796 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003797 Py_INCREF(Py_None);
3798 retval = Py_None;
3799 }
3800 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003801 retval = NULL;
3802 }
3803 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003804 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003805 FREE_DBT(key);
3806 }
3807
3808 return retval;
3809}
3810
3811
3812
3813/* --------------------------------------------------------------------- */
3814/* DBEnv methods */
3815
3816
3817static PyObject*
3818DBEnv_close(DBEnvObject* self, PyObject* args)
3819{
3820 int err, flags = 0;
3821
3822 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3823 return NULL;
3824 if (!self->closed) { /* Don't close more than once */
3825 MYDB_BEGIN_ALLOW_THREADS;
3826 err = self->db_env->close(self->db_env, flags);
3827 MYDB_END_ALLOW_THREADS;
3828 /* after calling DBEnv->close, regardless of error, this DBEnv
3829 * may not be accessed again (BerkeleyDB docs). */
3830 self->closed = 1;
3831 self->db_env = NULL;
3832 RETURN_IF_ERR();
3833 }
3834 RETURN_NONE();
3835}
3836
3837
3838static PyObject*
3839DBEnv_open(DBEnvObject* self, PyObject* args)
3840{
3841 int err, flags=0, mode=0660;
3842 char *db_home;
3843
3844 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3845 return NULL;
3846
3847 CHECK_ENV_NOT_CLOSED(self);
3848
3849 MYDB_BEGIN_ALLOW_THREADS;
3850 err = self->db_env->open(self->db_env, db_home, flags, mode);
3851 MYDB_END_ALLOW_THREADS;
3852 RETURN_IF_ERR();
3853 self->closed = 0;
3854 self->flags = flags;
3855 RETURN_NONE();
3856}
3857
3858
3859static PyObject*
3860DBEnv_remove(DBEnvObject* self, PyObject* args)
3861{
3862 int err, flags=0;
3863 char *db_home;
3864
3865 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3866 return NULL;
3867 CHECK_ENV_NOT_CLOSED(self);
3868 MYDB_BEGIN_ALLOW_THREADS;
3869 err = self->db_env->remove(self->db_env, db_home, flags);
3870 MYDB_END_ALLOW_THREADS;
3871 RETURN_IF_ERR();
3872 RETURN_NONE();
3873}
3874
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003875#if (DBVER >= 41)
3876static PyObject*
3877DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3878{
3879 int err;
3880 u_int32_t flags=0;
3881 char *file = NULL;
3882 char *database = NULL;
3883 PyObject *txnobj = NULL;
3884 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003885 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003886 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003887
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003888 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003889 &file, &database, &txnobj, &flags)) {
3890 return NULL;
3891 }
3892 if (!checkTxnObj(txnobj, &txn)) {
3893 return NULL;
3894 }
3895 CHECK_ENV_NOT_CLOSED(self);
3896 MYDB_BEGIN_ALLOW_THREADS;
3897 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3898 MYDB_END_ALLOW_THREADS;
3899 RETURN_IF_ERR();
3900 RETURN_NONE();
3901}
3902
3903static PyObject*
3904DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3905{
3906 int err;
3907 u_int32_t flags=0;
3908 char *file = NULL;
3909 char *database = NULL;
3910 char *newname = NULL;
3911 PyObject *txnobj = NULL;
3912 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003913 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003914 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003915
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003916 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003917 &file, &database, &newname, &txnobj, &flags)) {
3918 return NULL;
3919 }
3920 if (!checkTxnObj(txnobj, &txn)) {
3921 return NULL;
3922 }
3923 CHECK_ENV_NOT_CLOSED(self);
3924 MYDB_BEGIN_ALLOW_THREADS;
3925 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3926 flags);
3927 MYDB_END_ALLOW_THREADS;
3928 RETURN_IF_ERR();
3929 RETURN_NONE();
3930}
3931
3932static PyObject*
3933DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3934{
3935 int err;
3936 u_int32_t flags=0;
3937 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003938 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003939
3940 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3941 &passwd, &flags)) {
3942 return NULL;
3943 }
3944
3945 MYDB_BEGIN_ALLOW_THREADS;
3946 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3947 MYDB_END_ALLOW_THREADS;
3948
3949 RETURN_IF_ERR();
3950 RETURN_NONE();
3951}
3952#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003953
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003954#if (DBVER >= 40)
3955static PyObject*
3956DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3957{
3958 int err;
3959 u_int32_t flags=0;
3960 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003961 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003962
3963 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3964 &timeout, &flags)) {
3965 return NULL;
3966 }
3967
3968 MYDB_BEGIN_ALLOW_THREADS;
3969 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3970 MYDB_END_ALLOW_THREADS;
3971
3972 RETURN_IF_ERR();
3973 RETURN_NONE();
3974}
3975#endif /* DBVER >= 40 */
3976
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003977static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003978DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3979{
3980 int err;
3981 long shm_key = 0;
3982
3983 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3984 return NULL;
3985 CHECK_ENV_NOT_CLOSED(self);
3986
3987 err = self->db_env->set_shm_key(self->db_env, shm_key);
3988 RETURN_IF_ERR();
3989 RETURN_NONE();
3990}
3991
3992static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3994{
3995 int err, gbytes=0, bytes=0, ncache=0;
3996
3997 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3998 &gbytes, &bytes, &ncache))
3999 return NULL;
4000 CHECK_ENV_NOT_CLOSED(self);
4001
4002 MYDB_BEGIN_ALLOW_THREADS;
4003 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4004 MYDB_END_ALLOW_THREADS;
4005 RETURN_IF_ERR();
4006 RETURN_NONE();
4007}
4008
4009
4010#if (DBVER >= 32)
4011static PyObject*
4012DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4013{
4014 int err, flags=0, onoff=0;
4015
4016 if (!PyArg_ParseTuple(args, "ii:set_flags",
4017 &flags, &onoff))
4018 return NULL;
4019 CHECK_ENV_NOT_CLOSED(self);
4020
4021 MYDB_BEGIN_ALLOW_THREADS;
4022 err = self->db_env->set_flags(self->db_env, flags, onoff);
4023 MYDB_END_ALLOW_THREADS;
4024 RETURN_IF_ERR();
4025 RETURN_NONE();
4026}
4027#endif
4028
4029
4030static PyObject*
4031DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4032{
4033 int err;
4034 char *dir;
4035
4036 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4037 return NULL;
4038 CHECK_ENV_NOT_CLOSED(self);
4039
4040 MYDB_BEGIN_ALLOW_THREADS;
4041 err = self->db_env->set_data_dir(self->db_env, dir);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4045}
4046
4047
4048static PyObject*
4049DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4050{
4051 int err, lg_bsize;
4052
4053 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4056
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063
4064
4065static PyObject*
4066DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4067{
4068 int err;
4069 char *dir;
4070
4071 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4072 return NULL;
4073 CHECK_ENV_NOT_CLOSED(self);
4074
4075 MYDB_BEGIN_ALLOW_THREADS;
4076 err = self->db_env->set_lg_dir(self->db_env, dir);
4077 MYDB_END_ALLOW_THREADS;
4078 RETURN_IF_ERR();
4079 RETURN_NONE();
4080}
4081
4082static PyObject*
4083DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4084{
4085 int err, lg_max;
4086
4087 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_lg_max(self->db_env, lg_max);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
4098
Neal Norwitz84562352005-10-20 04:30:15 +00004099#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004100static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004101DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4102{
4103 int err, lg_max;
4104
4105 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
Neal Norwitz84562352005-10-20 04:30:15 +00004115#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004116
4117
4118static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004119DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4120{
4121 int err, lk_detect;
4122
4123 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4124 return NULL;
4125 CHECK_ENV_NOT_CLOSED(self);
4126
4127 MYDB_BEGIN_ALLOW_THREADS;
4128 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4129 MYDB_END_ALLOW_THREADS;
4130 RETURN_IF_ERR();
4131 RETURN_NONE();
4132}
4133
4134
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004135#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004136static PyObject*
4137DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4138{
4139 int err, max;
4140
4141 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4144
4145 MYDB_BEGIN_ALLOW_THREADS;
4146 err = self->db_env->set_lk_max(self->db_env, max);
4147 MYDB_END_ALLOW_THREADS;
4148 RETURN_IF_ERR();
4149 RETURN_NONE();
4150}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004151#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004152
4153
4154#if (DBVER >= 32)
4155
4156static PyObject*
4157DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4158{
4159 int err, max;
4160
4161 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4162 return NULL;
4163 CHECK_ENV_NOT_CLOSED(self);
4164
4165 MYDB_BEGIN_ALLOW_THREADS;
4166 err = self->db_env->set_lk_max_locks(self->db_env, max);
4167 MYDB_END_ALLOW_THREADS;
4168 RETURN_IF_ERR();
4169 RETURN_NONE();
4170}
4171
4172
4173static PyObject*
4174DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4175{
4176 int err, max;
4177
4178 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4179 return NULL;
4180 CHECK_ENV_NOT_CLOSED(self);
4181
4182 MYDB_BEGIN_ALLOW_THREADS;
4183 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4184 MYDB_END_ALLOW_THREADS;
4185 RETURN_IF_ERR();
4186 RETURN_NONE();
4187}
4188
4189
4190static PyObject*
4191DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4192{
4193 int err, max;
4194
4195 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4196 return NULL;
4197 CHECK_ENV_NOT_CLOSED(self);
4198
4199 MYDB_BEGIN_ALLOW_THREADS;
4200 err = self->db_env->set_lk_max_objects(self->db_env, max);
4201 MYDB_END_ALLOW_THREADS;
4202 RETURN_IF_ERR();
4203 RETURN_NONE();
4204}
4205
4206#endif
4207
4208
4209static PyObject*
4210DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4211{
4212 int err, mp_mmapsize;
4213
4214 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4215 return NULL;
4216 CHECK_ENV_NOT_CLOSED(self);
4217
4218 MYDB_BEGIN_ALLOW_THREADS;
4219 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4220 MYDB_END_ALLOW_THREADS;
4221 RETURN_IF_ERR();
4222 RETURN_NONE();
4223}
4224
4225
4226static PyObject*
4227DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4228{
4229 int err;
4230 char *dir;
4231
4232 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4233 return NULL;
4234 CHECK_ENV_NOT_CLOSED(self);
4235
4236 MYDB_BEGIN_ALLOW_THREADS;
4237 err = self->db_env->set_tmp_dir(self->db_env, dir);
4238 MYDB_END_ALLOW_THREADS;
4239 RETURN_IF_ERR();
4240 RETURN_NONE();
4241}
4242
4243
4244static PyObject*
4245DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4246{
4247 int flags = 0;
4248 PyObject* txnobj = NULL;
4249 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004250 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004251
4252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4253 &txnobj, &flags))
4254 return NULL;
4255
4256 if (!checkTxnObj(txnobj, &txn))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4259
4260 return (PyObject*)newDBTxnObject(self, txn, flags);
4261}
4262
4263
4264static PyObject*
4265DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4266{
4267 int err, kbyte=0, min=0, flags=0;
4268
4269 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4270 return NULL;
4271 CHECK_ENV_NOT_CLOSED(self);
4272
4273 MYDB_BEGIN_ALLOW_THREADS;
4274#if (DBVER >= 40)
4275 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4276#else
4277 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4278#endif
4279 MYDB_END_ALLOW_THREADS;
4280 RETURN_IF_ERR();
4281 RETURN_NONE();
4282}
4283
4284
4285static PyObject*
4286DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4287{
4288 int err, max;
4289
4290 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4291 return NULL;
4292 CHECK_ENV_NOT_CLOSED(self);
4293
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004294 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004295 RETURN_IF_ERR();
4296 RETURN_NONE();
4297}
4298
4299
4300static PyObject*
4301DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4302{
4303 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004304 long stamp;
4305 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004306
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004307 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004308 return NULL;
4309 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004310 timestamp = (time_t)stamp;
4311 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004312 RETURN_IF_ERR();
4313 RETURN_NONE();
4314}
4315
4316
4317static PyObject*
4318DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4319{
4320 int err, atype, flags=0;
4321 int aborted = 0;
4322
4323 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4324 return NULL;
4325 CHECK_ENV_NOT_CLOSED(self);
4326
4327 MYDB_BEGIN_ALLOW_THREADS;
4328#if (DBVER >= 40)
4329 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4330#else
4331 err = lock_detect(self->db_env, flags, atype, &aborted);
4332#endif
4333 MYDB_END_ALLOW_THREADS;
4334 RETURN_IF_ERR();
4335 return PyInt_FromLong(aborted);
4336}
4337
4338
4339static PyObject*
4340DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4341{
4342 int flags=0;
4343 int locker, lock_mode;
4344 DBT obj;
4345 PyObject* objobj;
4346
4347 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4348 return NULL;
4349
4350
4351 if (!make_dbt(objobj, &obj))
4352 return NULL;
4353
4354 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4355}
4356
4357
4358static PyObject*
4359DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4360{
4361 int err;
4362 u_int32_t theID;
4363
4364 if (!PyArg_ParseTuple(args, ":lock_id"))
4365 return NULL;
4366
4367 CHECK_ENV_NOT_CLOSED(self);
4368 MYDB_BEGIN_ALLOW_THREADS;
4369#if (DBVER >= 40)
4370 err = self->db_env->lock_id(self->db_env, &theID);
4371#else
4372 err = lock_id(self->db_env, &theID);
4373#endif
4374 MYDB_END_ALLOW_THREADS;
4375 RETURN_IF_ERR();
4376
4377 return PyInt_FromLong((long)theID);
4378}
4379
4380
4381static PyObject*
4382DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4383{
4384 int err;
4385 DBLockObject* dblockobj;
4386
4387 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4388 return NULL;
4389
4390 CHECK_ENV_NOT_CLOSED(self);
4391 MYDB_BEGIN_ALLOW_THREADS;
4392#if (DBVER >= 40)
4393 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4394#else
4395 err = lock_put(self->db_env, &dblockobj->lock);
4396#endif
4397 MYDB_END_ALLOW_THREADS;
4398 RETURN_IF_ERR();
4399 RETURN_NONE();
4400}
4401
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004402#if (DBVER >= 44)
4403static PyObject*
4404DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4405{
4406 int err;
4407 char *file;
4408 u_int32_t flags = 0;
4409 static char* kwnames[] = { "file", "flags", NULL};
4410
4411 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4412 &file, &flags))
4413 return NULL;
4414 CHECK_ENV_NOT_CLOSED(self);
4415
4416 MYDB_BEGIN_ALLOW_THREADS;
4417 err = self->db_env->lsn_reset(self->db_env, file, flags);
4418 MYDB_END_ALLOW_THREADS;
4419 RETURN_IF_ERR();
4420 RETURN_NONE();
4421}
4422#endif /* DBVER >= 4.4 */
4423
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004424#if (DBVER >= 40)
4425static PyObject*
4426DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4427{
4428 int err;
4429 DB_LOG_STAT* statp = NULL;
4430 PyObject* d = NULL;
4431 u_int32_t flags = 0;
4432
4433 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4434 return NULL;
4435 CHECK_ENV_NOT_CLOSED(self);
4436
4437 MYDB_BEGIN_ALLOW_THREADS;
4438 err = self->db_env->log_stat(self->db_env, &statp, flags);
4439 MYDB_END_ALLOW_THREADS;
4440 RETURN_IF_ERR();
4441
4442 /* Turn the stat structure into a dictionary */
4443 d = PyDict_New();
4444 if (d == NULL) {
4445 if (statp)
4446 free(statp);
4447 return NULL;
4448 }
4449
4450#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4451
4452 MAKE_ENTRY(magic);
4453 MAKE_ENTRY(version);
4454 MAKE_ENTRY(mode);
4455 MAKE_ENTRY(lg_bsize);
4456#if (DBVER >= 44)
4457 MAKE_ENTRY(lg_size);
4458 MAKE_ENTRY(record);
4459#endif
4460#if (DBVER <= 40)
4461 MAKE_ENTRY(lg_max);
4462#endif
4463 MAKE_ENTRY(w_mbytes);
4464 MAKE_ENTRY(w_bytes);
4465 MAKE_ENTRY(wc_mbytes);
4466 MAKE_ENTRY(wc_bytes);
4467 MAKE_ENTRY(wcount);
4468 MAKE_ENTRY(wcount_fill);
4469#if (DBVER >= 44)
4470 MAKE_ENTRY(rcount);
4471#endif
4472 MAKE_ENTRY(scount);
4473 MAKE_ENTRY(cur_file);
4474 MAKE_ENTRY(cur_offset);
4475 MAKE_ENTRY(disk_file);
4476 MAKE_ENTRY(disk_offset);
4477 MAKE_ENTRY(maxcommitperflush);
4478 MAKE_ENTRY(mincommitperflush);
4479 MAKE_ENTRY(regsize);
4480 MAKE_ENTRY(region_wait);
4481 MAKE_ENTRY(region_nowait);
4482
4483#undef MAKE_ENTRY
4484 free(statp);
4485 return d;
4486} /* DBEnv_log_stat */
4487#endif /* DBVER >= 4.0 for log_stat method */
4488
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004489
4490static PyObject*
4491DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4492{
4493 int err;
4494 DB_LOCK_STAT* sp;
4495 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004496 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004497
4498 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4499 return NULL;
4500 CHECK_ENV_NOT_CLOSED(self);
4501
4502 MYDB_BEGIN_ALLOW_THREADS;
4503#if (DBVER >= 40)
4504 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4505#else
4506#if (DBVER >= 33)
4507 err = lock_stat(self->db_env, &sp);
4508#else
4509 err = lock_stat(self->db_env, &sp, NULL);
4510#endif
4511#endif
4512 MYDB_END_ALLOW_THREADS;
4513 RETURN_IF_ERR();
4514
4515 /* Turn the stat structure into a dictionary */
4516 d = PyDict_New();
4517 if (d == NULL) {
4518 free(sp);
4519 return NULL;
4520 }
4521
4522#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4523
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004524#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004525 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004526#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004527 MAKE_ENTRY(nmodes);
4528#if (DBVER >= 32)
4529 MAKE_ENTRY(maxlocks);
4530 MAKE_ENTRY(maxlockers);
4531 MAKE_ENTRY(maxobjects);
4532 MAKE_ENTRY(nlocks);
4533 MAKE_ENTRY(maxnlocks);
4534#endif
4535 MAKE_ENTRY(nlockers);
4536 MAKE_ENTRY(maxnlockers);
4537#if (DBVER >= 32)
4538 MAKE_ENTRY(nobjects);
4539 MAKE_ENTRY(maxnobjects);
4540#endif
4541 MAKE_ENTRY(nrequests);
4542 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004543#if (DBVER < 44)
4544 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004546#else
4547 MAKE_ENTRY(lock_nowait);
4548 MAKE_ENTRY(lock_wait);
4549#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004550 MAKE_ENTRY(ndeadlocks);
4551 MAKE_ENTRY(regsize);
4552 MAKE_ENTRY(region_wait);
4553 MAKE_ENTRY(region_nowait);
4554
4555#undef MAKE_ENTRY
4556 free(sp);
4557 return d;
4558}
4559
4560
4561static PyObject*
4562DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4563{
4564 int flags=0;
4565 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004566 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004567 PyObject* list;
4568 PyObject* item = NULL;
4569
4570 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4571 return NULL;
4572
4573 CHECK_ENV_NOT_CLOSED(self);
4574 MYDB_BEGIN_ALLOW_THREADS;
4575#if (DBVER >= 40)
4576 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4577#elif (DBVER == 33)
4578 err = log_archive(self->db_env, &log_list, flags);
4579#else
4580 err = log_archive(self->db_env, &log_list, flags, NULL);
4581#endif
4582 MYDB_END_ALLOW_THREADS;
4583 RETURN_IF_ERR();
4584
Gregory P. Smithbad47452006-06-05 00:33:35 +00004585 list = PyList_New(0);
4586 if (list == NULL) {
4587 if (log_list)
4588 free(log_list);
4589 return NULL;
4590 }
4591
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004592 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004593 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004594 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4595 item = PyString_FromString (*log_list);
4596 if (item == NULL) {
4597 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 list = NULL;
4599 break;
4600 }
4601 PyList_Append(list, item);
4602 Py_DECREF(item);
4603 }
4604 free(log_list_start);
4605 }
4606 return list;
4607}
4608
4609
4610static PyObject*
4611DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4612{
4613 int err;
4614 DB_TXN_STAT* sp;
4615 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004616 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004617
4618 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4619 return NULL;
4620 CHECK_ENV_NOT_CLOSED(self);
4621
4622 MYDB_BEGIN_ALLOW_THREADS;
4623#if (DBVER >= 40)
4624 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4625#elif (DBVER == 33)
4626 err = txn_stat(self->db_env, &sp);
4627#else
4628 err = txn_stat(self->db_env, &sp, NULL);
4629#endif
4630 MYDB_END_ALLOW_THREADS;
4631 RETURN_IF_ERR();
4632
4633 /* Turn the stat structure into a dictionary */
4634 d = PyDict_New();
4635 if (d == NULL) {
4636 free(sp);
4637 return NULL;
4638 }
4639
4640#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4641
4642 MAKE_ENTRY(time_ckp);
4643 MAKE_ENTRY(last_txnid);
4644 MAKE_ENTRY(maxtxns);
4645 MAKE_ENTRY(nactive);
4646 MAKE_ENTRY(maxnactive);
4647 MAKE_ENTRY(nbegins);
4648 MAKE_ENTRY(naborts);
4649 MAKE_ENTRY(ncommits);
4650 MAKE_ENTRY(regsize);
4651 MAKE_ENTRY(region_wait);
4652 MAKE_ENTRY(region_nowait);
4653
4654#undef MAKE_ENTRY
4655 free(sp);
4656 return d;
4657}
4658
4659
4660static PyObject*
4661DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4662{
4663 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004664 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004665
4666 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4667 return NULL;
4668 CHECK_ENV_NOT_CLOSED(self);
4669
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004670 if (self->moduleFlags.getReturnsNone)
4671 ++oldValue;
4672 if (self->moduleFlags.cursorSetReturnsNone)
4673 ++oldValue;
4674 self->moduleFlags.getReturnsNone = (flags >= 1);
4675 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004676 return PyInt_FromLong(oldValue);
4677}
4678
4679
4680/* --------------------------------------------------------------------- */
4681/* DBTxn methods */
4682
4683
4684static PyObject*
4685DBTxn_commit(DBTxnObject* self, PyObject* args)
4686{
4687 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004688 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004689
4690 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4691 return NULL;
4692
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004693 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004694 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4695 "after txn_commit or txn_abort");
4696 PyErr_SetObject(DBError, t);
4697 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004698 return NULL;
4699 }
4700 txn = self->txn;
4701 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702 MYDB_BEGIN_ALLOW_THREADS;
4703#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004704 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004705#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004706 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004707#endif
4708 MYDB_END_ALLOW_THREADS;
4709 RETURN_IF_ERR();
4710 RETURN_NONE();
4711}
4712
4713static PyObject*
4714DBTxn_prepare(DBTxnObject* self, PyObject* args)
4715{
4716#if (DBVER >= 33)
4717 int err;
4718 char* gid=NULL;
4719 int gid_size=0;
4720
4721 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4722 return NULL;
4723
4724 if (gid_size != DB_XIDDATASIZE) {
4725 PyErr_SetString(PyExc_TypeError,
4726 "gid must be DB_XIDDATASIZE bytes long");
4727 return NULL;
4728 }
4729
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004730 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004731 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4732 "after txn_commit or txn_abort");
4733 PyErr_SetObject(DBError, t);
4734 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004735 return NULL;
4736 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004737 MYDB_BEGIN_ALLOW_THREADS;
4738#if (DBVER >= 40)
4739 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4740#else
4741 err = txn_prepare(self->txn, (u_int8_t*)gid);
4742#endif
4743 MYDB_END_ALLOW_THREADS;
4744 RETURN_IF_ERR();
4745 RETURN_NONE();
4746#else
4747 int err;
4748
4749 if (!PyArg_ParseTuple(args, ":prepare"))
4750 return NULL;
4751
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004752 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004753 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4754 "after txn_commit or txn_abort");
4755 PyErr_SetObject(DBError, t);
4756 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004757 return NULL;
4758 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004759 MYDB_BEGIN_ALLOW_THREADS;
4760 err = txn_prepare(self->txn);
4761 MYDB_END_ALLOW_THREADS;
4762 RETURN_IF_ERR();
4763 RETURN_NONE();
4764#endif
4765}
4766
4767
4768static PyObject*
4769DBTxn_abort(DBTxnObject* self, PyObject* args)
4770{
4771 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004772 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004773
4774 if (!PyArg_ParseTuple(args, ":abort"))
4775 return NULL;
4776
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004777 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004778 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4779 "after txn_commit or txn_abort");
4780 PyErr_SetObject(DBError, t);
4781 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004782 return NULL;
4783 }
4784 txn = self->txn;
4785 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004786 MYDB_BEGIN_ALLOW_THREADS;
4787#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004788 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004789#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004790 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791#endif
4792 MYDB_END_ALLOW_THREADS;
4793 RETURN_IF_ERR();
4794 RETURN_NONE();
4795}
4796
4797
4798static PyObject*
4799DBTxn_id(DBTxnObject* self, PyObject* args)
4800{
4801 int id;
4802
4803 if (!PyArg_ParseTuple(args, ":id"))
4804 return NULL;
4805
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004807 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4808 "after txn_commit or txn_abort");
4809 PyErr_SetObject(DBError, t);
4810 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004811 return NULL;
4812 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813 MYDB_BEGIN_ALLOW_THREADS;
4814#if (DBVER >= 40)
4815 id = self->txn->id(self->txn);
4816#else
4817 id = txn_id(self->txn);
4818#endif
4819 MYDB_END_ALLOW_THREADS;
4820 return PyInt_FromLong(id);
4821}
4822
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004823#if (DBVER >= 43)
4824/* --------------------------------------------------------------------- */
4825/* DBSequence methods */
4826
4827
4828static PyObject*
4829DBSequence_close(DBSequenceObject* self, PyObject* args)
4830{
4831 int err, flags=0;
4832 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4833 return NULL;
4834 CHECK_SEQUENCE_NOT_CLOSED(self)
4835
4836 MYDB_BEGIN_ALLOW_THREADS
4837 err = self->sequence->close(self->sequence, flags);
4838 self->sequence = NULL;
4839 MYDB_END_ALLOW_THREADS
4840
4841 RETURN_IF_ERR();
4842
4843 RETURN_NONE();
4844}
4845
4846static PyObject*
4847DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4848{
4849 int err, flags = 0;
4850 int delta = 1;
4851 db_seq_t value;
4852 PyObject *txnobj = NULL;
4853 DB_TXN *txn = NULL;
4854 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4855 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4856 return NULL;
4857 CHECK_SEQUENCE_NOT_CLOSED(self)
4858
4859 if (!checkTxnObj(txnobj, &txn))
4860 return NULL;
4861
4862 MYDB_BEGIN_ALLOW_THREADS
4863 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4864 MYDB_END_ALLOW_THREADS
4865
4866 RETURN_IF_ERR();
4867 return PyLong_FromLongLong(value);
4868
4869}
4870
4871static PyObject*
4872DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4873{
4874 if (!PyArg_ParseTuple(args,":get_dbp"))
4875 return NULL;
4876 CHECK_SEQUENCE_NOT_CLOSED(self)
4877 Py_INCREF(self->mydb);
4878 return (PyObject* )self->mydb;
4879}
4880
4881static PyObject*
4882DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4883{
4884 int err;
4885 DBT key;
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004886 PyObject *retval;
4887 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004888 CHECK_SEQUENCE_NOT_CLOSED(self)
4889 MYDB_BEGIN_ALLOW_THREADS
4890 err = self->sequence->get_key(self->sequence, &key);
4891 MYDB_END_ALLOW_THREADS
4892
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004893 if (!err)
4894 retval = PyString_FromStringAndSize(key.data, key.size);
4895
4896 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004897 RETURN_IF_ERR();
4898
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004899 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004900}
4901
4902static PyObject*
4903DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4904{
4905 int err;
4906 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004907 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004908 return NULL;
4909 CHECK_SEQUENCE_NOT_CLOSED(self)
4910
4911 MYDB_BEGIN_ALLOW_THREADS
4912 err = self->sequence->initial_value(self->sequence, value);
4913 MYDB_END_ALLOW_THREADS
4914
4915 RETURN_IF_ERR();
4916
4917 RETURN_NONE();
4918}
4919
4920static PyObject*
4921DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4922{
4923 int err, flags = 0;
4924 PyObject* keyobj;
4925 PyObject *txnobj = NULL;
4926 DB_TXN *txn = NULL;
4927 DBT key;
4928
4929 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004931 return NULL;
4932
4933 if (!checkTxnObj(txnobj, &txn))
4934 return NULL;
4935
4936 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4937 return NULL;
4938
4939 MYDB_BEGIN_ALLOW_THREADS
4940 err = self->sequence->open(self->sequence, txn, &key, flags);
4941 MYDB_END_ALLOW_THREADS
4942
4943 CLEAR_DBT(key);
4944 RETURN_IF_ERR();
4945
4946 RETURN_NONE();
4947}
4948
4949static PyObject*
4950DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4951{
4952 int err, flags = 0;
4953 PyObject *txnobj = NULL;
4954 DB_TXN *txn = NULL;
4955
4956 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004957 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004958 return NULL;
4959
4960 if (!checkTxnObj(txnobj, &txn))
4961 return NULL;
4962
4963 CHECK_SEQUENCE_NOT_CLOSED(self)
4964
4965 MYDB_BEGIN_ALLOW_THREADS
4966 err = self->sequence->remove(self->sequence, txn, flags);
4967 MYDB_END_ALLOW_THREADS
4968
4969 RETURN_IF_ERR();
4970 RETURN_NONE();
4971}
4972
4973static PyObject*
4974DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4975{
4976 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004977 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004978 return NULL;
4979 CHECK_SEQUENCE_NOT_CLOSED(self)
4980
4981 MYDB_BEGIN_ALLOW_THREADS
4982 err = self->sequence->set_cachesize(self->sequence, size);
4983 MYDB_END_ALLOW_THREADS
4984
4985 RETURN_IF_ERR();
4986 RETURN_NONE();
4987}
4988
4989static PyObject*
4990DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4991{
4992 int err, size;
4993 if (!PyArg_ParseTuple(args,":get_cachesize"))
4994 return NULL;
4995 CHECK_SEQUENCE_NOT_CLOSED(self)
4996
4997 MYDB_BEGIN_ALLOW_THREADS
4998 err = self->sequence->get_cachesize(self->sequence, &size);
4999 MYDB_END_ALLOW_THREADS
5000
5001 RETURN_IF_ERR();
5002 return PyInt_FromLong(size);
5003}
5004
5005static PyObject*
5006DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5007{
5008 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005009 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005010 return NULL;
5011 CHECK_SEQUENCE_NOT_CLOSED(self)
5012
5013 MYDB_BEGIN_ALLOW_THREADS
5014 err = self->sequence->set_flags(self->sequence, flags);
5015 MYDB_END_ALLOW_THREADS
5016
5017 RETURN_IF_ERR();
5018 RETURN_NONE();
5019
5020}
5021
5022static PyObject*
5023DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5024{
5025 unsigned int flags;
5026 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005027 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005028 return NULL;
5029 CHECK_SEQUENCE_NOT_CLOSED(self)
5030
5031 MYDB_BEGIN_ALLOW_THREADS
5032 err = self->sequence->get_flags(self->sequence, &flags);
5033 MYDB_END_ALLOW_THREADS
5034
5035 RETURN_IF_ERR();
5036 return PyInt_FromLong((int)flags);
5037}
5038
5039static PyObject*
5040DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5041{
5042 int err;
5043 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005044 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005045 return NULL;
5046 CHECK_SEQUENCE_NOT_CLOSED(self)
5047
5048 MYDB_BEGIN_ALLOW_THREADS
5049 err = self->sequence->set_range(self->sequence, min, max);
5050 MYDB_END_ALLOW_THREADS
5051
5052 RETURN_IF_ERR();
5053 RETURN_NONE();
5054}
5055
5056static PyObject*
5057DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5058{
5059 int err;
5060 db_seq_t min, max;
5061 if (!PyArg_ParseTuple(args,":get_range"))
5062 return NULL;
5063 CHECK_SEQUENCE_NOT_CLOSED(self)
5064
5065 MYDB_BEGIN_ALLOW_THREADS
5066 err = self->sequence->get_range(self->sequence, &min, &max);
5067 MYDB_END_ALLOW_THREADS
5068
5069 RETURN_IF_ERR();
5070 return Py_BuildValue("(LL)", min, max);
5071}
5072
5073static PyObject*
5074DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5075{
5076 int err, flags = 0;
5077 DB_SEQUENCE_STAT* sp = NULL;
5078 PyObject* dict_stat;
5079 static char* kwnames[] = {"flags", NULL };
5080 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5081 return NULL;
5082 CHECK_SEQUENCE_NOT_CLOSED(self);
5083
5084 MYDB_BEGIN_ALLOW_THREADS;
5085 err = self->sequence->stat(self->sequence, &sp, flags);
5086 MYDB_END_ALLOW_THREADS;
5087 RETURN_IF_ERR();
5088
5089 if ((dict_stat = PyDict_New()) == NULL) {
5090 free(sp);
5091 return NULL;
5092 }
5093
5094
5095#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5096#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5097
5098 MAKE_INT_ENTRY(wait);
5099 MAKE_INT_ENTRY(nowait);
5100 MAKE_LONG_LONG_ENTRY(current);
5101 MAKE_LONG_LONG_ENTRY(value);
5102 MAKE_LONG_LONG_ENTRY(last_value);
5103 MAKE_LONG_LONG_ENTRY(min);
5104 MAKE_LONG_LONG_ENTRY(max);
5105 MAKE_INT_ENTRY(cache_size);
5106 MAKE_INT_ENTRY(flags);
5107
5108#undef MAKE_INT_ENTRY
5109#undef MAKE_LONG_LONG_ENTRY
5110
5111 free(sp);
5112 return dict_stat;
5113}
5114#endif
5115
5116
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005117/* --------------------------------------------------------------------- */
5118/* Method definition tables and type objects */
5119
5120static PyMethodDef DB_methods[] = {
5121 {"append", (PyCFunction)DB_append, METH_VARARGS},
5122#if (DBVER >= 33)
5123 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5124#endif
5125 {"close", (PyCFunction)DB_close, METH_VARARGS},
5126#if (DBVER >= 32)
5127 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5128 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5129#endif
5130 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5131 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5132 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5133 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005134#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005135 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005136#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005137 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5138 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5139 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5140 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5141 {"join", (PyCFunction)DB_join, METH_VARARGS},
5142 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5143 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5144 {"items", (PyCFunction)DB_items, METH_VARARGS},
5145 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5146 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5147 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5148 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5149 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5150 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005151#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005152 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005153#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005155#if (DBVER >= 41)
5156 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5157#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5159 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5160 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5161 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5162 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5163 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5164 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5165 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5166 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5167#if (DBVER >= 32)
5168 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5169#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005170 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005171 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5172#if (DBVER >= 33)
5173 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5174#endif
5175 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5176 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5177 {"values", (PyCFunction)DB_values, METH_VARARGS},
5178 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5179 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5180 {NULL, NULL} /* sentinel */
5181};
5182
5183
5184static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005185 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005186 (binaryfunc)DB_subscript, /*mp_subscript*/
5187 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5188};
5189
5190
5191static PyMethodDef DBCursor_methods[] = {
5192 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5193 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5194 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5195 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5196 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5197 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5198 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005199#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005200 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005201#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005202 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5203 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5204 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5205 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5206 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5207 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5208 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5209 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005210 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005211 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005212 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5213 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5214 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5215 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5216 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5217 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5218 {NULL, NULL} /* sentinel */
5219};
5220
5221
5222static PyMethodDef DBEnv_methods[] = {
5223 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5224 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5225 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005226#if (DBVER >= 41)
5227 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5228 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5229 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5230#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005231#if (DBVER >= 40)
5232 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5233#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005234 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005235 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5236 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5237#if (DBVER >= 32)
5238 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5239#endif
5240 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5241 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5242 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005243#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005244 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005245#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005246 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005247#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005248 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005249#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005250#if (DBVER >= 32)
5251 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5252 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5253 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5254#endif
5255 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5256 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5257 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5258 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5259 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5260 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005261 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5263 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5264 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5265 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5266 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5267 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005268#if (DBVER >= 40)
5269 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5270#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005271#if (DBVER >= 44)
5272 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5273#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005274 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5275 {NULL, NULL} /* sentinel */
5276};
5277
5278
5279static PyMethodDef DBTxn_methods[] = {
5280 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5281 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5282 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5283 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5284 {NULL, NULL} /* sentinel */
5285};
5286
5287
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005288#if (DBVER >= 43)
5289static PyMethodDef DBSequence_methods[] = {
5290 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5291 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5292 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5293 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005294 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5295 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5296 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5297 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5298 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5299 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5300 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5301 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5302 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5303 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5304 {NULL, NULL} /* sentinel */
5305};
5306#endif
5307
5308
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005309static PyObject*
5310DB_getattr(DBObject* self, char *name)
5311{
5312 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5313}
5314
5315
5316static PyObject*
5317DBEnv_getattr(DBEnvObject* self, char *name)
5318{
5319 if (!strcmp(name, "db_home")) {
5320 CHECK_ENV_NOT_CLOSED(self);
5321 if (self->db_env->db_home == NULL) {
5322 RETURN_NONE();
5323 }
5324 return PyString_FromString(self->db_env->db_home);
5325 }
5326
5327 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5328}
5329
5330
5331static PyObject*
5332DBCursor_getattr(DBCursorObject* self, char *name)
5333{
5334 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5335}
5336
5337static PyObject*
5338DBTxn_getattr(DBTxnObject* self, char *name)
5339{
5340 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5341}
5342
5343static PyObject*
5344DBLock_getattr(DBLockObject* self, char *name)
5345{
5346 return NULL;
5347}
5348
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005349#if (DBVER >= 43)
5350static PyObject*
5351DBSequence_getattr(DBSequenceObject* self, char *name)
5352{
5353 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5354}
5355#endif
5356
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005357statichere PyTypeObject DB_Type = {
5358 PyObject_HEAD_INIT(NULL)
5359 0, /*ob_size*/
5360 "DB", /*tp_name*/
5361 sizeof(DBObject), /*tp_basicsize*/
5362 0, /*tp_itemsize*/
5363 /* methods */
5364 (destructor)DB_dealloc, /*tp_dealloc*/
5365 0, /*tp_print*/
5366 (getattrfunc)DB_getattr, /*tp_getattr*/
5367 0, /*tp_setattr*/
5368 0, /*tp_compare*/
5369 0, /*tp_repr*/
5370 0, /*tp_as_number*/
5371 0, /*tp_as_sequence*/
5372 &DB_mapping,/*tp_as_mapping*/
5373 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005374#ifdef HAVE_WEAKREF
5375 0, /* tp_call */
5376 0, /* tp_str */
5377 0, /* tp_getattro */
5378 0, /* tp_setattro */
5379 0, /* tp_as_buffer */
5380 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5381 0, /* tp_doc */
5382 0, /* tp_traverse */
5383 0, /* tp_clear */
5384 0, /* tp_richcompare */
5385 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5386#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005387};
5388
5389
5390statichere PyTypeObject DBCursor_Type = {
5391 PyObject_HEAD_INIT(NULL)
5392 0, /*ob_size*/
5393 "DBCursor", /*tp_name*/
5394 sizeof(DBCursorObject), /*tp_basicsize*/
5395 0, /*tp_itemsize*/
5396 /* methods */
5397 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5398 0, /*tp_print*/
5399 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5400 0, /*tp_setattr*/
5401 0, /*tp_compare*/
5402 0, /*tp_repr*/
5403 0, /*tp_as_number*/
5404 0, /*tp_as_sequence*/
5405 0, /*tp_as_mapping*/
5406 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005407#ifdef HAVE_WEAKREF
5408 0, /* tp_call */
5409 0, /* tp_str */
5410 0, /* tp_getattro */
5411 0, /* tp_setattro */
5412 0, /* tp_as_buffer */
5413 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5414 0, /* tp_doc */
5415 0, /* tp_traverse */
5416 0, /* tp_clear */
5417 0, /* tp_richcompare */
5418 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5419#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005420};
5421
5422
5423statichere PyTypeObject DBEnv_Type = {
5424 PyObject_HEAD_INIT(NULL)
5425 0, /*ob_size*/
5426 "DBEnv", /*tp_name*/
5427 sizeof(DBEnvObject), /*tp_basicsize*/
5428 0, /*tp_itemsize*/
5429 /* methods */
5430 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5431 0, /*tp_print*/
5432 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5433 0, /*tp_setattr*/
5434 0, /*tp_compare*/
5435 0, /*tp_repr*/
5436 0, /*tp_as_number*/
5437 0, /*tp_as_sequence*/
5438 0, /*tp_as_mapping*/
5439 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005440#ifdef HAVE_WEAKREF
5441 0, /* tp_call */
5442 0, /* tp_str */
5443 0, /* tp_getattro */
5444 0, /* tp_setattro */
5445 0, /* tp_as_buffer */
5446 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5447 0, /* tp_doc */
5448 0, /* tp_traverse */
5449 0, /* tp_clear */
5450 0, /* tp_richcompare */
5451 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5452#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005453};
5454
5455statichere PyTypeObject DBTxn_Type = {
5456 PyObject_HEAD_INIT(NULL)
5457 0, /*ob_size*/
5458 "DBTxn", /*tp_name*/
5459 sizeof(DBTxnObject), /*tp_basicsize*/
5460 0, /*tp_itemsize*/
5461 /* methods */
5462 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5463 0, /*tp_print*/
5464 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5465 0, /*tp_setattr*/
5466 0, /*tp_compare*/
5467 0, /*tp_repr*/
5468 0, /*tp_as_number*/
5469 0, /*tp_as_sequence*/
5470 0, /*tp_as_mapping*/
5471 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005472#ifdef HAVE_WEAKREF
5473 0, /* tp_call */
5474 0, /* tp_str */
5475 0, /* tp_getattro */
5476 0, /* tp_setattro */
5477 0, /* tp_as_buffer */
5478 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5479 0, /* tp_doc */
5480 0, /* tp_traverse */
5481 0, /* tp_clear */
5482 0, /* tp_richcompare */
5483 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5484#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005485};
5486
5487
5488statichere PyTypeObject DBLock_Type = {
5489 PyObject_HEAD_INIT(NULL)
5490 0, /*ob_size*/
5491 "DBLock", /*tp_name*/
5492 sizeof(DBLockObject), /*tp_basicsize*/
5493 0, /*tp_itemsize*/
5494 /* methods */
5495 (destructor)DBLock_dealloc, /*tp_dealloc*/
5496 0, /*tp_print*/
5497 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5498 0, /*tp_setattr*/
5499 0, /*tp_compare*/
5500 0, /*tp_repr*/
5501 0, /*tp_as_number*/
5502 0, /*tp_as_sequence*/
5503 0, /*tp_as_mapping*/
5504 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005505#ifdef HAVE_WEAKREF
5506 0, /* tp_call */
5507 0, /* tp_str */
5508 0, /* tp_getattro */
5509 0, /* tp_setattro */
5510 0, /* tp_as_buffer */
5511 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5512 0, /* tp_doc */
5513 0, /* tp_traverse */
5514 0, /* tp_clear */
5515 0, /* tp_richcompare */
5516 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005518};
5519
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005520#if (DBVER >= 43)
5521statichere PyTypeObject DBSequence_Type = {
5522 PyObject_HEAD_INIT(NULL)
5523 0, /*ob_size*/
5524 "DBSequence", /*tp_name*/
5525 sizeof(DBSequenceObject), /*tp_basicsize*/
5526 0, /*tp_itemsize*/
5527 /* methods */
5528 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5529 0, /*tp_print*/
5530 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5531 0, /*tp_setattr*/
5532 0, /*tp_compare*/
5533 0, /*tp_repr*/
5534 0, /*tp_as_number*/
5535 0, /*tp_as_sequence*/
5536 0, /*tp_as_mapping*/
5537 0, /*tp_hash*/
5538#ifdef HAVE_WEAKREF
5539 0, /* tp_call */
5540 0, /* tp_str */
5541 0, /* tp_getattro */
5542 0, /* tp_setattro */
5543 0, /* tp_as_buffer */
5544 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5545 0, /* tp_doc */
5546 0, /* tp_traverse */
5547 0, /* tp_clear */
5548 0, /* tp_richcompare */
5549 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5550#endif
5551};
5552#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005553
5554/* --------------------------------------------------------------------- */
5555/* Module-level functions */
5556
5557static PyObject*
5558DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5559{
5560 PyObject* dbenvobj = NULL;
5561 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005562 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5565 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005566 return NULL;
5567 if (dbenvobj == Py_None)
5568 dbenvobj = NULL;
5569 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5570 makeTypeError("DBEnv", dbenvobj);
5571 return NULL;
5572 }
5573
5574 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5575}
5576
5577
5578static PyObject*
5579DBEnv_construct(PyObject* self, PyObject* args)
5580{
5581 int flags = 0;
5582 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5583 return (PyObject* )newDBEnvObject(flags);
5584}
5585
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005586#if (DBVER >= 43)
5587static PyObject*
5588DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5589{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005590 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005591 int flags = 0;
5592 static char* kwnames[] = { "db", "flags", NULL};
5593
5594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5595 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005596 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005597 makeTypeError("DB", dbobj);
5598 return NULL;
5599 }
5600 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5601}
5602#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005603
5604static char bsddb_version_doc[] =
5605"Returns a tuple of major, minor, and patch release numbers of the\n\
5606underlying DB library.";
5607
5608static PyObject*
5609bsddb_version(PyObject* self, PyObject* args)
5610{
5611 int major, minor, patch;
5612
5613 if (!PyArg_ParseTuple(args, ":version"))
5614 return NULL;
5615 db_version(&major, &minor, &patch);
5616 return Py_BuildValue("(iii)", major, minor, patch);
5617}
5618
5619
5620/* List of functions defined in the module */
5621
5622static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005623 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5624 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5625#if (DBVER >= 43)
5626 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5627#endif
5628 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005629 {NULL, NULL} /* sentinel */
5630};
5631
5632
5633/* --------------------------------------------------------------------- */
5634/* Module initialization */
5635
5636
5637/* Convenience routine to export an integer value.
5638 * Errors are silently ignored, for better or for worse...
5639 */
5640#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5641
Gregory P. Smith41631e82003-09-21 00:08:14 +00005642#define MODULE_NAME_MAX_LEN 11
5643static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644
5645DL_EXPORT(void) init_bsddb(void)
5646{
5647 PyObject* m;
5648 PyObject* d;
5649 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5650 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5651 PyObject* cvsid_s = PyString_FromString( rcs_id );
5652
5653 /* Initialize the type of the new type objects here; doing it here
5654 is required for portability to Windows without requiring C++. */
5655 DB_Type.ob_type = &PyType_Type;
5656 DBCursor_Type.ob_type = &PyType_Type;
5657 DBEnv_Type.ob_type = &PyType_Type;
5658 DBTxn_Type.ob_type = &PyType_Type;
5659 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005660#if (DBVER >= 43)
5661 DBSequence_Type.ob_type = &PyType_Type;
5662#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005663
5664
Mark Hammonda69d4092003-04-22 23:13:27 +00005665#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005666 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005667 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005668#endif
5669
5670 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005671 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005672 if (m == NULL)
5673 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005674
5675 /* Add some symbolic constants to the module */
5676 d = PyModule_GetDict(m);
5677 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5678 PyDict_SetItemString(d, "cvsid", cvsid_s);
5679 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5680 Py_DECREF(pybsddb_version_s);
5681 pybsddb_version_s = NULL;
5682 Py_DECREF(cvsid_s);
5683 cvsid_s = NULL;
5684 Py_DECREF(db_version_s);
5685 db_version_s = NULL;
5686
5687 ADD_INT(d, DB_VERSION_MAJOR);
5688 ADD_INT(d, DB_VERSION_MINOR);
5689 ADD_INT(d, DB_VERSION_PATCH);
5690
5691 ADD_INT(d, DB_MAX_PAGES);
5692 ADD_INT(d, DB_MAX_RECORDS);
5693
Gregory P. Smith41631e82003-09-21 00:08:14 +00005694#if (DBVER >= 42)
5695 ADD_INT(d, DB_RPCCLIENT);
5696#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005697 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005698 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5699 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5700#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005701 ADD_INT(d, DB_XA_CREATE);
5702
5703 ADD_INT(d, DB_CREATE);
5704 ADD_INT(d, DB_NOMMAP);
5705 ADD_INT(d, DB_THREAD);
5706
5707 ADD_INT(d, DB_FORCE);
5708 ADD_INT(d, DB_INIT_CDB);
5709 ADD_INT(d, DB_INIT_LOCK);
5710 ADD_INT(d, DB_INIT_LOG);
5711 ADD_INT(d, DB_INIT_MPOOL);
5712 ADD_INT(d, DB_INIT_TXN);
5713#if (DBVER >= 32)
5714 ADD_INT(d, DB_JOINENV);
5715#endif
5716
5717 ADD_INT(d, DB_RECOVER);
5718 ADD_INT(d, DB_RECOVER_FATAL);
5719 ADD_INT(d, DB_TXN_NOSYNC);
5720 ADD_INT(d, DB_USE_ENVIRON);
5721 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5722
5723 ADD_INT(d, DB_LOCKDOWN);
5724 ADD_INT(d, DB_PRIVATE);
5725 ADD_INT(d, DB_SYSTEM_MEM);
5726
5727 ADD_INT(d, DB_TXN_SYNC);
5728 ADD_INT(d, DB_TXN_NOWAIT);
5729
5730 ADD_INT(d, DB_EXCL);
5731 ADD_INT(d, DB_FCNTL_LOCKING);
5732 ADD_INT(d, DB_ODDFILESIZE);
5733 ADD_INT(d, DB_RDWRMASTER);
5734 ADD_INT(d, DB_RDONLY);
5735 ADD_INT(d, DB_TRUNCATE);
5736#if (DBVER >= 32)
5737 ADD_INT(d, DB_EXTENT);
5738 ADD_INT(d, DB_CDB_ALLDB);
5739 ADD_INT(d, DB_VERIFY);
5740#endif
5741 ADD_INT(d, DB_UPGRADE);
5742
5743 ADD_INT(d, DB_AGGRESSIVE);
5744 ADD_INT(d, DB_NOORDERCHK);
5745 ADD_INT(d, DB_ORDERCHKONLY);
5746 ADD_INT(d, DB_PR_PAGE);
5747#if ! (DBVER >= 33)
5748 ADD_INT(d, DB_VRFY_FLAGMASK);
5749 ADD_INT(d, DB_PR_HEADERS);
5750#endif
5751 ADD_INT(d, DB_PR_RECOVERYTEST);
5752 ADD_INT(d, DB_SALVAGE);
5753
5754 ADD_INT(d, DB_LOCK_NORUN);
5755 ADD_INT(d, DB_LOCK_DEFAULT);
5756 ADD_INT(d, DB_LOCK_OLDEST);
5757 ADD_INT(d, DB_LOCK_RANDOM);
5758 ADD_INT(d, DB_LOCK_YOUNGEST);
5759#if (DBVER >= 33)
5760 ADD_INT(d, DB_LOCK_MAXLOCKS);
5761 ADD_INT(d, DB_LOCK_MINLOCKS);
5762 ADD_INT(d, DB_LOCK_MINWRITE);
5763#endif
5764
5765
5766#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005767 /* docs say to use zero instead */
5768 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005769#else
5770 ADD_INT(d, DB_LOCK_CONFLICT);
5771#endif
5772
5773 ADD_INT(d, DB_LOCK_DUMP);
5774 ADD_INT(d, DB_LOCK_GET);
5775 ADD_INT(d, DB_LOCK_INHERIT);
5776 ADD_INT(d, DB_LOCK_PUT);
5777 ADD_INT(d, DB_LOCK_PUT_ALL);
5778 ADD_INT(d, DB_LOCK_PUT_OBJ);
5779
5780 ADD_INT(d, DB_LOCK_NG);
5781 ADD_INT(d, DB_LOCK_READ);
5782 ADD_INT(d, DB_LOCK_WRITE);
5783 ADD_INT(d, DB_LOCK_NOWAIT);
5784#if (DBVER >= 32)
5785 ADD_INT(d, DB_LOCK_WAIT);
5786#endif
5787 ADD_INT(d, DB_LOCK_IWRITE);
5788 ADD_INT(d, DB_LOCK_IREAD);
5789 ADD_INT(d, DB_LOCK_IWR);
5790#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005791#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005792 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005793#else
5794 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5795#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796 ADD_INT(d, DB_LOCK_WWRITE);
5797#endif
5798
5799 ADD_INT(d, DB_LOCK_RECORD);
5800 ADD_INT(d, DB_LOCK_UPGRADE);
5801#if (DBVER >= 32)
5802 ADD_INT(d, DB_LOCK_SWITCH);
5803#endif
5804#if (DBVER >= 33)
5805 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5806#endif
5807
5808 ADD_INT(d, DB_LOCK_NOWAIT);
5809 ADD_INT(d, DB_LOCK_RECORD);
5810 ADD_INT(d, DB_LOCK_UPGRADE);
5811
5812#if (DBVER >= 33)
5813 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005814#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005815 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005816#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005817 ADD_INT(d, DB_LSTAT_FREE);
5818 ADD_INT(d, DB_LSTAT_HELD);
5819#if (DBVER == 33)
5820 ADD_INT(d, DB_LSTAT_NOGRANT);
5821#endif
5822 ADD_INT(d, DB_LSTAT_PENDING);
5823 ADD_INT(d, DB_LSTAT_WAITING);
5824#endif
5825
5826 ADD_INT(d, DB_ARCH_ABS);
5827 ADD_INT(d, DB_ARCH_DATA);
5828 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005829#if (DBVER >= 42)
5830 ADD_INT(d, DB_ARCH_REMOVE);
5831#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005832
5833 ADD_INT(d, DB_BTREE);
5834 ADD_INT(d, DB_HASH);
5835 ADD_INT(d, DB_RECNO);
5836 ADD_INT(d, DB_QUEUE);
5837 ADD_INT(d, DB_UNKNOWN);
5838
5839 ADD_INT(d, DB_DUP);
5840 ADD_INT(d, DB_DUPSORT);
5841 ADD_INT(d, DB_RECNUM);
5842 ADD_INT(d, DB_RENUMBER);
5843 ADD_INT(d, DB_REVSPLITOFF);
5844 ADD_INT(d, DB_SNAPSHOT);
5845
5846 ADD_INT(d, DB_JOIN_NOSORT);
5847
5848 ADD_INT(d, DB_AFTER);
5849 ADD_INT(d, DB_APPEND);
5850 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005851#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005852 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005853#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005854#if (DBVER >= 41)
5855 _addIntToDict(d, "DB_CHECKPOINT", 0);
5856#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005858 ADD_INT(d, DB_CURLSN);
5859#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005860#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005861 ADD_INT(d, DB_COMMIT);
5862#endif
5863 ADD_INT(d, DB_CONSUME);
5864#if (DBVER >= 32)
5865 ADD_INT(d, DB_CONSUME_WAIT);
5866#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005867 ADD_INT(d, DB_CURRENT);
5868#if (DBVER >= 33)
5869 ADD_INT(d, DB_FAST_STAT);
5870#endif
5871 ADD_INT(d, DB_FIRST);
5872 ADD_INT(d, DB_FLUSH);
5873 ADD_INT(d, DB_GET_BOTH);
5874 ADD_INT(d, DB_GET_RECNO);
5875 ADD_INT(d, DB_JOIN_ITEM);
5876 ADD_INT(d, DB_KEYFIRST);
5877 ADD_INT(d, DB_KEYLAST);
5878 ADD_INT(d, DB_LAST);
5879 ADD_INT(d, DB_NEXT);
5880 ADD_INT(d, DB_NEXT_DUP);
5881 ADD_INT(d, DB_NEXT_NODUP);
5882 ADD_INT(d, DB_NODUPDATA);
5883 ADD_INT(d, DB_NOOVERWRITE);
5884 ADD_INT(d, DB_NOSYNC);
5885 ADD_INT(d, DB_POSITION);
5886 ADD_INT(d, DB_PREV);
5887 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005888#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005889 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005890#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005891 ADD_INT(d, DB_SET);
5892 ADD_INT(d, DB_SET_RANGE);
5893 ADD_INT(d, DB_SET_RECNO);
5894 ADD_INT(d, DB_WRITECURSOR);
5895
5896 ADD_INT(d, DB_OPFLAGS_MASK);
5897 ADD_INT(d, DB_RMW);
5898#if (DBVER >= 33)
5899 ADD_INT(d, DB_DIRTY_READ);
5900 ADD_INT(d, DB_MULTIPLE);
5901 ADD_INT(d, DB_MULTIPLE_KEY);
5902#endif
5903
Gregory P. Smith29602d22006-01-24 09:46:48 +00005904#if (DBVER >= 44)
5905 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5906 ADD_INT(d, DB_READ_COMMITTED);
5907#endif
5908
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005909#if (DBVER >= 33)
5910 ADD_INT(d, DB_DONOTINDEX);
5911#endif
5912
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005913#if (DBVER >= 41)
5914 _addIntToDict(d, "DB_INCOMPLETE", 0);
5915#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005916 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005917#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005918 ADD_INT(d, DB_KEYEMPTY);
5919 ADD_INT(d, DB_KEYEXIST);
5920 ADD_INT(d, DB_LOCK_DEADLOCK);
5921 ADD_INT(d, DB_LOCK_NOTGRANTED);
5922 ADD_INT(d, DB_NOSERVER);
5923 ADD_INT(d, DB_NOSERVER_HOME);
5924 ADD_INT(d, DB_NOSERVER_ID);
5925 ADD_INT(d, DB_NOTFOUND);
5926 ADD_INT(d, DB_OLD_VERSION);
5927 ADD_INT(d, DB_RUNRECOVERY);
5928 ADD_INT(d, DB_VERIFY_BAD);
5929#if (DBVER >= 33)
5930 ADD_INT(d, DB_PAGE_NOTFOUND);
5931 ADD_INT(d, DB_SECONDARY_BAD);
5932#endif
5933#if (DBVER >= 40)
5934 ADD_INT(d, DB_STAT_CLEAR);
5935 ADD_INT(d, DB_REGION_INIT);
5936 ADD_INT(d, DB_NOLOCKING);
5937 ADD_INT(d, DB_YIELDCPU);
5938 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5939 ADD_INT(d, DB_NOPANIC);
5940#endif
5941
Gregory P. Smith41631e82003-09-21 00:08:14 +00005942#if (DBVER >= 42)
5943 ADD_INT(d, DB_TIME_NOTGRANTED);
5944 ADD_INT(d, DB_TXN_NOT_DURABLE);
5945 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5946 ADD_INT(d, DB_LOG_AUTOREMOVE);
5947 ADD_INT(d, DB_DIRECT_LOG);
5948 ADD_INT(d, DB_DIRECT_DB);
5949 ADD_INT(d, DB_INIT_REP);
5950 ADD_INT(d, DB_ENCRYPT);
5951 ADD_INT(d, DB_CHKSUM);
5952#endif
5953
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005954#if (DBVER >= 43)
5955 ADD_INT(d, DB_LOG_INMEMORY);
5956 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005957 ADD_INT(d, DB_SEQ_DEC);
5958 ADD_INT(d, DB_SEQ_INC);
5959 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005960#endif
5961
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005962#if (DBVER >= 41)
5963 ADD_INT(d, DB_ENCRYPT_AES);
5964 ADD_INT(d, DB_AUTO_COMMIT);
5965#else
5966 /* allow berkeleydb 4.1 aware apps to run on older versions */
5967 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5968#endif
5969
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005970 ADD_INT(d, EINVAL);
5971 ADD_INT(d, EACCES);
5972 ADD_INT(d, ENOSPC);
5973 ADD_INT(d, ENOMEM);
5974 ADD_INT(d, EAGAIN);
5975 ADD_INT(d, EBUSY);
5976 ADD_INT(d, EEXIST);
5977 ADD_INT(d, ENOENT);
5978 ADD_INT(d, EPERM);
5979
Barry Warsaw1baa9822003-03-31 19:51:29 +00005980#if (DBVER >= 40)
5981 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5982 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5983#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005985 /* The exception name must be correct for pickled exception *
5986 * objects to unpickle properly. */
5987#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5988#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5989#else
5990#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5991#endif
5992
5993 /* All the rest of the exceptions derive only from DBError */
5994#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5995 PyDict_SetItemString(d, #name, name)
5996
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005997 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005998 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5999 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000
Gregory P. Smithe9477062005-06-04 06:46:59 +00006001 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6002 * from both DBError and KeyError, since the API only supports
6003 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006004 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006005 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6006 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 Py_file_input, d, d);
6008 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006009 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010 PyDict_DelItemString(d, "KeyError");
6011
6012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013#if !INCOMPLETE_IS_WARNING
6014 MAKE_EX(DBIncompleteError);
6015#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006016 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006017 MAKE_EX(DBKeyEmptyError);
6018 MAKE_EX(DBKeyExistError);
6019 MAKE_EX(DBLockDeadlockError);
6020 MAKE_EX(DBLockNotGrantedError);
6021 MAKE_EX(DBOldVersionError);
6022 MAKE_EX(DBRunRecoveryError);
6023 MAKE_EX(DBVerifyBadError);
6024 MAKE_EX(DBNoServerError);
6025 MAKE_EX(DBNoServerHomeError);
6026 MAKE_EX(DBNoServerIDError);
6027#if (DBVER >= 33)
6028 MAKE_EX(DBPageNotFoundError);
6029 MAKE_EX(DBSecondaryBadError);
6030#endif
6031
6032 MAKE_EX(DBInvalidArgError);
6033 MAKE_EX(DBAccessError);
6034 MAKE_EX(DBNoSpaceError);
6035 MAKE_EX(DBNoMemoryError);
6036 MAKE_EX(DBAgainError);
6037 MAKE_EX(DBBusyError);
6038 MAKE_EX(DBFileExistsError);
6039 MAKE_EX(DBNoSuchFileError);
6040 MAKE_EX(DBPermissionsError);
6041
6042#undef MAKE_EX
6043
6044 /* Check for errors */
6045 if (PyErr_Occurred()) {
6046 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006047 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048 }
6049}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006050
6051/* allow this module to be named _pybsddb so that it can be installed
6052 * and imported on top of python >= 2.3 that includes its own older
6053 * copy of the library named _bsddb without importing the old version. */
6054DL_EXPORT(void) init_pybsddb(void)
6055{
6056 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6057 init_bsddb();
6058}