blob: ef0c7f33d7e8e67927dad0019db887e8f2c1f005 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000101#define PY_BSDDB_VERSION "4.5.0"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000106typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298static PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
Neal Norwitz227b5332006-03-22 09:28:35 +0000301static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000548#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000559#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000603 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
Gregory P. Smithe9477062005-06-04 06:46:59 +0000706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000752
753/* The same, when the value is a time_t */
754static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
755{
756 PyObject* v;
757 /* if the value fits in regular int, use that. */
758#ifdef HAVE_LONG_LONG
759 if (sizeof(time_t) > sizeof(long))
760 v = PyLong_FromLongLong((PY_LONG_LONG) value);
761 else
762#endif
763 v = PyInt_FromLong((long) value);
764 if (!v || PyDict_SetItemString(dict, name, v))
765 PyErr_Clear();
766
767 Py_XDECREF(v);
768}
769
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000770#if (DBVER >= 43)
771/* add an db_seq_t to a dictionary using the given name as a key */
772static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
773{
774 PyObject* v = PyLong_FromLongLong(value);
775 if (!v || PyDict_SetItemString(dict, name, v))
776 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000778 Py_XDECREF(v);
779}
780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781
782
783
784/* --------------------------------------------------------------------- */
785/* Allocators and deallocators */
786
787static DBObject*
788newDBObject(DBEnvObject* arg, int flags)
789{
790 DBObject* self;
791 DB_ENV* db_env = NULL;
792 int err;
793
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 if (self == NULL)
796 return NULL;
797
798 self->haveStat = 0;
799 self->flags = 0;
800 self->setflags = 0;
801 self->myenvobj = NULL;
802#if (DBVER >= 33)
803 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000804 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805 self->primaryDBType = 0;
806#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000807#ifdef HAVE_WEAKREF
808 self->in_weakreflist = NULL;
809#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810
811 /* keep a reference to our python DBEnv object */
812 if (arg) {
813 Py_INCREF(arg);
814 self->myenvobj = arg;
815 db_env = arg->db_env;
816 }
817
818 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000819 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000820 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000821 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
822 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823
824 MYDB_BEGIN_ALLOW_THREADS;
825 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000826 if (self->db != NULL) {
827 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000829 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000831 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000833 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
834 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000835 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 if (makeDBError(err)) {
837 if (self->myenvobj) {
838 Py_DECREF(self->myenvobj);
839 self->myenvobj = NULL;
840 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000841 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 self = NULL;
843 }
844 return self;
845}
846
847
848static void
849DB_dealloc(DBObject* self)
850{
851 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000852 /* avoid closing a DB when its DBEnv has been closed out from under
853 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000854 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000855 (self->myenvobj && self->myenvobj->db_env))
856 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 MYDB_BEGIN_ALLOW_THREADS;
858 self->db->close(self->db, 0);
859 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000860#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861 } else {
862 PyErr_Warn(PyExc_RuntimeWarning,
863 "DB could not be closed in destructor: DBEnv already closed");
864#endif
865 }
866 self->db = NULL;
867 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000868#ifdef HAVE_WEAKREF
869 if (self->in_weakreflist != NULL) {
870 PyObject_ClearWeakRefs((PyObject *) self);
871 }
872#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000873 if (self->myenvobj) {
874 Py_DECREF(self->myenvobj);
875 self->myenvobj = NULL;
876 }
877#if (DBVER >= 33)
878 if (self->associateCallback != NULL) {
879 Py_DECREF(self->associateCallback);
880 self->associateCallback = NULL;
881 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000882 if (self->btCompareCallback != NULL) {
883 Py_DECREF(self->btCompareCallback);
884 self->btCompareCallback = NULL;
885 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000887 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888}
889
890
891static DBCursorObject*
892newDBCursorObject(DBC* dbc, DBObject* db)
893{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000894 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000895 if (self == NULL)
896 return NULL;
897
898 self->dbc = dbc;
899 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000900#ifdef HAVE_WEAKREF
901 self->in_weakreflist = NULL;
902#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 Py_INCREF(self->mydb);
904 return self;
905}
906
907
908static void
909DBCursor_dealloc(DBCursorObject* self)
910{
911 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000912
913#ifdef HAVE_WEAKREF
914 if (self->in_weakreflist != NULL) {
915 PyObject_ClearWeakRefs((PyObject *) self);
916 }
917#endif
918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919 if (self->dbc != NULL) {
920 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000921 /* If the underlying database has been closed, we don't
922 need to do anything. If the environment has been closed
923 we need to leak, as BerkeleyDB will crash trying to access
924 the environment. There was an exception when the
925 user closed the environment even though there still was
926 a database open. */
927 if (self->mydb->db && self->mydb->myenvobj &&
928 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000929 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 self->dbc = NULL;
931 MYDB_END_ALLOW_THREADS;
932 }
933 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935}
936
937
938static DBEnvObject*
939newDBEnvObject(int flags)
940{
941 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000942 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943 if (self == NULL)
944 return NULL;
945
946 self->closed = 1;
947 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000948 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
949 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000950#ifdef HAVE_WEAKREF
951 self->in_weakreflist = NULL;
952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953
954 MYDB_BEGIN_ALLOW_THREADS;
955 err = db_env_create(&self->db_env, flags);
956 MYDB_END_ALLOW_THREADS;
957 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000958 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000959 self = NULL;
960 }
961 else {
962 self->db_env->set_errcall(self->db_env, _db_errorCallback);
963 }
964 return self;
965}
966
967
968static void
969DBEnv_dealloc(DBEnvObject* self)
970{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000971#ifdef HAVE_WEAKREF
972 if (self->in_weakreflist != NULL) {
973 PyObject_ClearWeakRefs((PyObject *) self);
974 }
975#endif
976
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000977 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 MYDB_BEGIN_ALLOW_THREADS;
979 self->db_env->close(self->db_env, 0);
980 MYDB_END_ALLOW_THREADS;
981 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983}
984
985
986static DBTxnObject*
987newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
988{
989 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000990 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 if (self == NULL)
992 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000993 Py_INCREF(myenv);
994 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000995#ifdef HAVE_WEAKREF
996 self->in_weakreflist = NULL;
997#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000998
999 MYDB_BEGIN_ALLOW_THREADS;
1000#if (DBVER >= 40)
1001 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1002#else
1003 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1004#endif
1005 MYDB_END_ALLOW_THREADS;
1006 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001007 Py_DECREF(self->env);
1008 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 self = NULL;
1010 }
1011 return self;
1012}
1013
1014
1015static void
1016DBTxn_dealloc(DBTxnObject* self)
1017{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001018#ifdef HAVE_WEAKREF
1019 if (self->in_weakreflist != NULL) {
1020 PyObject_ClearWeakRefs((PyObject *) self);
1021 }
1022#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023
Gregory P. Smith31c50652004-06-28 01:20:40 +00001024#ifdef HAVE_WARNINGS
1025 if (self->txn) {
1026 /* it hasn't been finalized, abort it! */
1027 MYDB_BEGIN_ALLOW_THREADS;
1028#if (DBVER >= 40)
1029 self->txn->abort(self->txn);
1030#else
1031 txn_abort(self->txn);
1032#endif
1033 MYDB_END_ALLOW_THREADS;
1034 PyErr_Warn(PyExc_RuntimeWarning,
1035 "DBTxn aborted in destructor. No prior commit() or abort().");
1036 }
1037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001038
Neal Norwitz62a21122006-01-25 05:21:55 +00001039 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001041}
1042
1043
1044static DBLockObject*
1045newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1046 db_lockmode_t lock_mode, int flags)
1047{
1048 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001049 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001050 if (self == NULL)
1051 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001052#ifdef HAVE_WEAKREF
1053 self->in_weakreflist = NULL;
1054#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055
1056 MYDB_BEGIN_ALLOW_THREADS;
1057#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001058 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1059 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060#else
1061 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1062#endif
1063 MYDB_END_ALLOW_THREADS;
1064 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001065 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001066 self = NULL;
1067 }
1068
1069 return self;
1070}
1071
1072
1073static void
1074DBLock_dealloc(DBLockObject* self)
1075{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001076#ifdef HAVE_WEAKREF
1077 if (self->in_weakreflist != NULL) {
1078 PyObject_ClearWeakRefs((PyObject *) self);
1079 }
1080#endif
1081 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001082
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001083 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001084}
1085
1086
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001087#if (DBVER >= 43)
1088static DBSequenceObject*
1089newDBSequenceObject(DBObject* mydb, int flags)
1090{
1091 int err;
1092 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1093 if (self == NULL)
1094 return NULL;
1095 Py_INCREF(mydb);
1096 self->mydb = mydb;
1097#ifdef HAVE_WEAKREF
1098 self->in_weakreflist = NULL;
1099#endif
1100
1101
1102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108 self = NULL;
1109 }
1110
1111 return self;
1112}
1113
1114
1115static void
1116DBSequence_dealloc(DBSequenceObject* self)
1117{
1118#ifdef HAVE_WEAKREF
1119 if (self->in_weakreflist != NULL) {
1120 PyObject_ClearWeakRefs((PyObject *) self);
1121 }
1122#endif
1123
1124 Py_DECREF(self->mydb);
1125 PyObject_Del(self);
1126}
1127#endif
1128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001129/* --------------------------------------------------------------------- */
1130/* DB methods */
1131
1132static PyObject*
1133DB_append(DBObject* self, PyObject* args)
1134{
1135 PyObject* txnobj = NULL;
1136 PyObject* dataobj;
1137 db_recno_t recno;
1138 DBT key, data;
1139 DB_TXN *txn = NULL;
1140
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001141 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001142 return NULL;
1143
1144 CHECK_DB_NOT_CLOSED(self);
1145
1146 /* make a dummy key out of a recno */
1147 recno = 0;
1148 CLEAR_DBT(key);
1149 key.data = &recno;
1150 key.size = sizeof(recno);
1151 key.ulen = key.size;
1152 key.flags = DB_DBT_USERMEM;
1153
1154 if (!make_dbt(dataobj, &data)) return NULL;
1155 if (!checkTxnObj(txnobj, &txn)) return NULL;
1156
1157 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1158 return NULL;
1159
1160 return PyInt_FromLong(recno);
1161}
1162
1163
1164#if (DBVER >= 33)
1165
1166static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001167_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1168 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169{
1170 int retval = DB_DONOTINDEX;
1171 DBObject* secondaryDB = (DBObject*)db->app_private;
1172 PyObject* callback = secondaryDB->associateCallback;
1173 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001175 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176
1177
1178 if (callback != NULL) {
1179 MYDB_BEGIN_BLOCK_THREADS;
1180
Thomas Woutersb3153832006-03-08 01:47:19 +00001181 if (type == DB_RECNO || type == DB_QUEUE)
1182 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1183 priData->data, priData->size);
1184 else
1185 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1186 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001187 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001188 result = PyEval_CallObject(callback, args);
1189 }
1190 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001191 PyErr_Print();
1192 }
1193 else if (result == Py_None) {
1194 retval = DB_DONOTINDEX;
1195 }
1196 else if (PyInt_Check(result)) {
1197 retval = PyInt_AsLong(result);
1198 }
1199 else if (PyString_Check(result)) {
1200 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001201 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001202
1203 CLEAR_DBT(*secKey);
1204#if PYTHON_API_VERSION <= 1007
1205 /* 1.5 compatibility */
1206 size = PyString_Size(result);
1207 data = PyString_AsString(result);
1208#else
1209 PyString_AsStringAndSize(result, &data, &size);
1210#endif
1211 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1212 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001213 if (secKey->data) {
1214 memcpy(secKey->data, data, size);
1215 secKey->size = size;
1216 retval = 0;
1217 }
1218 else {
1219 PyErr_SetString(PyExc_MemoryError,
1220 "malloc failed in _db_associateCallback");
1221 PyErr_Print();
1222 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001223 }
1224 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225 PyErr_SetString(
1226 PyExc_TypeError,
1227 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228 PyErr_Print();
1229 }
1230
Thomas Woutersb3153832006-03-08 01:47:19 +00001231 Py_XDECREF(args);
1232 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233
1234 MYDB_END_BLOCK_THREADS;
1235 }
1236 return retval;
1237}
1238
1239
1240static PyObject*
1241DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1242{
1243 int err, flags=0;
1244 DBObject* secondaryDB;
1245 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246#if (DBVER >= 41)
1247 PyObject *txnobj = NULL;
1248 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001249 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001250 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001251#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001252 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001253#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001254
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001255#if (DBVER >= 41)
1256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1257 &secondaryDB, &callback, &flags,
1258 &txnobj)) {
1259#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001261 &secondaryDB, &callback, &flags)) {
1262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001263 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001264 }
1265
1266#if (DBVER >= 41)
1267 if (!checkTxnObj(txnobj, &txn)) return NULL;
1268#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001269
1270 CHECK_DB_NOT_CLOSED(self);
1271 if (!DBObject_Check(secondaryDB)) {
1272 makeTypeError("DB", (PyObject*)secondaryDB);
1273 return NULL;
1274 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001275 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 if (callback == Py_None) {
1277 callback = NULL;
1278 }
1279 else if (!PyCallable_Check(callback)) {
1280 makeTypeError("Callable", callback);
1281 return NULL;
1282 }
1283
1284 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001285 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001286 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001287 secondaryDB->associateCallback = callback;
1288 secondaryDB->primaryDBType = _DB_get_type(self);
1289
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001290 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1291 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1292 * The global interepreter lock is not initialized until the first
1293 * thread is created using thread.start_new_thread() or fork() is
1294 * called. that would cause the ALLOW_THREADS here to segfault due
1295 * to a null pointer reference if no threads or child processes
1296 * have been created. This works around that and is a no-op if
1297 * threads have already been initialized.
1298 * (see pybsddb-users mailing list post on 2002-08-07)
1299 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001300#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001301 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001302#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001304#if (DBVER >= 41)
1305 err = self->db->associate(self->db,
1306 txn,
1307 secondaryDB->db,
1308 _db_associateCallback,
1309 flags);
1310#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 err = self->db->associate(self->db,
1312 secondaryDB->db,
1313 _db_associateCallback,
1314 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001315#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 MYDB_END_ALLOW_THREADS;
1317
1318 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001319 Py_XDECREF(secondaryDB->associateCallback);
1320 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001321 secondaryDB->primaryDBType = 0;
1322 }
1323
1324 RETURN_IF_ERR();
1325 RETURN_NONE();
1326}
1327
1328
1329#endif
1330
1331
1332static PyObject*
1333DB_close(DBObject* self, PyObject* args)
1334{
1335 int err, flags=0;
1336 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1337 return NULL;
1338 if (self->db != NULL) {
1339 if (self->myenvobj)
1340 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342 self->db = NULL;
1343 RETURN_IF_ERR();
1344 }
1345 RETURN_NONE();
1346}
1347
1348
1349#if (DBVER >= 32)
1350static PyObject*
1351_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1352{
1353 int err, flags=0, type;
1354 PyObject* txnobj = NULL;
1355 PyObject* retval = NULL;
1356 DBT key, data;
1357 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001358 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001359
1360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1361 &txnobj, &flags))
1362 return NULL;
1363
1364 CHECK_DB_NOT_CLOSED(self);
1365 type = _DB_get_type(self);
1366 if (type == -1)
1367 return NULL;
1368 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 PyErr_SetString(PyExc_TypeError,
1370 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 return NULL;
1372 }
1373 if (!checkTxnObj(txnobj, &txn))
1374 return NULL;
1375
1376 CLEAR_DBT(key);
1377 CLEAR_DBT(data);
1378 if (CHECK_DBFLAG(self, DB_THREAD)) {
1379 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1380 data.flags = DB_DBT_MALLOC;
1381 key.flags = DB_DBT_MALLOC;
1382 }
1383
1384 MYDB_BEGIN_ALLOW_THREADS;
1385 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1386 MYDB_END_ALLOW_THREADS;
1387
Gregory P. Smithe9477062005-06-04 06:46:59 +00001388 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1389 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001390 err = 0;
1391 Py_INCREF(Py_None);
1392 retval = Py_None;
1393 }
1394 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001395 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1396 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001397 FREE_DBT(key);
1398 FREE_DBT(data);
1399 }
1400
1401 RETURN_IF_ERR();
1402 return retval;
1403}
1404
1405static PyObject*
1406DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1407{
1408 return _DB_consume(self, args, kwargs, DB_CONSUME);
1409}
1410
1411static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001412DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1413 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414{
1415 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1416}
1417#endif
1418
1419
1420
1421static PyObject*
1422DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1423{
1424 int err, flags=0;
1425 DBC* dbc;
1426 PyObject* txnobj = NULL;
1427 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001428 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1431 &txnobj, &flags))
1432 return NULL;
1433 CHECK_DB_NOT_CLOSED(self);
1434 if (!checkTxnObj(txnobj, &txn))
1435 return NULL;
1436
1437 MYDB_BEGIN_ALLOW_THREADS;
1438 err = self->db->cursor(self->db, txn, &dbc, flags);
1439 MYDB_END_ALLOW_THREADS;
1440 RETURN_IF_ERR();
1441 return (PyObject*) newDBCursorObject(dbc, self);
1442}
1443
1444
1445static PyObject*
1446DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1447{
1448 PyObject* txnobj = NULL;
1449 int flags = 0;
1450 PyObject* keyobj;
1451 DBT key;
1452 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001453 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454
1455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1456 &keyobj, &txnobj, &flags))
1457 return NULL;
1458 CHECK_DB_NOT_CLOSED(self);
1459 if (!make_key_dbt(self, keyobj, &key, NULL))
1460 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001461 if (!checkTxnObj(txnobj, &txn)) {
1462 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001463 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001464 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001466 if (-1 == _DB_delete(self, txn, &key, 0)) {
1467 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001468 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001469 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470
1471 FREE_DBT(key);
1472 RETURN_NONE();
1473}
1474
1475
1476static PyObject*
1477DB_fd(DBObject* self, PyObject* args)
1478{
1479 int err, the_fd;
1480
1481 if (!PyArg_ParseTuple(args,":fd"))
1482 return NULL;
1483 CHECK_DB_NOT_CLOSED(self);
1484
1485 MYDB_BEGIN_ALLOW_THREADS;
1486 err = self->db->fd(self->db, &the_fd);
1487 MYDB_END_ALLOW_THREADS;
1488 RETURN_IF_ERR();
1489 return PyInt_FromLong(the_fd);
1490}
1491
1492
1493static PyObject*
1494DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1495{
1496 int err, flags=0;
1497 PyObject* txnobj = NULL;
1498 PyObject* keyobj;
1499 PyObject* dfltobj = NULL;
1500 PyObject* retval = NULL;
1501 int dlen = -1;
1502 int doff = -1;
1503 DBT key, data;
1504 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001505 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001506 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001507
1508 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001509 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1510 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 return NULL;
1512
1513 CHECK_DB_NOT_CLOSED(self);
1514 if (!make_key_dbt(self, keyobj, &key, &flags))
1515 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001516 if (!checkTxnObj(txnobj, &txn)) {
1517 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001519 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001520
1521 CLEAR_DBT(data);
1522 if (CHECK_DBFLAG(self, DB_THREAD)) {
1523 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1524 data.flags = DB_DBT_MALLOC;
1525 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001526 if (!add_partial_dbt(&data, dlen, doff)) {
1527 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001529 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001530
1531 MYDB_BEGIN_ALLOW_THREADS;
1532 err = self->db->get(self->db, txn, &key, &data, flags);
1533 MYDB_END_ALLOW_THREADS;
1534
Gregory P. Smithe9477062005-06-04 06:46:59 +00001535 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536 err = 0;
1537 Py_INCREF(dfltobj);
1538 retval = dfltobj;
1539 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001540 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1541 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542 err = 0;
1543 Py_INCREF(Py_None);
1544 retval = Py_None;
1545 }
1546 else if (!err) {
1547 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001548 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1549 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550 else /* return just the data */
1551 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001552 FREE_DBT(data);
1553 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001554 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555
1556 RETURN_IF_ERR();
1557 return retval;
1558}
1559
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001560#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001561static PyObject*
1562DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1563{
1564 int err, flags=0;
1565 PyObject* txnobj = NULL;
1566 PyObject* keyobj;
1567 PyObject* dfltobj = NULL;
1568 PyObject* retval = NULL;
1569 int dlen = -1;
1570 int doff = -1;
1571 DBT key, pkey, data;
1572 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001573 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001574 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001575
1576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1577 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1578 &doff))
1579 return NULL;
1580
1581 CHECK_DB_NOT_CLOSED(self);
1582 if (!make_key_dbt(self, keyobj, &key, &flags))
1583 return NULL;
1584 if (!checkTxnObj(txnobj, &txn)) {
1585 FREE_DBT(key);
1586 return NULL;
1587 }
1588
1589 CLEAR_DBT(data);
1590 if (CHECK_DBFLAG(self, DB_THREAD)) {
1591 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1592 data.flags = DB_DBT_MALLOC;
1593 }
1594 if (!add_partial_dbt(&data, dlen, doff)) {
1595 FREE_DBT(key);
1596 return NULL;
1597 }
1598
1599 CLEAR_DBT(pkey);
1600 pkey.flags = DB_DBT_MALLOC;
1601
1602 MYDB_BEGIN_ALLOW_THREADS;
1603 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1604 MYDB_END_ALLOW_THREADS;
1605
Gregory P. Smithe9477062005-06-04 06:46:59 +00001606 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 err = 0;
1608 Py_INCREF(dfltobj);
1609 retval = dfltobj;
1610 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001611 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1612 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001613 err = 0;
1614 Py_INCREF(Py_None);
1615 retval = Py_None;
1616 }
1617 else if (!err) {
1618 PyObject *pkeyObj;
1619 PyObject *dataObj;
1620 dataObj = PyString_FromStringAndSize(data.data, data.size);
1621
1622 if (self->primaryDBType == DB_RECNO ||
1623 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001624 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001625 else
1626 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1627
1628 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1629 {
1630 PyObject *keyObj;
1631 int type = _DB_get_type(self);
1632 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001633 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001634 else
1635 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001636#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001637 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001638#else
1639 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1640#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001641 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001642 }
1643 else /* return just the pkey and data */
1644 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001645#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001646 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001647#else
1648 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1649#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001650 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001651 Py_DECREF(dataObj);
1652 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001653 FREE_DBT(pkey);
1654 FREE_DBT(data);
1655 }
1656 FREE_DBT(key);
1657
1658 RETURN_IF_ERR();
1659 return retval;
1660}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001661#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001662
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663
1664/* Return size of entry */
1665static PyObject*
1666DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1667{
1668 int err, flags=0;
1669 PyObject* txnobj = NULL;
1670 PyObject* keyobj;
1671 PyObject* retval = NULL;
1672 DBT key, data;
1673 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001674 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001675
1676 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1677 &keyobj, &txnobj))
1678 return NULL;
1679 CHECK_DB_NOT_CLOSED(self);
1680 if (!make_key_dbt(self, keyobj, &key, &flags))
1681 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001682 if (!checkTxnObj(txnobj, &txn)) {
1683 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001684 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001685 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 CLEAR_DBT(data);
1687
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001688 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1689 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 data.flags = DB_DBT_USERMEM;
1691 data.ulen = 0;
1692 MYDB_BEGIN_ALLOW_THREADS;
1693 err = self->db->get(self->db, txn, &key, &data, flags);
1694 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001695 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 retval = PyInt_FromLong((long)data.size);
1697 err = 0;
1698 }
1699
1700 FREE_DBT(key);
1701 FREE_DBT(data);
1702 RETURN_IF_ERR();
1703 return retval;
1704}
1705
1706
1707static PyObject*
1708DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1709{
1710 int err, flags=0;
1711 PyObject* txnobj = NULL;
1712 PyObject* keyobj;
1713 PyObject* dataobj;
1714 PyObject* retval = NULL;
1715 DBT key, data;
1716 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001717 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001718
1719
1720 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1721 &keyobj, &dataobj, &txnobj, &flags))
1722 return NULL;
1723
1724 CHECK_DB_NOT_CLOSED(self);
1725 if (!make_key_dbt(self, keyobj, &key, NULL))
1726 return NULL;
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001727 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001728 if ( !make_dbt(dataobj, &data) ||
1729 !checkTxnObj(txnobj, &txn) )
1730 {
1731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001734
1735 flags |= DB_GET_BOTH;
1736
1737 if (CHECK_DBFLAG(self, DB_THREAD)) {
1738 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1739 data.flags = DB_DBT_MALLOC;
1740 /* TODO: Is this flag needed? We're passing a data object that should
1741 match what's in the DB, so there should be no need to malloc.
1742 We run the risk of freeing something twice! Check this. */
1743 }
1744
1745 MYDB_BEGIN_ALLOW_THREADS;
1746 err = self->db->get(self->db, txn, &key, &data, flags);
1747 MYDB_END_ALLOW_THREADS;
1748
Gregory P. Smithe9477062005-06-04 06:46:59 +00001749 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1750 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001751 err = 0;
1752 Py_INCREF(Py_None);
1753 retval = Py_None;
1754 }
1755 else if (!err) {
1756 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1757 FREE_DBT(data); /* Only if retrieval was successful */
1758 }
1759
1760 FREE_DBT(key);
1761 RETURN_IF_ERR();
1762 return retval;
1763}
1764
1765
1766static PyObject*
1767DB_get_byteswapped(DBObject* self, PyObject* args)
1768{
1769#if (DBVER >= 33)
1770 int err = 0;
1771#endif
1772 int retval = -1;
1773
1774 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1775 return NULL;
1776 CHECK_DB_NOT_CLOSED(self);
1777
1778#if (DBVER >= 33)
1779 MYDB_BEGIN_ALLOW_THREADS;
1780 err = self->db->get_byteswapped(self->db, &retval);
1781 MYDB_END_ALLOW_THREADS;
1782 RETURN_IF_ERR();
1783#else
1784 MYDB_BEGIN_ALLOW_THREADS;
1785 retval = self->db->get_byteswapped(self->db);
1786 MYDB_END_ALLOW_THREADS;
1787#endif
1788 return PyInt_FromLong(retval);
1789}
1790
1791
1792static PyObject*
1793DB_get_type(DBObject* self, PyObject* args)
1794{
1795 int type;
1796
1797 if (!PyArg_ParseTuple(args,":get_type"))
1798 return NULL;
1799 CHECK_DB_NOT_CLOSED(self);
1800
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802 if (type == -1)
1803 return NULL;
1804 return PyInt_FromLong(type);
1805}
1806
1807
1808static PyObject*
1809DB_join(DBObject* self, PyObject* args)
1810{
1811 int err, flags=0;
1812 int length, x;
1813 PyObject* cursorsObj;
1814 DBC** cursors;
1815 DBC* dbc;
1816
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001817 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1818 return NULL;
1819
1820 CHECK_DB_NOT_CLOSED(self);
1821
1822 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001823 PyErr_SetString(PyExc_TypeError,
1824 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 return NULL;
1826 }
1827
1828 length = PyObject_Length(cursorsObj);
1829 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001830 if (!cursors) {
1831 PyErr_NoMemory();
1832 return NULL;
1833 }
1834
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001835 cursors[length] = NULL;
1836 for (x=0; x<length; x++) {
1837 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001838 if (item == NULL) {
1839 free(cursors);
1840 return NULL;
1841 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001843 PyErr_SetString(PyExc_TypeError,
1844 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 free(cursors);
1846 return NULL;
1847 }
1848 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001849 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850 }
1851
1852 MYDB_BEGIN_ALLOW_THREADS;
1853 err = self->db->join(self->db, cursors, &dbc, flags);
1854 MYDB_END_ALLOW_THREADS;
1855 free(cursors);
1856 RETURN_IF_ERR();
1857
Gregory P. Smith7441e652003-11-03 21:35:31 +00001858 /* FIXME: this is a buggy interface. The returned cursor
1859 contains internal references to the passed in cursors
1860 but does not hold python references to them or prevent
1861 them from being closed prematurely. This can cause
1862 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863 return (PyObject*) newDBCursorObject(dbc, self);
1864}
1865
1866
1867static PyObject*
1868DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1869{
1870 int err, flags=0;
1871 PyObject* txnobj = NULL;
1872 PyObject* keyobj;
1873 DBT key;
1874 DB_TXN *txn = NULL;
1875 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001876 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001877
1878 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1879 &keyobj, &txnobj, &flags))
1880 return NULL;
1881 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001882 if (!make_dbt(keyobj, &key))
1883 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001884 return NULL;
1885 if (!checkTxnObj(txnobj, &txn))
1886 return NULL;
1887
1888 MYDB_BEGIN_ALLOW_THREADS;
1889 err = self->db->key_range(self->db, txn, &key, &range, flags);
1890 MYDB_END_ALLOW_THREADS;
1891
1892 RETURN_IF_ERR();
1893 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1894}
1895
1896
1897static PyObject*
1898DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1899{
1900 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1901 char* filename = NULL;
1902 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001903#if (DBVER >= 41)
1904 PyObject *txnobj = NULL;
1905 DB_TXN *txn = NULL;
1906 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001907 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001908 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1909 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001910 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001911 "filename", "dbtype", "flags", "mode", "txn", NULL};
1912#else
1913 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001914 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001915 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1916 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001917 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918 "filename", "dbtype", "flags", "mode", NULL};
1919#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001920
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001921#if (DBVER >= 41)
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1923 &filename, &dbname, &type, &flags, &mode,
1924 &txnobj))
1925#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001927 &filename, &dbname, &type, &flags,
1928 &mode))
1929#endif
1930 {
1931 PyErr_Clear();
1932 type = DB_UNKNOWN; flags = 0; mode = 0660;
1933 filename = NULL; dbname = NULL;
1934#if (DBVER >= 41)
1935 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1936 kwnames_basic,
1937 &filename, &type, &flags, &mode,
1938 &txnobj))
1939 return NULL;
1940#else
1941 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1942 kwnames_basic,
1943 &filename, &type, &flags, &mode))
1944 return NULL;
1945#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946 }
1947
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001948#if (DBVER >= 41)
1949 if (!checkTxnObj(txnobj, &txn)) return NULL;
1950#endif
1951
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001953 PyObject *t = Py_BuildValue("(is)", 0,
1954 "Cannot call open() twice for DB object");
1955 PyErr_SetObject(DBError, t);
1956 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 return NULL;
1958 }
1959
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001960#if 0 && (DBVER >= 41)
1961 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1962 && (self->myenvobj->flags & DB_INIT_TXN))
1963 {
1964 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1965 * explicitly passed) but we are in a transaction ready environment:
1966 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1967 * to work on BerkeleyDB 4.1 without needing to modify their
1968 * DBEnv or DB open calls.
1969 * TODO make this behaviour of the library configurable.
1970 */
1971 flags |= DB_AUTO_COMMIT;
1972 }
1973#endif
1974
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001975 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001976#if (DBVER >= 41)
1977 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1978#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001980#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001981 MYDB_END_ALLOW_THREADS;
1982 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001983 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984 self->db = NULL;
1985 return NULL;
1986 }
1987
1988 self->flags = flags;
1989 RETURN_NONE();
1990}
1991
1992
1993static PyObject*
1994DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1995{
1996 int flags=0;
1997 PyObject* txnobj = NULL;
1998 int dlen = -1;
1999 int doff = -1;
2000 PyObject* keyobj, *dataobj, *retval;
2001 DBT key, data;
2002 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002003 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002004 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002005
2006 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2007 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2008 return NULL;
2009
2010 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002011 if (!make_key_dbt(self, keyobj, &key, NULL))
2012 return NULL;
2013 if ( !make_dbt(dataobj, &data) ||
2014 !add_partial_dbt(&data, dlen, doff) ||
2015 !checkTxnObj(txnobj, &txn) )
2016 {
2017 FREE_DBT(key);
2018 return NULL;
2019 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002020
2021 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2022 FREE_DBT(key);
2023 return NULL;
2024 }
2025
2026 if (flags & DB_APPEND)
2027 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2028 else {
2029 retval = Py_None;
2030 Py_INCREF(retval);
2031 }
2032 FREE_DBT(key);
2033 return retval;
2034}
2035
2036
2037
2038static PyObject*
2039DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2040{
2041 char* filename;
2042 char* database = NULL;
2043 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002044 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002045
2046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2047 &filename, &database, &flags))
2048 return NULL;
2049 CHECK_DB_NOT_CLOSED(self);
2050
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002052 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 RETURN_IF_ERR();
2054 RETURN_NONE();
2055}
2056
2057
2058
2059static PyObject*
2060DB_rename(DBObject* self, PyObject* args)
2061{
2062 char* filename;
2063 char* database;
2064 char* newname;
2065 int err, flags=0;
2066
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002067 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2068 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002069 return NULL;
2070 CHECK_DB_NOT_CLOSED(self);
2071
2072 MYDB_BEGIN_ALLOW_THREADS;
2073 err = self->db->rename(self->db, filename, database, newname, flags);
2074 MYDB_END_ALLOW_THREADS;
2075 RETURN_IF_ERR();
2076 RETURN_NONE();
2077}
2078
2079
2080static PyObject*
2081DB_set_bt_minkey(DBObject* self, PyObject* args)
2082{
2083 int err, minkey;
2084
2085 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2086 return NULL;
2087 CHECK_DB_NOT_CLOSED(self);
2088
2089 MYDB_BEGIN_ALLOW_THREADS;
2090 err = self->db->set_bt_minkey(self->db, minkey);
2091 MYDB_END_ALLOW_THREADS;
2092 RETURN_IF_ERR();
2093 RETURN_NONE();
2094}
2095
Neal Norwitz84562352005-10-20 04:30:15 +00002096#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002097static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002098_default_cmp(const DBT *leftKey,
2099 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100{
2101 int res;
2102 int lsize = leftKey->size, rsize = rightKey->size;
2103
Georg Brandlef1701f2006-03-07 14:57:48 +00002104 res = memcmp(leftKey->data, rightKey->data,
2105 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002106
2107 if (res == 0) {
2108 if (lsize < rsize) {
2109 res = -1;
2110 }
2111 else if (lsize > rsize) {
2112 res = 1;
2113 }
2114 }
2115 return res;
2116}
2117
2118static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002119_db_compareCallback(DB* db,
2120 const DBT *leftKey,
2121 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122{
2123 int res = 0;
2124 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002125 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002127
2128 if (self == NULL || self->btCompareCallback == NULL) {
2129 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 PyErr_SetString(PyExc_TypeError,
2131 (self == 0
2132 ? "DB_bt_compare db is NULL."
2133 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002135 PyErr_Print();
2136 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002138 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002139 MYDB_BEGIN_BLOCK_THREADS;
2140
Thomas Woutersb3153832006-03-08 01:47:19 +00002141 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2142 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002143 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002144 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002146 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002147 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 PyErr_Print();
2151 res = _default_cmp(leftKey, rightKey);
2152 } else if (PyInt_Check(result)) {
2153 res = PyInt_AsLong(result);
2154 } else {
2155 PyErr_SetString(PyExc_TypeError,
2156 "DB_bt_compare callback MUST return an int.");
2157 /* we're in a callback within the DB code, we can't raise */
2158 PyErr_Print();
2159 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160 }
2161
Thomas Woutersb3153832006-03-08 01:47:19 +00002162 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002164
2165 MYDB_END_BLOCK_THREADS;
2166 }
2167 return res;
2168}
2169
2170static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002171DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002172{
2173 int err;
2174 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002175 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002176
Georg Brandlef1701f2006-03-07 14:57:48 +00002177 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178 return NULL;
2179
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 if (!PyCallable_Check(comparator)) {
2183 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184 return NULL;
2185 }
2186
2187 /*
2188 * Perform a test call of the comparator function with two empty
2189 * string objects here. verify that it returns an int (0).
2190 * err if not.
2191 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002192 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002193 result = PyEval_CallObject(comparator, tuple);
2194 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002195 if (result == NULL)
2196 return NULL;
2197 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002198 PyErr_SetString(PyExc_TypeError,
2199 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002201 } else if (PyInt_AsLong(result) != 0) {
2202 PyErr_SetString(PyExc_TypeError,
2203 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204 return NULL;
2205 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002206 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
2208 /* We don't accept multiple set_bt_compare operations, in order to
2209 * simplify the code. This would have no real use, as one cannot
2210 * change the function once the db is opened anyway */
2211 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002212 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213 return NULL;
2214 }
2215
Georg Brandlef1701f2006-03-07 14:57:48 +00002216 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002217 self->btCompareCallback = comparator;
2218
2219 /* This is to workaround a problem with un-initialized threads (see
2220 comment in DB_associate) */
2221#ifdef WITH_THREAD
2222 PyEval_InitThreads();
2223#endif
2224
Thomas Woutersb3153832006-03-08 01:47:19 +00002225 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002226
2227 if (err) {
2228 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002229 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002230 self->btCompareCallback = NULL;
2231 }
2232
Georg Brandlef1701f2006-03-07 14:57:48 +00002233 RETURN_IF_ERR();
2234 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002235}
Neal Norwitz84562352005-10-20 04:30:15 +00002236#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002237
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002238
2239static PyObject*
2240DB_set_cachesize(DBObject* self, PyObject* args)
2241{
2242 int err;
2243 int gbytes = 0, bytes = 0, ncache = 0;
2244
2245 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2246 &gbytes,&bytes,&ncache))
2247 return NULL;
2248 CHECK_DB_NOT_CLOSED(self);
2249
2250 MYDB_BEGIN_ALLOW_THREADS;
2251 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2252 MYDB_END_ALLOW_THREADS;
2253 RETURN_IF_ERR();
2254 RETURN_NONE();
2255}
2256
2257
2258static PyObject*
2259DB_set_flags(DBObject* self, PyObject* args)
2260{
2261 int err, flags;
2262
2263 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2266
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_flags(self->db, flags);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271
2272 self->setflags |= flags;
2273 RETURN_NONE();
2274}
2275
2276
2277static PyObject*
2278DB_set_h_ffactor(DBObject* self, PyObject* args)
2279{
2280 int err, ffactor;
2281
2282 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2283 return NULL;
2284 CHECK_DB_NOT_CLOSED(self);
2285
2286 MYDB_BEGIN_ALLOW_THREADS;
2287 err = self->db->set_h_ffactor(self->db, ffactor);
2288 MYDB_END_ALLOW_THREADS;
2289 RETURN_IF_ERR();
2290 RETURN_NONE();
2291}
2292
2293
2294static PyObject*
2295DB_set_h_nelem(DBObject* self, PyObject* args)
2296{
2297 int err, nelem;
2298
2299 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2300 return NULL;
2301 CHECK_DB_NOT_CLOSED(self);
2302
2303 MYDB_BEGIN_ALLOW_THREADS;
2304 err = self->db->set_h_nelem(self->db, nelem);
2305 MYDB_END_ALLOW_THREADS;
2306 RETURN_IF_ERR();
2307 RETURN_NONE();
2308}
2309
2310
2311static PyObject*
2312DB_set_lorder(DBObject* self, PyObject* args)
2313{
2314 int err, lorder;
2315
2316 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319
2320 MYDB_BEGIN_ALLOW_THREADS;
2321 err = self->db->set_lorder(self->db, lorder);
2322 MYDB_END_ALLOW_THREADS;
2323 RETURN_IF_ERR();
2324 RETURN_NONE();
2325}
2326
2327
2328static PyObject*
2329DB_set_pagesize(DBObject* self, PyObject* args)
2330{
2331 int err, pagesize;
2332
2333 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2334 return NULL;
2335 CHECK_DB_NOT_CLOSED(self);
2336
2337 MYDB_BEGIN_ALLOW_THREADS;
2338 err = self->db->set_pagesize(self->db, pagesize);
2339 MYDB_END_ALLOW_THREADS;
2340 RETURN_IF_ERR();
2341 RETURN_NONE();
2342}
2343
2344
2345static PyObject*
2346DB_set_re_delim(DBObject* self, PyObject* args)
2347{
2348 int err;
2349 char delim;
2350
2351 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2352 PyErr_Clear();
2353 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2354 return NULL;
2355 }
2356
2357 CHECK_DB_NOT_CLOSED(self);
2358
2359 MYDB_BEGIN_ALLOW_THREADS;
2360 err = self->db->set_re_delim(self->db, delim);
2361 MYDB_END_ALLOW_THREADS;
2362 RETURN_IF_ERR();
2363 RETURN_NONE();
2364}
2365
2366static PyObject*
2367DB_set_re_len(DBObject* self, PyObject* args)
2368{
2369 int err, len;
2370
2371 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2372 return NULL;
2373 CHECK_DB_NOT_CLOSED(self);
2374
2375 MYDB_BEGIN_ALLOW_THREADS;
2376 err = self->db->set_re_len(self->db, len);
2377 MYDB_END_ALLOW_THREADS;
2378 RETURN_IF_ERR();
2379 RETURN_NONE();
2380}
2381
2382
2383static PyObject*
2384DB_set_re_pad(DBObject* self, PyObject* args)
2385{
2386 int err;
2387 char pad;
2388
2389 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2390 PyErr_Clear();
2391 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2392 return NULL;
2393 }
2394 CHECK_DB_NOT_CLOSED(self);
2395
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_re_pad(self->db, pad);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2400 RETURN_NONE();
2401}
2402
2403
2404static PyObject*
2405DB_set_re_source(DBObject* self, PyObject* args)
2406{
2407 int err;
2408 char *re_source;
2409
2410 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2413
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_re_source(self->db, re_source);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2419}
2420
2421
2422#if (DBVER >= 32)
2423static PyObject*
2424DB_set_q_extentsize(DBObject* self, PyObject* args)
2425{
2426 int err;
2427 int extentsize;
2428
2429 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2430 return NULL;
2431 CHECK_DB_NOT_CLOSED(self);
2432
2433 MYDB_BEGIN_ALLOW_THREADS;
2434 err = self->db->set_q_extentsize(self->db, extentsize);
2435 MYDB_END_ALLOW_THREADS;
2436 RETURN_IF_ERR();
2437 RETURN_NONE();
2438}
2439#endif
2440
2441static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002442DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002443{
2444 int err, flags = 0, type;
2445 void* sp;
2446 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002447#if (DBVER >= 43)
2448 PyObject* txnobj = NULL;
2449 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002450 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002452 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002453#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002454
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002455#if (DBVER >= 43)
2456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2457 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002458 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002459 if (!checkTxnObj(txnobj, &txn))
2460 return NULL;
2461#else
2462 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2463 return NULL;
2464#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002465 CHECK_DB_NOT_CLOSED(self);
2466
2467 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002468#if (DBVER >= 43)
2469 err = self->db->stat(self->db, txn, &sp, flags);
2470#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 err = self->db->stat(self->db, &sp, flags);
2472#else
2473 err = self->db->stat(self->db, &sp, NULL, flags);
2474#endif
2475 MYDB_END_ALLOW_THREADS;
2476 RETURN_IF_ERR();
2477
2478 self->haveStat = 1;
2479
2480 /* Turn the stat structure into a dictionary */
2481 type = _DB_get_type(self);
2482 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2483 free(sp);
2484 return NULL;
2485 }
2486
2487#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2488#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2489#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2490
2491 switch (type) {
2492 case DB_HASH:
2493 MAKE_HASH_ENTRY(magic);
2494 MAKE_HASH_ENTRY(version);
2495 MAKE_HASH_ENTRY(nkeys);
2496 MAKE_HASH_ENTRY(ndata);
2497 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002498#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002499 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002500#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002501 MAKE_HASH_ENTRY(ffactor);
2502 MAKE_HASH_ENTRY(buckets);
2503 MAKE_HASH_ENTRY(free);
2504 MAKE_HASH_ENTRY(bfree);
2505 MAKE_HASH_ENTRY(bigpages);
2506 MAKE_HASH_ENTRY(big_bfree);
2507 MAKE_HASH_ENTRY(overflows);
2508 MAKE_HASH_ENTRY(ovfl_free);
2509 MAKE_HASH_ENTRY(dup);
2510 MAKE_HASH_ENTRY(dup_free);
2511 break;
2512
2513 case DB_BTREE:
2514 case DB_RECNO:
2515 MAKE_BT_ENTRY(magic);
2516 MAKE_BT_ENTRY(version);
2517 MAKE_BT_ENTRY(nkeys);
2518 MAKE_BT_ENTRY(ndata);
2519 MAKE_BT_ENTRY(pagesize);
2520 MAKE_BT_ENTRY(minkey);
2521 MAKE_BT_ENTRY(re_len);
2522 MAKE_BT_ENTRY(re_pad);
2523 MAKE_BT_ENTRY(levels);
2524 MAKE_BT_ENTRY(int_pg);
2525 MAKE_BT_ENTRY(leaf_pg);
2526 MAKE_BT_ENTRY(dup_pg);
2527 MAKE_BT_ENTRY(over_pg);
2528 MAKE_BT_ENTRY(free);
2529 MAKE_BT_ENTRY(int_pgfree);
2530 MAKE_BT_ENTRY(leaf_pgfree);
2531 MAKE_BT_ENTRY(dup_pgfree);
2532 MAKE_BT_ENTRY(over_pgfree);
2533 break;
2534
2535 case DB_QUEUE:
2536 MAKE_QUEUE_ENTRY(magic);
2537 MAKE_QUEUE_ENTRY(version);
2538 MAKE_QUEUE_ENTRY(nkeys);
2539 MAKE_QUEUE_ENTRY(ndata);
2540 MAKE_QUEUE_ENTRY(pagesize);
2541 MAKE_QUEUE_ENTRY(pages);
2542 MAKE_QUEUE_ENTRY(re_len);
2543 MAKE_QUEUE_ENTRY(re_pad);
2544 MAKE_QUEUE_ENTRY(pgfree);
2545#if (DBVER == 31)
2546 MAKE_QUEUE_ENTRY(start);
2547#endif
2548 MAKE_QUEUE_ENTRY(first_recno);
2549 MAKE_QUEUE_ENTRY(cur_recno);
2550 break;
2551
2552 default:
2553 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2554 Py_DECREF(d);
2555 d = NULL;
2556 }
2557
2558#undef MAKE_HASH_ENTRY
2559#undef MAKE_BT_ENTRY
2560#undef MAKE_QUEUE_ENTRY
2561
2562 free(sp);
2563 return d;
2564}
2565
2566static PyObject*
2567DB_sync(DBObject* self, PyObject* args)
2568{
2569 int err;
2570 int flags = 0;
2571
2572 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2573 return NULL;
2574 CHECK_DB_NOT_CLOSED(self);
2575
2576 MYDB_BEGIN_ALLOW_THREADS;
2577 err = self->db->sync(self->db, flags);
2578 MYDB_END_ALLOW_THREADS;
2579 RETURN_IF_ERR();
2580 RETURN_NONE();
2581}
2582
2583
2584#if (DBVER >= 33)
2585static PyObject*
2586DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2587{
2588 int err, flags=0;
2589 u_int32_t count=0;
2590 PyObject* txnobj = NULL;
2591 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002592 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002593
2594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2595 &txnobj, &flags))
2596 return NULL;
2597 CHECK_DB_NOT_CLOSED(self);
2598 if (!checkTxnObj(txnobj, &txn))
2599 return NULL;
2600
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->truncate(self->db, txn, &count, flags);
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605 return PyInt_FromLong(count);
2606}
2607#endif
2608
2609
2610static PyObject*
2611DB_upgrade(DBObject* self, PyObject* args)
2612{
2613 int err, flags=0;
2614 char *filename;
2615
2616 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2617 return NULL;
2618 CHECK_DB_NOT_CLOSED(self);
2619
2620 MYDB_BEGIN_ALLOW_THREADS;
2621 err = self->db->upgrade(self->db, filename, flags);
2622 MYDB_END_ALLOW_THREADS;
2623 RETURN_IF_ERR();
2624 RETURN_NONE();
2625}
2626
2627
2628static PyObject*
2629DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2630{
2631 int err, flags=0;
2632 char* fileName;
2633 char* dbName=NULL;
2634 char* outFileName=NULL;
2635 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002636 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002637 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002638
2639 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2640 &fileName, &dbName, &outFileName, &flags))
2641 return NULL;
2642
2643 CHECK_DB_NOT_CLOSED(self);
2644 if (outFileName)
2645 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002646 /* XXX(nnorwitz): it should probably be an exception if outFile
2647 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002648
2649 MYDB_BEGIN_ALLOW_THREADS;
2650 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2651 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002652 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002653 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002654
2655 /* DB.verify acts as a DB handle destructor (like close); this was
2656 * documented in BerkeleyDB 4.2 but had the undocumented effect
2657 * of not being safe in prior versions while still requiring an explicit
2658 * DB.close call afterwards. Lets call close for the user to emulate
2659 * the safe 4.2 behaviour. */
2660#if (DBVER <= 41)
2661 self->db->close(self->db, 0);
2662#endif
2663 self->db = NULL;
2664
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002665 RETURN_IF_ERR();
2666 RETURN_NONE();
2667}
2668
2669
2670static PyObject*
2671DB_set_get_returns_none(DBObject* self, PyObject* args)
2672{
2673 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002674 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002675
2676 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2677 return NULL;
2678 CHECK_DB_NOT_CLOSED(self);
2679
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002680 if (self->moduleFlags.getReturnsNone)
2681 ++oldValue;
2682 if (self->moduleFlags.cursorSetReturnsNone)
2683 ++oldValue;
2684 self->moduleFlags.getReturnsNone = (flags >= 1);
2685 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686 return PyInt_FromLong(oldValue);
2687}
2688
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002689#if (DBVER >= 41)
2690static PyObject*
2691DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2692{
2693 int err;
2694 u_int32_t flags=0;
2695 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002696 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002697
2698 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2699 &passwd, &flags)) {
2700 return NULL;
2701 }
2702
2703 MYDB_BEGIN_ALLOW_THREADS;
2704 err = self->db->set_encrypt(self->db, passwd, flags);
2705 MYDB_END_ALLOW_THREADS;
2706
2707 RETURN_IF_ERR();
2708 RETURN_NONE();
2709}
2710#endif /* DBVER >= 41 */
2711
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002712
2713/*-------------------------------------------------------------- */
2714/* Mapping and Dictionary-like access routines */
2715
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002716Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717{
2718 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002719 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720 int flags = 0;
2721 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002722 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723
2724 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002725 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2726 PyErr_SetObject(DBError, t);
2727 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002728 return -1;
2729 }
2730
2731 if (self->haveStat) { /* Has the stat function been called recently? If
2732 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002733 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 }
2735
2736 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002737redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002738#if (DBVER >= 43)
2739 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2740#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002741 err = self->db->stat(self->db, &sp, flags);
2742#else
2743 err = self->db->stat(self->db, &sp, NULL, flags);
2744#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002745
2746 /* All the stat structures have matching fields upto the ndata field,
2747 so we can use any of them for the type cast */
2748 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2749
2750 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2751 * redo a full stat to make sure.
2752 * Fixes SF python bug 1493322, pybsddb bug 1184012
2753 */
2754 if (size == 0 && (flags & DB_FAST_STAT)) {
2755 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002756 if (!err)
2757 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002758 goto redo_stat_for_length;
2759 }
2760
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002761 MYDB_END_ALLOW_THREADS;
2762
2763 if (err)
2764 return -1;
2765
2766 self->haveStat = 1;
2767
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002768 free(sp);
2769 return size;
2770}
2771
2772
2773PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2774{
2775 int err;
2776 PyObject* retval;
2777 DBT key;
2778 DBT data;
2779
2780 CHECK_DB_NOT_CLOSED(self);
2781 if (!make_key_dbt(self, keyobj, &key, NULL))
2782 return NULL;
2783
2784 CLEAR_DBT(data);
2785 if (CHECK_DBFLAG(self, DB_THREAD)) {
2786 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2787 data.flags = DB_DBT_MALLOC;
2788 }
2789 MYDB_BEGIN_ALLOW_THREADS;
2790 err = self->db->get(self->db, NULL, &key, &data, 0);
2791 MYDB_END_ALLOW_THREADS;
2792 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2793 PyErr_SetObject(PyExc_KeyError, keyobj);
2794 retval = NULL;
2795 }
2796 else if (makeDBError(err)) {
2797 retval = NULL;
2798 }
2799 else {
2800 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2801 FREE_DBT(data);
2802 }
2803
2804 FREE_DBT(key);
2805 return retval;
2806}
2807
2808
2809static int
2810DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2811{
2812 DBT key, data;
2813 int retval;
2814 int flags = 0;
2815
2816 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002817 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2818 PyErr_SetObject(DBError, t);
2819 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002820 return -1;
2821 }
2822
2823 if (!make_key_dbt(self, keyobj, &key, NULL))
2824 return -1;
2825
2826 if (dataobj != NULL) {
2827 if (!make_dbt(dataobj, &data))
2828 retval = -1;
2829 else {
2830 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002831 /* dictionaries shouldn't have duplicate keys */
2832 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002833 retval = _DB_put(self, NULL, &key, &data, flags);
2834
2835 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002836 /* try deleting any old record that matches and then PUT it
2837 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 _DB_delete(self, NULL, &key, 0);
2839 PyErr_Clear();
2840 retval = _DB_put(self, NULL, &key, &data, flags);
2841 }
2842 }
2843 }
2844 else {
2845 /* dataobj == NULL, so delete the key */
2846 retval = _DB_delete(self, NULL, &key, 0);
2847 }
2848 FREE_DBT(key);
2849 return retval;
2850}
2851
2852
2853static PyObject*
2854DB_has_key(DBObject* self, PyObject* args)
2855{
2856 int err;
2857 PyObject* keyobj;
2858 DBT key, data;
2859 PyObject* txnobj = NULL;
2860 DB_TXN *txn = NULL;
2861
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002862 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002863 return NULL;
2864 CHECK_DB_NOT_CLOSED(self);
2865 if (!make_key_dbt(self, keyobj, &key, NULL))
2866 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002867 if (!checkTxnObj(txnobj, &txn)) {
2868 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002870 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002871
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002872 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873 it has a record but can't allocate a buffer for the data. This saves
2874 having to deal with data we won't be using.
2875 */
2876 CLEAR_DBT(data);
2877 data.flags = DB_DBT_USERMEM;
2878
2879 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002880 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002881 MYDB_END_ALLOW_THREADS;
2882 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002883
2884 if (err == DB_BUFFER_SMALL || err == 0) {
2885 return PyInt_FromLong(1);
2886 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2887 return PyInt_FromLong(0);
2888 }
2889
2890 makeDBError(err);
2891 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002892}
2893
2894
2895#define _KEYS_LIST 1
2896#define _VALUES_LIST 2
2897#define _ITEMS_LIST 3
2898
2899static PyObject*
2900_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2901{
2902 int err, dbtype;
2903 DBT key;
2904 DBT data;
2905 DBC *cursor;
2906 PyObject* list;
2907 PyObject* item = NULL;
2908
2909 CHECK_DB_NOT_CLOSED(self);
2910 CLEAR_DBT(key);
2911 CLEAR_DBT(data);
2912
2913 dbtype = _DB_get_type(self);
2914 if (dbtype == -1)
2915 return NULL;
2916
2917 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002918 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002920
2921 /* get a cursor */
2922 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002923 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002925 if (makeDBError(err)) {
2926 Py_DECREF(list);
2927 return NULL;
2928 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929
2930 if (CHECK_DBFLAG(self, DB_THREAD)) {
2931 key.flags = DB_DBT_REALLOC;
2932 data.flags = DB_DBT_REALLOC;
2933 }
2934
2935 while (1) { /* use the cursor to traverse the DB, collecting items */
2936 MYDB_BEGIN_ALLOW_THREADS;
2937 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2938 MYDB_END_ALLOW_THREADS;
2939
2940 if (err) {
2941 /* for any error, break out of the loop */
2942 break;
2943 }
2944
2945 switch (type) {
2946 case _KEYS_LIST:
2947 switch(dbtype) {
2948 case DB_BTREE:
2949 case DB_HASH:
2950 default:
2951 item = PyString_FromStringAndSize((char*)key.data, key.size);
2952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
2955 item = PyInt_FromLong(*((db_recno_t*)key.data));
2956 break;
2957 }
2958 break;
2959
2960 case _VALUES_LIST:
2961 item = PyString_FromStringAndSize((char*)data.data, data.size);
2962 break;
2963
2964 case _ITEMS_LIST:
2965 switch(dbtype) {
2966 case DB_BTREE:
2967 case DB_HASH:
2968 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002969 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2970 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971 break;
2972 case DB_RECNO:
2973 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002974 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2975 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 break;
2977 }
2978 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002979 default:
2980 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2981 item = NULL;
2982 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983 }
2984 if (item == NULL) {
2985 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986 list = NULL;
2987 goto done;
2988 }
2989 PyList_Append(list, item);
2990 Py_DECREF(item);
2991 }
2992
Gregory P. Smithe9477062005-06-04 06:46:59 +00002993 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2994 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002995 Py_DECREF(list);
2996 list = NULL;
2997 }
2998
2999 done:
3000 FREE_DBT(key);
3001 FREE_DBT(data);
3002 MYDB_BEGIN_ALLOW_THREADS;
3003 cursor->c_close(cursor);
3004 MYDB_END_ALLOW_THREADS;
3005 return list;
3006}
3007
3008
3009static PyObject*
3010DB_keys(DBObject* self, PyObject* args)
3011{
3012 PyObject* txnobj = NULL;
3013 DB_TXN *txn = NULL;
3014
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003015 if (!PyArg_UnpackTuple(args, "keys", 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, _KEYS_LIST);
3020}
3021
3022
3023static PyObject*
3024DB_items(DBObject* self, PyObject* args)
3025{
3026 PyObject* txnobj = NULL;
3027 DB_TXN *txn = NULL;
3028
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003029 if (!PyArg_UnpackTuple(args, "items", 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, _ITEMS_LIST);
3034}
3035
3036
3037static PyObject*
3038DB_values(DBObject* self, PyObject* args)
3039{
3040 PyObject* txnobj = NULL;
3041 DB_TXN *txn = NULL;
3042
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003043 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 return NULL;
3045 if (!checkTxnObj(txnobj, &txn))
3046 return NULL;
3047 return _DB_make_list(self, txn, _VALUES_LIST);
3048}
3049
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050/* --------------------------------------------------------------------- */
3051/* DBCursor methods */
3052
3053
3054static PyObject*
3055DBC_close(DBCursorObject* self, PyObject* args)
3056{
3057 int err = 0;
3058
3059 if (!PyArg_ParseTuple(args, ":close"))
3060 return NULL;
3061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062 if (self->dbc != NULL) {
3063 MYDB_BEGIN_ALLOW_THREADS;
3064 err = self->dbc->c_close(self->dbc);
3065 self->dbc = NULL;
3066 MYDB_END_ALLOW_THREADS;
3067 }
3068 RETURN_IF_ERR();
3069 RETURN_NONE();
3070}
3071
3072
3073static PyObject*
3074DBC_count(DBCursorObject* self, PyObject* args)
3075{
3076 int err = 0;
3077 db_recno_t count;
3078 int flags = 0;
3079
3080 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3081 return NULL;
3082
3083 CHECK_CURSOR_NOT_CLOSED(self);
3084
3085 MYDB_BEGIN_ALLOW_THREADS;
3086 err = self->dbc->c_count(self->dbc, &count, flags);
3087 MYDB_END_ALLOW_THREADS;
3088 RETURN_IF_ERR();
3089
3090 return PyInt_FromLong(count);
3091}
3092
3093
3094static PyObject*
3095DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3096{
3097 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3098}
3099
3100
3101static PyObject*
3102DBC_delete(DBCursorObject* self, PyObject* args)
3103{
3104 int err, flags=0;
3105
3106 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3107 return NULL;
3108
3109 CHECK_CURSOR_NOT_CLOSED(self);
3110
3111 MYDB_BEGIN_ALLOW_THREADS;
3112 err = self->dbc->c_del(self->dbc, flags);
3113 MYDB_END_ALLOW_THREADS;
3114 RETURN_IF_ERR();
3115
3116 self->mydb->haveStat = 0;
3117 RETURN_NONE();
3118}
3119
3120
3121static PyObject*
3122DBC_dup(DBCursorObject* self, PyObject* args)
3123{
3124 int err, flags =0;
3125 DBC* dbc = NULL;
3126
3127 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3128 return NULL;
3129
3130 CHECK_CURSOR_NOT_CLOSED(self);
3131
3132 MYDB_BEGIN_ALLOW_THREADS;
3133 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3134 MYDB_END_ALLOW_THREADS;
3135 RETURN_IF_ERR();
3136
3137 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3138}
3139
3140static PyObject*
3141DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3142{
3143 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3144}
3145
3146
3147static PyObject*
3148DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3149{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003150 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 PyObject* keyobj = NULL;
3152 PyObject* dataobj = NULL;
3153 PyObject* retval = NULL;
3154 int dlen = -1;
3155 int doff = -1;
3156 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003157 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003158 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003159
3160 CLEAR_DBT(key);
3161 CLEAR_DBT(data);
3162 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003163 &flags, &dlen, &doff))
3164 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003166 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3167 &kwnames[1],
3168 &keyobj, &flags, &dlen, &doff))
3169 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003171 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3172 kwnames, &keyobj, &dataobj,
3173 &flags, &dlen, &doff))
3174 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003175 return NULL;
3176 }
3177 }
3178 }
3179
3180 CHECK_CURSOR_NOT_CLOSED(self);
3181
3182 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3183 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003184 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3185 (!add_partial_dbt(&data, dlen, doff)) )
3186 {
3187 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003189 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190
3191 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3192 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003193 if (!(key.flags & DB_DBT_REALLOC)) {
3194 key.flags |= DB_DBT_MALLOC;
3195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 }
3197
3198 MYDB_BEGIN_ALLOW_THREADS;
3199 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3200 MYDB_END_ALLOW_THREADS;
3201
Gregory P. Smithe9477062005-06-04 06:46:59 +00003202 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3203 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003204 Py_INCREF(Py_None);
3205 retval = Py_None;
3206 }
3207 else if (makeDBError(err)) {
3208 retval = NULL;
3209 }
3210 else {
3211 switch (_DB_get_type(self->mydb)) {
3212 case -1:
3213 retval = NULL;
3214 break;
3215 case DB_BTREE:
3216 case DB_HASH:
3217 default:
3218 retval = Py_BuildValue("s#s#", key.data, key.size,
3219 data.data, data.size);
3220 break;
3221 case DB_RECNO:
3222 case DB_QUEUE:
3223 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3224 data.data, data.size);
3225 break;
3226 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003227 FREE_DBT(data);
3228 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003229 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003230 return retval;
3231}
3232
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003233#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003234static PyObject*
3235DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3236{
3237 int err, flags=0;
3238 PyObject* keyobj = NULL;
3239 PyObject* dataobj = NULL;
3240 PyObject* retval = NULL;
3241 int dlen = -1;
3242 int doff = -1;
3243 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003244 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3245 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003246
3247 CLEAR_DBT(key);
3248 CLEAR_DBT(data);
3249 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3250 &flags, &dlen, &doff))
3251 {
3252 PyErr_Clear();
3253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003254 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003255 &keyobj, &flags, &dlen, &doff))
3256 {
3257 PyErr_Clear();
3258 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3259 kwnames, &keyobj, &dataobj,
3260 &flags, &dlen, &doff))
3261 {
3262 return NULL;
3263 }
3264 }
3265 }
3266
3267 CHECK_CURSOR_NOT_CLOSED(self);
3268
3269 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3270 return NULL;
3271 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3272 (!add_partial_dbt(&data, dlen, doff)) ) {
3273 FREE_DBT(key);
3274 return NULL;
3275 }
3276
3277 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3278 data.flags = DB_DBT_MALLOC;
3279 if (!(key.flags & DB_DBT_REALLOC)) {
3280 key.flags |= DB_DBT_MALLOC;
3281 }
3282 }
3283
3284 CLEAR_DBT(pkey);
3285 pkey.flags = DB_DBT_MALLOC;
3286
3287 MYDB_BEGIN_ALLOW_THREADS;
3288 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3289 MYDB_END_ALLOW_THREADS;
3290
Gregory P. Smithe9477062005-06-04 06:46:59 +00003291 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3292 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003293 Py_INCREF(Py_None);
3294 retval = Py_None;
3295 }
3296 else if (makeDBError(err)) {
3297 retval = NULL;
3298 }
3299 else {
3300 PyObject *pkeyObj;
3301 PyObject *dataObj;
3302 dataObj = PyString_FromStringAndSize(data.data, data.size);
3303
3304 if (self->mydb->primaryDBType == DB_RECNO ||
3305 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003306 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307 else
3308 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3309
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003310 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 {
3312 PyObject *keyObj;
3313 int type = _DB_get_type(self->mydb);
3314 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003315 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003316 else
3317 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003318#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003319 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003320#else
3321 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3322#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003323 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324 FREE_DBT(key);
3325 }
3326 else /* return just the pkey and data */
3327 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003328#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003329 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003330#else
3331 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3332#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003333 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003334 Py_DECREF(dataObj);
3335 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003336 FREE_DBT(pkey);
3337 FREE_DBT(data);
3338 }
3339 /* the only time REALLOC should be set is if we used an integer
3340 * key that make_key_dbt malloc'd for us. always free these. */
3341 if (key.flags & DB_DBT_REALLOC) {
3342 FREE_DBT(key);
3343 }
3344 return retval;
3345}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003346#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003347
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348
3349static PyObject*
3350DBC_get_recno(DBCursorObject* self, PyObject* args)
3351{
3352 int err;
3353 db_recno_t recno;
3354 DBT key;
3355 DBT data;
3356
3357 if (!PyArg_ParseTuple(args, ":get_recno"))
3358 return NULL;
3359
3360 CHECK_CURSOR_NOT_CLOSED(self);
3361
3362 CLEAR_DBT(key);
3363 CLEAR_DBT(data);
3364 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3365 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3366 data.flags = DB_DBT_MALLOC;
3367 key.flags = DB_DBT_MALLOC;
3368 }
3369
3370 MYDB_BEGIN_ALLOW_THREADS;
3371 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3372 MYDB_END_ALLOW_THREADS;
3373 RETURN_IF_ERR();
3374
3375 recno = *((db_recno_t*)data.data);
3376 FREE_DBT(key);
3377 FREE_DBT(data);
3378 return PyInt_FromLong(recno);
3379}
3380
3381
3382static PyObject*
3383DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3384{
3385 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3386}
3387
3388
3389static PyObject*
3390DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3391{
3392 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3393}
3394
3395
3396static PyObject*
3397DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3398{
3399 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3400}
3401
3402
3403static PyObject*
3404DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3405{
3406 int err, flags = 0;
3407 PyObject* keyobj, *dataobj;
3408 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003409 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003410 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411 int dlen = -1;
3412 int doff = -1;
3413
3414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3415 &keyobj, &dataobj, &flags, &dlen, &doff))
3416 return NULL;
3417
3418 CHECK_CURSOR_NOT_CLOSED(self);
3419
3420 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3421 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003422 if (!make_dbt(dataobj, &data) ||
3423 !add_partial_dbt(&data, dlen, doff) )
3424 {
3425 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003426 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003427 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428
3429 MYDB_BEGIN_ALLOW_THREADS;
3430 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3431 MYDB_END_ALLOW_THREADS;
3432 FREE_DBT(key);
3433 RETURN_IF_ERR();
3434 self->mydb->haveStat = 0;
3435 RETURN_NONE();
3436}
3437
3438
3439static PyObject*
3440DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3441{
3442 int err, flags = 0;
3443 DBT key, data;
3444 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003445 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446 int dlen = -1;
3447 int doff = -1;
3448
3449 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3450 &keyobj, &flags, &dlen, &doff))
3451 return NULL;
3452
3453 CHECK_CURSOR_NOT_CLOSED(self);
3454
3455 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3456 return NULL;
3457
3458 CLEAR_DBT(data);
3459 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3460 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3461 data.flags = DB_DBT_MALLOC;
3462 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003463 if (!add_partial_dbt(&data, dlen, doff)) {
3464 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003466 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467
3468 MYDB_BEGIN_ALLOW_THREADS;
3469 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3470 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003471 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3472 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003473 Py_INCREF(Py_None);
3474 retval = Py_None;
3475 }
3476 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477 retval = NULL;
3478 }
3479 else {
3480 switch (_DB_get_type(self->mydb)) {
3481 case -1:
3482 retval = NULL;
3483 break;
3484 case DB_BTREE:
3485 case DB_HASH:
3486 default:
3487 retval = Py_BuildValue("s#s#", key.data, key.size,
3488 data.data, data.size);
3489 break;
3490 case DB_RECNO:
3491 case DB_QUEUE:
3492 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3493 data.data, data.size);
3494 break;
3495 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003496 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003497 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003499 /* the only time REALLOC should be set is if we used an integer
3500 * key that make_key_dbt malloc'd for us. always free these. */
3501 if (key.flags & DB_DBT_REALLOC) {
3502 FREE_DBT(key);
3503 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003504
3505 return retval;
3506}
3507
3508
3509static PyObject*
3510DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3511{
3512 int err, flags = 0;
3513 DBT key, data;
3514 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003515 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 int dlen = -1;
3517 int doff = -1;
3518
3519 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3520 &keyobj, &flags, &dlen, &doff))
3521 return NULL;
3522
3523 CHECK_CURSOR_NOT_CLOSED(self);
3524
3525 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3526 return NULL;
3527
3528 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003529 if (!add_partial_dbt(&data, dlen, doff)) {
3530 FREE_DBT(key);
3531 return NULL;
3532 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3534 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003535 data.flags |= DB_DBT_MALLOC;
3536 /* only BTREE databases will return anything in the key */
3537 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3538 key.flags |= DB_DBT_MALLOC;
3539 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3543 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003544 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3545 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003546 Py_INCREF(Py_None);
3547 retval = Py_None;
3548 }
3549 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550 retval = NULL;
3551 }
3552 else {
3553 switch (_DB_get_type(self->mydb)) {
3554 case -1:
3555 retval = NULL;
3556 break;
3557 case DB_BTREE:
3558 case DB_HASH:
3559 default:
3560 retval = Py_BuildValue("s#s#", key.data, key.size,
3561 data.data, data.size);
3562 break;
3563 case DB_RECNO:
3564 case DB_QUEUE:
3565 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3566 data.data, data.size);
3567 break;
3568 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003569 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570 FREE_DBT(data);
3571 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003573 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003574 if (key.flags & DB_DBT_REALLOC) {
3575 FREE_DBT(key);
3576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577
3578 return retval;
3579}
3580
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003582_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3583 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003585 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003587 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588
Gregory P. Smith7441e652003-11-03 21:35:31 +00003589 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3591 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003592 if (!make_dbt(dataobj, &data)) {
3593 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003595 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596
3597 MYDB_BEGIN_ALLOW_THREADS;
3598 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3599 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003600 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003601 Py_INCREF(Py_None);
3602 retval = Py_None;
3603 }
3604 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003605 retval = NULL;
3606 }
3607 else {
3608 switch (_DB_get_type(self->mydb)) {
3609 case -1:
3610 retval = NULL;
3611 break;
3612 case DB_BTREE:
3613 case DB_HASH:
3614 default:
3615 retval = Py_BuildValue("s#s#", key.data, key.size,
3616 data.data, data.size);
3617 break;
3618 case DB_RECNO:
3619 case DB_QUEUE:
3620 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3621 data.data, data.size);
3622 break;
3623 }
3624 }
3625
3626 FREE_DBT(key);
3627 return retval;
3628}
3629
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003630static PyObject*
3631DBC_get_both(DBCursorObject* self, PyObject* args)
3632{
3633 int flags=0;
3634 PyObject *keyobj, *dataobj;
3635
3636 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3637 return NULL;
3638
Gregory P. Smith7441e652003-11-03 21:35:31 +00003639 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003640 CHECK_CURSOR_NOT_CLOSED(self);
3641
3642 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3643 self->mydb->moduleFlags.getReturnsNone);
3644}
3645
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003646/* Return size of entry */
3647static PyObject*
3648DBC_get_current_size(DBCursorObject* self, PyObject* args)
3649{
3650 int err, flags=DB_CURRENT;
3651 PyObject* retval = NULL;
3652 DBT key, data;
3653
3654 if (!PyArg_ParseTuple(args, ":get_current_size"))
3655 return NULL;
3656 CHECK_CURSOR_NOT_CLOSED(self);
3657 CLEAR_DBT(key);
3658 CLEAR_DBT(data);
3659
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003660 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003661 getting the record size. */
3662 data.flags = DB_DBT_USERMEM;
3663 data.ulen = 0;
3664 MYDB_BEGIN_ALLOW_THREADS;
3665 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3666 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003667 if (err == DB_BUFFER_SMALL || !err) {
3668 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003669 retval = PyInt_FromLong((long)data.size);
3670 err = 0;
3671 }
3672
3673 FREE_DBT(key);
3674 FREE_DBT(data);
3675 RETURN_IF_ERR();
3676 return retval;
3677}
3678
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003679static PyObject*
3680DBC_set_both(DBCursorObject* self, PyObject* args)
3681{
3682 int flags=0;
3683 PyObject *keyobj, *dataobj;
3684
3685 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3686 return NULL;
3687
Gregory P. Smith7441e652003-11-03 21:35:31 +00003688 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003689 CHECK_CURSOR_NOT_CLOSED(self);
3690
3691 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3692 self->mydb->moduleFlags.cursorSetReturnsNone);
3693}
3694
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003695
3696static PyObject*
3697DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3698{
3699 int err, irecno, flags=0;
3700 db_recno_t recno;
3701 DBT key, data;
3702 PyObject* retval;
3703 int dlen = -1;
3704 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003705 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003706
3707 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3708 &irecno, &flags, &dlen, &doff))
3709 return NULL;
3710
3711 CHECK_CURSOR_NOT_CLOSED(self);
3712
3713 CLEAR_DBT(key);
3714 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003715 /* use allocated space so DB will be able to realloc room for the real
3716 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717 key.data = malloc(sizeof(db_recno_t));
3718 if (key.data == NULL) {
3719 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3720 return NULL;
3721 }
3722 key.size = sizeof(db_recno_t);
3723 key.ulen = key.size;
3724 memcpy(key.data, &recno, sizeof(db_recno_t));
3725 key.flags = DB_DBT_REALLOC;
3726
3727 CLEAR_DBT(data);
3728 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3729 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3730 data.flags = DB_DBT_MALLOC;
3731 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003732 if (!add_partial_dbt(&data, dlen, doff)) {
3733 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003735 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736
3737 MYDB_BEGIN_ALLOW_THREADS;
3738 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3739 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003740 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3741 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003742 Py_INCREF(Py_None);
3743 retval = Py_None;
3744 }
3745 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003746 retval = NULL;
3747 }
3748 else { /* Can only be used for BTrees, so no need to return int key */
3749 retval = Py_BuildValue("s#s#", key.data, key.size,
3750 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003751 FREE_DBT(data);
3752 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003753 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754
3755 return retval;
3756}
3757
3758
3759static PyObject*
3760DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3761{
3762 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3763}
3764
3765
3766static PyObject*
3767DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3768{
3769 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3770}
3771
3772
3773static PyObject*
3774DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3775{
3776 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3777}
3778
3779
3780static PyObject*
3781DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3782{
3783 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3784}
3785
3786
3787static PyObject*
3788DBC_join_item(DBCursorObject* self, PyObject* args)
3789{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003790 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791 DBT key, data;
3792 PyObject* retval;
3793
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003794 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003795 return NULL;
3796
3797 CHECK_CURSOR_NOT_CLOSED(self);
3798
3799 CLEAR_DBT(key);
3800 CLEAR_DBT(data);
3801 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3802 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3803 key.flags = DB_DBT_MALLOC;
3804 }
3805
3806 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003807 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003808 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003809 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3810 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003811 Py_INCREF(Py_None);
3812 retval = Py_None;
3813 }
3814 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815 retval = NULL;
3816 }
3817 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003818 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003819 FREE_DBT(key);
3820 }
3821
3822 return retval;
3823}
3824
3825
3826
3827/* --------------------------------------------------------------------- */
3828/* DBEnv methods */
3829
3830
3831static PyObject*
3832DBEnv_close(DBEnvObject* self, PyObject* args)
3833{
3834 int err, flags = 0;
3835
3836 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3837 return NULL;
3838 if (!self->closed) { /* Don't close more than once */
3839 MYDB_BEGIN_ALLOW_THREADS;
3840 err = self->db_env->close(self->db_env, flags);
3841 MYDB_END_ALLOW_THREADS;
3842 /* after calling DBEnv->close, regardless of error, this DBEnv
3843 * may not be accessed again (BerkeleyDB docs). */
3844 self->closed = 1;
3845 self->db_env = NULL;
3846 RETURN_IF_ERR();
3847 }
3848 RETURN_NONE();
3849}
3850
3851
3852static PyObject*
3853DBEnv_open(DBEnvObject* self, PyObject* args)
3854{
3855 int err, flags=0, mode=0660;
3856 char *db_home;
3857
3858 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3859 return NULL;
3860
3861 CHECK_ENV_NOT_CLOSED(self);
3862
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->open(self->db_env, db_home, flags, mode);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 self->closed = 0;
3868 self->flags = flags;
3869 RETURN_NONE();
3870}
3871
3872
3873static PyObject*
3874DBEnv_remove(DBEnvObject* self, PyObject* args)
3875{
3876 int err, flags=0;
3877 char *db_home;
3878
3879 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3880 return NULL;
3881 CHECK_ENV_NOT_CLOSED(self);
3882 MYDB_BEGIN_ALLOW_THREADS;
3883 err = self->db_env->remove(self->db_env, db_home, flags);
3884 MYDB_END_ALLOW_THREADS;
3885 RETURN_IF_ERR();
3886 RETURN_NONE();
3887}
3888
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003889#if (DBVER >= 41)
3890static PyObject*
3891DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3892{
3893 int err;
3894 u_int32_t flags=0;
3895 char *file = NULL;
3896 char *database = NULL;
3897 PyObject *txnobj = NULL;
3898 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003899 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003900 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003901
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003903 &file, &database, &txnobj, &flags)) {
3904 return NULL;
3905 }
3906 if (!checkTxnObj(txnobj, &txn)) {
3907 return NULL;
3908 }
3909 CHECK_ENV_NOT_CLOSED(self);
3910 MYDB_BEGIN_ALLOW_THREADS;
3911 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3912 MYDB_END_ALLOW_THREADS;
3913 RETURN_IF_ERR();
3914 RETURN_NONE();
3915}
3916
3917static PyObject*
3918DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3919{
3920 int err;
3921 u_int32_t flags=0;
3922 char *file = NULL;
3923 char *database = NULL;
3924 char *newname = NULL;
3925 PyObject *txnobj = NULL;
3926 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003927 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003928 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003929
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003931 &file, &database, &newname, &txnobj, &flags)) {
3932 return NULL;
3933 }
3934 if (!checkTxnObj(txnobj, &txn)) {
3935 return NULL;
3936 }
3937 CHECK_ENV_NOT_CLOSED(self);
3938 MYDB_BEGIN_ALLOW_THREADS;
3939 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3940 flags);
3941 MYDB_END_ALLOW_THREADS;
3942 RETURN_IF_ERR();
3943 RETURN_NONE();
3944}
3945
3946static PyObject*
3947DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3948{
3949 int err;
3950 u_int32_t flags=0;
3951 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003952 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003953
3954 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3955 &passwd, &flags)) {
3956 return NULL;
3957 }
3958
3959 MYDB_BEGIN_ALLOW_THREADS;
3960 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3961 MYDB_END_ALLOW_THREADS;
3962
3963 RETURN_IF_ERR();
3964 RETURN_NONE();
3965}
3966#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003967
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003968#if (DBVER >= 40)
3969static PyObject*
3970DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3971{
3972 int err;
3973 u_int32_t flags=0;
3974 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003975 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003976
3977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3978 &timeout, &flags)) {
3979 return NULL;
3980 }
3981
3982 MYDB_BEGIN_ALLOW_THREADS;
3983 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3984 MYDB_END_ALLOW_THREADS;
3985
3986 RETURN_IF_ERR();
3987 RETURN_NONE();
3988}
3989#endif /* DBVER >= 40 */
3990
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003992DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3993{
3994 int err;
3995 long shm_key = 0;
3996
3997 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3998 return NULL;
3999 CHECK_ENV_NOT_CLOSED(self);
4000
4001 err = self->db_env->set_shm_key(self->db_env, shm_key);
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004007DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4008{
4009 int err, gbytes=0, bytes=0, ncache=0;
4010
4011 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4012 &gbytes, &bytes, &ncache))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4015
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4021}
4022
4023
4024#if (DBVER >= 32)
4025static PyObject*
4026DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4027{
4028 int err, flags=0, onoff=0;
4029
4030 if (!PyArg_ParseTuple(args, "ii:set_flags",
4031 &flags, &onoff))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4034
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_flags(self->db_env, flags, onoff);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4040}
4041#endif
4042
4043
4044static PyObject*
4045DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4046{
4047 int err;
4048 char *dir;
4049
4050 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_data_dir(self->db_env, dir);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4064{
4065 int err, lg_bsize;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
4079static PyObject*
4080DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4081{
4082 int err;
4083 char *dir;
4084
4085 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4086 return NULL;
4087 CHECK_ENV_NOT_CLOSED(self);
4088
4089 MYDB_BEGIN_ALLOW_THREADS;
4090 err = self->db_env->set_lg_dir(self->db_env, dir);
4091 MYDB_END_ALLOW_THREADS;
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
4095
4096static PyObject*
4097DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4098{
4099 int err, lg_max;
4100
4101 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4102 return NULL;
4103 CHECK_ENV_NOT_CLOSED(self);
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_lg_max(self->db_env, lg_max);
4107 MYDB_END_ALLOW_THREADS;
4108 RETURN_IF_ERR();
4109 RETURN_NONE();
4110}
4111
4112
Neal Norwitz84562352005-10-20 04:30:15 +00004113#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004115DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4116{
4117 int err, lg_max;
4118
4119 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
Neal Norwitz84562352005-10-20 04:30:15 +00004129#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004130
4131
4132static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004133DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4134{
4135 int err, lk_detect;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004149#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004150static PyObject*
4151DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4152{
4153 int err, max;
4154
4155 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lk_max(self->db_env, max);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4164}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004166
4167
4168#if (DBVER >= 32)
4169
4170static PyObject*
4171DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4172{
4173 int err, max;
4174
4175 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4176 return NULL;
4177 CHECK_ENV_NOT_CLOSED(self);
4178
4179 MYDB_BEGIN_ALLOW_THREADS;
4180 err = self->db_env->set_lk_max_locks(self->db_env, max);
4181 MYDB_END_ALLOW_THREADS;
4182 RETURN_IF_ERR();
4183 RETURN_NONE();
4184}
4185
4186
4187static PyObject*
4188DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4189{
4190 int err, max;
4191
4192 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4193 return NULL;
4194 CHECK_ENV_NOT_CLOSED(self);
4195
4196 MYDB_BEGIN_ALLOW_THREADS;
4197 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4198 MYDB_END_ALLOW_THREADS;
4199 RETURN_IF_ERR();
4200 RETURN_NONE();
4201}
4202
4203
4204static PyObject*
4205DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4206{
4207 int err, max;
4208
4209 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_lk_max_objects(self->db_env, max);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
4220#endif
4221
4222
4223static PyObject*
4224DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4225{
4226 int err, mp_mmapsize;
4227
4228 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4229 return NULL;
4230 CHECK_ENV_NOT_CLOSED(self);
4231
4232 MYDB_BEGIN_ALLOW_THREADS;
4233 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4234 MYDB_END_ALLOW_THREADS;
4235 RETURN_IF_ERR();
4236 RETURN_NONE();
4237}
4238
4239
4240static PyObject*
4241DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4242{
4243 int err;
4244 char *dir;
4245
4246 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4247 return NULL;
4248 CHECK_ENV_NOT_CLOSED(self);
4249
4250 MYDB_BEGIN_ALLOW_THREADS;
4251 err = self->db_env->set_tmp_dir(self->db_env, dir);
4252 MYDB_END_ALLOW_THREADS;
4253 RETURN_IF_ERR();
4254 RETURN_NONE();
4255}
4256
4257
4258static PyObject*
4259DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4260{
4261 int flags = 0;
4262 PyObject* txnobj = NULL;
4263 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004264 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004265
4266 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4267 &txnobj, &flags))
4268 return NULL;
4269
4270 if (!checkTxnObj(txnobj, &txn))
4271 return NULL;
4272 CHECK_ENV_NOT_CLOSED(self);
4273
4274 return (PyObject*)newDBTxnObject(self, txn, flags);
4275}
4276
4277
4278static PyObject*
4279DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4280{
4281 int err, kbyte=0, min=0, flags=0;
4282
4283 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4284 return NULL;
4285 CHECK_ENV_NOT_CLOSED(self);
4286
4287 MYDB_BEGIN_ALLOW_THREADS;
4288#if (DBVER >= 40)
4289 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4290#else
4291 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4292#endif
4293 MYDB_END_ALLOW_THREADS;
4294 RETURN_IF_ERR();
4295 RETURN_NONE();
4296}
4297
4298
4299static PyObject*
4300DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4301{
4302 int err, max;
4303
4304 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4305 return NULL;
4306 CHECK_ENV_NOT_CLOSED(self);
4307
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004308 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004309 RETURN_IF_ERR();
4310 RETURN_NONE();
4311}
4312
4313
4314static PyObject*
4315DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4316{
4317 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004318 long stamp;
4319 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004320
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004321 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004322 return NULL;
4323 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004324 timestamp = (time_t)stamp;
4325 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004326 RETURN_IF_ERR();
4327 RETURN_NONE();
4328}
4329
4330
4331static PyObject*
4332DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4333{
4334 int err, atype, flags=0;
4335 int aborted = 0;
4336
4337 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4338 return NULL;
4339 CHECK_ENV_NOT_CLOSED(self);
4340
4341 MYDB_BEGIN_ALLOW_THREADS;
4342#if (DBVER >= 40)
4343 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4344#else
4345 err = lock_detect(self->db_env, flags, atype, &aborted);
4346#endif
4347 MYDB_END_ALLOW_THREADS;
4348 RETURN_IF_ERR();
4349 return PyInt_FromLong(aborted);
4350}
4351
4352
4353static PyObject*
4354DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4355{
4356 int flags=0;
4357 int locker, lock_mode;
4358 DBT obj;
4359 PyObject* objobj;
4360
4361 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4362 return NULL;
4363
4364
4365 if (!make_dbt(objobj, &obj))
4366 return NULL;
4367
4368 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4369}
4370
4371
4372static PyObject*
4373DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4374{
4375 int err;
4376 u_int32_t theID;
4377
4378 if (!PyArg_ParseTuple(args, ":lock_id"))
4379 return NULL;
4380
4381 CHECK_ENV_NOT_CLOSED(self);
4382 MYDB_BEGIN_ALLOW_THREADS;
4383#if (DBVER >= 40)
4384 err = self->db_env->lock_id(self->db_env, &theID);
4385#else
4386 err = lock_id(self->db_env, &theID);
4387#endif
4388 MYDB_END_ALLOW_THREADS;
4389 RETURN_IF_ERR();
4390
4391 return PyInt_FromLong((long)theID);
4392}
4393
4394
4395static PyObject*
4396DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4397{
4398 int err;
4399 DBLockObject* dblockobj;
4400
4401 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4402 return NULL;
4403
4404 CHECK_ENV_NOT_CLOSED(self);
4405 MYDB_BEGIN_ALLOW_THREADS;
4406#if (DBVER >= 40)
4407 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4408#else
4409 err = lock_put(self->db_env, &dblockobj->lock);
4410#endif
4411 MYDB_END_ALLOW_THREADS;
4412 RETURN_IF_ERR();
4413 RETURN_NONE();
4414}
4415
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004416#if (DBVER >= 44)
4417static PyObject*
4418DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4419{
4420 int err;
4421 char *file;
4422 u_int32_t flags = 0;
4423 static char* kwnames[] = { "file", "flags", NULL};
4424
4425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4426 &file, &flags))
4427 return NULL;
4428 CHECK_ENV_NOT_CLOSED(self);
4429
4430 MYDB_BEGIN_ALLOW_THREADS;
4431 err = self->db_env->lsn_reset(self->db_env, file, flags);
4432 MYDB_END_ALLOW_THREADS;
4433 RETURN_IF_ERR();
4434 RETURN_NONE();
4435}
4436#endif /* DBVER >= 4.4 */
4437
4438#if (DBVER >= 40)
4439static PyObject*
4440DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4441{
4442 int err;
4443 DB_LOG_STAT* statp = NULL;
4444 PyObject* d = NULL;
4445 u_int32_t flags = 0;
4446
4447 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4448 return NULL;
4449 CHECK_ENV_NOT_CLOSED(self);
4450
4451 MYDB_BEGIN_ALLOW_THREADS;
4452 err = self->db_env->log_stat(self->db_env, &statp, flags);
4453 MYDB_END_ALLOW_THREADS;
4454 RETURN_IF_ERR();
4455
4456 /* Turn the stat structure into a dictionary */
4457 d = PyDict_New();
4458 if (d == NULL) {
4459 if (statp)
4460 free(statp);
4461 return NULL;
4462 }
4463
4464#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4465
4466 MAKE_ENTRY(magic);
4467 MAKE_ENTRY(version);
4468 MAKE_ENTRY(mode);
4469 MAKE_ENTRY(lg_bsize);
4470#if (DBVER >= 44)
4471 MAKE_ENTRY(lg_size);
4472 MAKE_ENTRY(record);
4473#endif
4474#if (DBVER <= 40)
4475 MAKE_ENTRY(lg_max);
4476#endif
4477 MAKE_ENTRY(w_mbytes);
4478 MAKE_ENTRY(w_bytes);
4479 MAKE_ENTRY(wc_mbytes);
4480 MAKE_ENTRY(wc_bytes);
4481 MAKE_ENTRY(wcount);
4482 MAKE_ENTRY(wcount_fill);
4483#if (DBVER >= 44)
4484 MAKE_ENTRY(rcount);
4485#endif
4486 MAKE_ENTRY(scount);
4487 MAKE_ENTRY(cur_file);
4488 MAKE_ENTRY(cur_offset);
4489 MAKE_ENTRY(disk_file);
4490 MAKE_ENTRY(disk_offset);
4491 MAKE_ENTRY(maxcommitperflush);
4492 MAKE_ENTRY(mincommitperflush);
4493 MAKE_ENTRY(regsize);
4494 MAKE_ENTRY(region_wait);
4495 MAKE_ENTRY(region_nowait);
4496
4497#undef MAKE_ENTRY
4498 free(statp);
4499 return d;
4500} /* DBEnv_log_stat */
4501#endif /* DBVER >= 4.0 for log_stat method */
4502
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004503
4504static PyObject*
4505DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4506{
4507 int err;
4508 DB_LOCK_STAT* sp;
4509 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004510 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004511
4512 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4513 return NULL;
4514 CHECK_ENV_NOT_CLOSED(self);
4515
4516 MYDB_BEGIN_ALLOW_THREADS;
4517#if (DBVER >= 40)
4518 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4519#else
4520#if (DBVER >= 33)
4521 err = lock_stat(self->db_env, &sp);
4522#else
4523 err = lock_stat(self->db_env, &sp, NULL);
4524#endif
4525#endif
4526 MYDB_END_ALLOW_THREADS;
4527 RETURN_IF_ERR();
4528
4529 /* Turn the stat structure into a dictionary */
4530 d = PyDict_New();
4531 if (d == NULL) {
4532 free(sp);
4533 return NULL;
4534 }
4535
4536#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4537
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004538#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004540#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541 MAKE_ENTRY(nmodes);
4542#if (DBVER >= 32)
4543 MAKE_ENTRY(maxlocks);
4544 MAKE_ENTRY(maxlockers);
4545 MAKE_ENTRY(maxobjects);
4546 MAKE_ENTRY(nlocks);
4547 MAKE_ENTRY(maxnlocks);
4548#endif
4549 MAKE_ENTRY(nlockers);
4550 MAKE_ENTRY(maxnlockers);
4551#if (DBVER >= 32)
4552 MAKE_ENTRY(nobjects);
4553 MAKE_ENTRY(maxnobjects);
4554#endif
4555 MAKE_ENTRY(nrequests);
4556 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004557#if (DBVER < 44)
4558 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004560#else
4561 MAKE_ENTRY(lock_nowait);
4562 MAKE_ENTRY(lock_wait);
4563#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004564 MAKE_ENTRY(ndeadlocks);
4565 MAKE_ENTRY(regsize);
4566 MAKE_ENTRY(region_wait);
4567 MAKE_ENTRY(region_nowait);
4568
4569#undef MAKE_ENTRY
4570 free(sp);
4571 return d;
4572}
4573
4574
4575static PyObject*
4576DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4577{
4578 int flags=0;
4579 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004580 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004581 PyObject* list;
4582 PyObject* item = NULL;
4583
4584 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4585 return NULL;
4586
4587 CHECK_ENV_NOT_CLOSED(self);
4588 MYDB_BEGIN_ALLOW_THREADS;
4589#if (DBVER >= 40)
4590 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4591#elif (DBVER == 33)
4592 err = log_archive(self->db_env, &log_list, flags);
4593#else
4594 err = log_archive(self->db_env, &log_list, flags, NULL);
4595#endif
4596 MYDB_END_ALLOW_THREADS;
4597 RETURN_IF_ERR();
4598
4599 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004600 if (list == NULL) {
4601 if (log_list)
4602 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004603 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004604 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605
4606 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004607 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4609 item = PyString_FromString (*log_list);
4610 if (item == NULL) {
4611 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 list = NULL;
4613 break;
4614 }
4615 PyList_Append(list, item);
4616 Py_DECREF(item);
4617 }
4618 free(log_list_start);
4619 }
4620 return list;
4621}
4622
4623
4624static PyObject*
4625DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4626{
4627 int err;
4628 DB_TXN_STAT* sp;
4629 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004630 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004631
4632 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4633 return NULL;
4634 CHECK_ENV_NOT_CLOSED(self);
4635
4636 MYDB_BEGIN_ALLOW_THREADS;
4637#if (DBVER >= 40)
4638 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4639#elif (DBVER == 33)
4640 err = txn_stat(self->db_env, &sp);
4641#else
4642 err = txn_stat(self->db_env, &sp, NULL);
4643#endif
4644 MYDB_END_ALLOW_THREADS;
4645 RETURN_IF_ERR();
4646
4647 /* Turn the stat structure into a dictionary */
4648 d = PyDict_New();
4649 if (d == NULL) {
4650 free(sp);
4651 return NULL;
4652 }
4653
4654#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004655#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004656
Guido van Rossumd8faa362007-04-27 19:54:29 +00004657 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004658 MAKE_ENTRY(last_txnid);
4659 MAKE_ENTRY(maxtxns);
4660 MAKE_ENTRY(nactive);
4661 MAKE_ENTRY(maxnactive);
4662 MAKE_ENTRY(nbegins);
4663 MAKE_ENTRY(naborts);
4664 MAKE_ENTRY(ncommits);
4665 MAKE_ENTRY(regsize);
4666 MAKE_ENTRY(region_wait);
4667 MAKE_ENTRY(region_nowait);
4668
4669#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004670#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004671 free(sp);
4672 return d;
4673}
4674
4675
4676static PyObject*
4677DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4678{
4679 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004680 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004681
4682 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4683 return NULL;
4684 CHECK_ENV_NOT_CLOSED(self);
4685
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004686 if (self->moduleFlags.getReturnsNone)
4687 ++oldValue;
4688 if (self->moduleFlags.cursorSetReturnsNone)
4689 ++oldValue;
4690 self->moduleFlags.getReturnsNone = (flags >= 1);
4691 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004692 return PyInt_FromLong(oldValue);
4693}
4694
4695
4696/* --------------------------------------------------------------------- */
4697/* DBTxn methods */
4698
4699
4700static PyObject*
4701DBTxn_commit(DBTxnObject* self, PyObject* args)
4702{
4703 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004704 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004705
4706 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4707 return NULL;
4708
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004709 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004710 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4711 "after txn_commit or txn_abort");
4712 PyErr_SetObject(DBError, t);
4713 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004714 return NULL;
4715 }
4716 txn = self->txn;
4717 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 MYDB_BEGIN_ALLOW_THREADS;
4719#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004720 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004721#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004722 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004723#endif
4724 MYDB_END_ALLOW_THREADS;
4725 RETURN_IF_ERR();
4726 RETURN_NONE();
4727}
4728
4729static PyObject*
4730DBTxn_prepare(DBTxnObject* self, PyObject* args)
4731{
4732#if (DBVER >= 33)
4733 int err;
4734 char* gid=NULL;
4735 int gid_size=0;
4736
4737 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4738 return NULL;
4739
4740 if (gid_size != DB_XIDDATASIZE) {
4741 PyErr_SetString(PyExc_TypeError,
4742 "gid must be DB_XIDDATASIZE bytes long");
4743 return NULL;
4744 }
4745
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004746 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004747 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4748 "after txn_commit or txn_abort");
4749 PyErr_SetObject(DBError, t);
4750 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004751 return NULL;
4752 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004753 MYDB_BEGIN_ALLOW_THREADS;
4754#if (DBVER >= 40)
4755 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4756#else
4757 err = txn_prepare(self->txn, (u_int8_t*)gid);
4758#endif
4759 MYDB_END_ALLOW_THREADS;
4760 RETURN_IF_ERR();
4761 RETURN_NONE();
4762#else
4763 int err;
4764
4765 if (!PyArg_ParseTuple(args, ":prepare"))
4766 return NULL;
4767
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004769 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4770 "after txn_commit or txn_abort");
4771 PyErr_SetObject(DBError, t);
4772 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004773 return NULL;
4774 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004775 MYDB_BEGIN_ALLOW_THREADS;
4776 err = txn_prepare(self->txn);
4777 MYDB_END_ALLOW_THREADS;
4778 RETURN_IF_ERR();
4779 RETURN_NONE();
4780#endif
4781}
4782
4783
4784static PyObject*
4785DBTxn_abort(DBTxnObject* self, PyObject* args)
4786{
4787 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004788 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004789
4790 if (!PyArg_ParseTuple(args, ":abort"))
4791 return NULL;
4792
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004793 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004794 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4795 "after txn_commit or txn_abort");
4796 PyErr_SetObject(DBError, t);
4797 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004798 return NULL;
4799 }
4800 txn = self->txn;
4801 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004802 MYDB_BEGIN_ALLOW_THREADS;
4803#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004805#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004806 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807#endif
4808 MYDB_END_ALLOW_THREADS;
4809 RETURN_IF_ERR();
4810 RETURN_NONE();
4811}
4812
4813
4814static PyObject*
4815DBTxn_id(DBTxnObject* self, PyObject* args)
4816{
4817 int id;
4818
4819 if (!PyArg_ParseTuple(args, ":id"))
4820 return NULL;
4821
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004822 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004823 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4824 "after txn_commit or txn_abort");
4825 PyErr_SetObject(DBError, t);
4826 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004827 return NULL;
4828 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004829 MYDB_BEGIN_ALLOW_THREADS;
4830#if (DBVER >= 40)
4831 id = self->txn->id(self->txn);
4832#else
4833 id = txn_id(self->txn);
4834#endif
4835 MYDB_END_ALLOW_THREADS;
4836 return PyInt_FromLong(id);
4837}
4838
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004839#if (DBVER >= 43)
4840/* --------------------------------------------------------------------- */
4841/* DBSequence methods */
4842
4843
4844static PyObject*
4845DBSequence_close(DBSequenceObject* self, PyObject* args)
4846{
4847 int err, flags=0;
4848 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4849 return NULL;
4850 CHECK_SEQUENCE_NOT_CLOSED(self)
4851
4852 MYDB_BEGIN_ALLOW_THREADS
4853 err = self->sequence->close(self->sequence, flags);
4854 self->sequence = NULL;
4855 MYDB_END_ALLOW_THREADS
4856
4857 RETURN_IF_ERR();
4858
4859 RETURN_NONE();
4860}
4861
4862static PyObject*
4863DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4864{
4865 int err, flags = 0;
4866 int delta = 1;
4867 db_seq_t value;
4868 PyObject *txnobj = NULL;
4869 DB_TXN *txn = NULL;
4870 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4871 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4872 return NULL;
4873 CHECK_SEQUENCE_NOT_CLOSED(self)
4874
4875 if (!checkTxnObj(txnobj, &txn))
4876 return NULL;
4877
4878 MYDB_BEGIN_ALLOW_THREADS
4879 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4880 MYDB_END_ALLOW_THREADS
4881
4882 RETURN_IF_ERR();
4883 return PyLong_FromLongLong(value);
4884
4885}
4886
4887static PyObject*
4888DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4889{
4890 if (!PyArg_ParseTuple(args,":get_dbp"))
4891 return NULL;
4892 CHECK_SEQUENCE_NOT_CLOSED(self)
4893 Py_INCREF(self->mydb);
4894 return (PyObject* )self->mydb;
4895}
4896
4897static PyObject*
4898DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4899{
4900 int err;
4901 DBT key;
4902 CHECK_SEQUENCE_NOT_CLOSED(self)
4903 MYDB_BEGIN_ALLOW_THREADS
4904 err = self->sequence->get_key(self->sequence, &key);
4905 MYDB_END_ALLOW_THREADS
4906
4907 RETURN_IF_ERR();
4908
4909 return PyString_FromStringAndSize(key.data, key.size);
4910}
4911
4912static PyObject*
4913DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4914{
4915 int err;
4916 db_seq_t value;
4917 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4918 return NULL;
4919 CHECK_SEQUENCE_NOT_CLOSED(self)
4920
4921 MYDB_BEGIN_ALLOW_THREADS
4922 err = self->sequence->initial_value(self->sequence, value);
4923 MYDB_END_ALLOW_THREADS
4924
4925 RETURN_IF_ERR();
4926
4927 RETURN_NONE();
4928}
4929
4930static PyObject*
4931DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4932{
4933 int err, flags = 0;
4934 PyObject* keyobj;
4935 PyObject *txnobj = NULL;
4936 DB_TXN *txn = NULL;
4937 DBT key;
4938
4939 static char* kwnames[] = {"key", "txn", "flags", NULL };
4940 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4941 return NULL;
4942
4943 if (!checkTxnObj(txnobj, &txn))
4944 return NULL;
4945
4946 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4947 return NULL;
4948
4949 MYDB_BEGIN_ALLOW_THREADS
4950 err = self->sequence->open(self->sequence, txn, &key, flags);
4951 MYDB_END_ALLOW_THREADS
4952
4953 CLEAR_DBT(key);
4954 RETURN_IF_ERR();
4955
4956 RETURN_NONE();
4957}
4958
4959static PyObject*
4960DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4961{
4962 int err, flags = 0;
4963 PyObject *txnobj = NULL;
4964 DB_TXN *txn = NULL;
4965
4966 static char* kwnames[] = {"txn", "flags", NULL };
4967 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4968 return NULL;
4969
4970 if (!checkTxnObj(txnobj, &txn))
4971 return NULL;
4972
4973 CHECK_SEQUENCE_NOT_CLOSED(self)
4974
4975 MYDB_BEGIN_ALLOW_THREADS
4976 err = self->sequence->remove(self->sequence, txn, flags);
4977 MYDB_END_ALLOW_THREADS
4978
4979 RETURN_IF_ERR();
4980 RETURN_NONE();
4981}
4982
4983static PyObject*
4984DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4985{
4986 int err, size;
4987 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4988 return NULL;
4989 CHECK_SEQUENCE_NOT_CLOSED(self)
4990
4991 MYDB_BEGIN_ALLOW_THREADS
4992 err = self->sequence->set_cachesize(self->sequence, size);
4993 MYDB_END_ALLOW_THREADS
4994
4995 RETURN_IF_ERR();
4996 RETURN_NONE();
4997}
4998
4999static PyObject*
5000DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5001{
5002 int err, size;
5003 if (!PyArg_ParseTuple(args,":get_cachesize"))
5004 return NULL;
5005 CHECK_SEQUENCE_NOT_CLOSED(self)
5006
5007 MYDB_BEGIN_ALLOW_THREADS
5008 err = self->sequence->get_cachesize(self->sequence, &size);
5009 MYDB_END_ALLOW_THREADS
5010
5011 RETURN_IF_ERR();
5012 return PyInt_FromLong(size);
5013}
5014
5015static PyObject*
5016DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5017{
5018 int err, flags = 0;
5019 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5020 return NULL;
5021 CHECK_SEQUENCE_NOT_CLOSED(self)
5022
5023 MYDB_BEGIN_ALLOW_THREADS
5024 err = self->sequence->set_flags(self->sequence, flags);
5025 MYDB_END_ALLOW_THREADS
5026
5027 RETURN_IF_ERR();
5028 RETURN_NONE();
5029
5030}
5031
5032static PyObject*
5033DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5034{
5035 unsigned int flags;
5036 int err;
5037 if (!PyArg_ParseTuple(args,":get_flags"))
5038 return NULL;
5039 CHECK_SEQUENCE_NOT_CLOSED(self)
5040
5041 MYDB_BEGIN_ALLOW_THREADS
5042 err = self->sequence->get_flags(self->sequence, &flags);
5043 MYDB_END_ALLOW_THREADS
5044
5045 RETURN_IF_ERR();
5046 return PyInt_FromLong((int)flags);
5047}
5048
5049static PyObject*
5050DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5051{
5052 int err;
5053 db_seq_t min, max;
5054 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5055 return NULL;
5056 CHECK_SEQUENCE_NOT_CLOSED(self)
5057
5058 MYDB_BEGIN_ALLOW_THREADS
5059 err = self->sequence->set_range(self->sequence, min, max);
5060 MYDB_END_ALLOW_THREADS
5061
5062 RETURN_IF_ERR();
5063 RETURN_NONE();
5064}
5065
5066static PyObject*
5067DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5068{
5069 int err;
5070 db_seq_t min, max;
5071 if (!PyArg_ParseTuple(args,":get_range"))
5072 return NULL;
5073 CHECK_SEQUENCE_NOT_CLOSED(self)
5074
5075 MYDB_BEGIN_ALLOW_THREADS
5076 err = self->sequence->get_range(self->sequence, &min, &max);
5077 MYDB_END_ALLOW_THREADS
5078
5079 RETURN_IF_ERR();
5080 return Py_BuildValue("(LL)", min, max);
5081}
5082
5083static PyObject*
5084DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5085{
5086 int err, flags = 0;
5087 DB_SEQUENCE_STAT* sp = NULL;
5088 PyObject* dict_stat;
5089 static char* kwnames[] = {"flags", NULL };
5090 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5091 return NULL;
5092 CHECK_SEQUENCE_NOT_CLOSED(self);
5093
5094 MYDB_BEGIN_ALLOW_THREADS;
5095 err = self->sequence->stat(self->sequence, &sp, flags);
5096 MYDB_END_ALLOW_THREADS;
5097 RETURN_IF_ERR();
5098
5099 if ((dict_stat = PyDict_New()) == NULL) {
5100 free(sp);
5101 return NULL;
5102 }
5103
5104
5105#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5106#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5107
5108 MAKE_INT_ENTRY(wait);
5109 MAKE_INT_ENTRY(nowait);
5110 MAKE_LONG_LONG_ENTRY(current);
5111 MAKE_LONG_LONG_ENTRY(value);
5112 MAKE_LONG_LONG_ENTRY(last_value);
5113 MAKE_LONG_LONG_ENTRY(min);
5114 MAKE_LONG_LONG_ENTRY(max);
5115 MAKE_INT_ENTRY(cache_size);
5116 MAKE_INT_ENTRY(flags);
5117
5118#undef MAKE_INT_ENTRY
5119#undef MAKE_LONG_LONG_ENTRY
5120
5121 free(sp);
5122 return dict_stat;
5123}
5124#endif
5125
5126
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005127/* --------------------------------------------------------------------- */
5128/* Method definition tables and type objects */
5129
5130static PyMethodDef DB_methods[] = {
5131 {"append", (PyCFunction)DB_append, METH_VARARGS},
5132#if (DBVER >= 33)
5133 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5134#endif
5135 {"close", (PyCFunction)DB_close, METH_VARARGS},
5136#if (DBVER >= 32)
5137 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5138 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5139#endif
5140 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5141 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5142 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5143 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005144#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005145 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005147 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5148 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5149 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5150 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5151 {"join", (PyCFunction)DB_join, METH_VARARGS},
5152 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5153 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5154 {"items", (PyCFunction)DB_items, METH_VARARGS},
5155 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5156 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5157 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5158 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5159 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5160 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005161#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005162 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005163#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005164 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005165#if (DBVER >= 41)
5166 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005168 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5169 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5170 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5171 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5172 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5173 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5174 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5175 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5176 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5177#if (DBVER >= 32)
5178 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5179#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005180 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005181 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5182#if (DBVER >= 33)
5183 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5184#endif
5185 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5186 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5187 {"values", (PyCFunction)DB_values, METH_VARARGS},
5188 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5189 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5190 {NULL, NULL} /* sentinel */
5191};
5192
5193
5194static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005195 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005196 (binaryfunc)DB_subscript, /*mp_subscript*/
5197 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5198};
5199
5200
5201static PyMethodDef DBCursor_methods[] = {
5202 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5203 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5204 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5205 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5206 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5207 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5208 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005209#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005210 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005211#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005212 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5213 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5214 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5215 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5216 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5217 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5218 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5219 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005220 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005221 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005222 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5223 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5224 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5225 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5226 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5227 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5228 {NULL, NULL} /* sentinel */
5229};
5230
5231
5232static PyMethodDef DBEnv_methods[] = {
5233 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5234 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5235 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005236#if (DBVER >= 41)
5237 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5238 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5239 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5240#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005241#if (DBVER >= 40)
5242 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5243#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005244 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005245 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5246 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5247#if (DBVER >= 32)
5248 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5249#endif
5250 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5251 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5252 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005253#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005254 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005255#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005256 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005257#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005258 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005259#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260#if (DBVER >= 32)
5261 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5262 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5263 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5264#endif
5265 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5266 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5267 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5268 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5269 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5270 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005271 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005272 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5273 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5274 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5275 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5276 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5277 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005278#if (DBVER >= 40)
5279 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5280#endif
5281#if (DBVER >= 44)
5282 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5283#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005284 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5285 {NULL, NULL} /* sentinel */
5286};
5287
5288
5289static PyMethodDef DBTxn_methods[] = {
5290 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5291 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5292 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5293 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5294 {NULL, NULL} /* sentinel */
5295};
5296
5297
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005298#if (DBVER >= 43)
5299static PyMethodDef DBSequence_methods[] = {
5300 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5301 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5302 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5303 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5304 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5305 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5306 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5307 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5308 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5309 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5310 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5311 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5312 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5313 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5314 {NULL, NULL} /* sentinel */
5315};
5316#endif
5317
5318
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005319static PyObject*
5320DB_getattr(DBObject* self, char *name)
5321{
5322 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5323}
5324
5325
5326static PyObject*
5327DBEnv_getattr(DBEnvObject* self, char *name)
5328{
5329 if (!strcmp(name, "db_home")) {
5330 CHECK_ENV_NOT_CLOSED(self);
5331 if (self->db_env->db_home == NULL) {
5332 RETURN_NONE();
5333 }
5334 return PyString_FromString(self->db_env->db_home);
5335 }
5336
5337 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5338}
5339
5340
5341static PyObject*
5342DBCursor_getattr(DBCursorObject* self, char *name)
5343{
5344 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5345}
5346
5347static PyObject*
5348DBTxn_getattr(DBTxnObject* self, char *name)
5349{
5350 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5351}
5352
5353static PyObject*
5354DBLock_getattr(DBLockObject* self, char *name)
5355{
5356 return NULL;
5357}
5358
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005359#if (DBVER >= 43)
5360static PyObject*
5361DBSequence_getattr(DBSequenceObject* self, char *name)
5362{
5363 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5364}
5365#endif
5366
Neal Norwitz227b5332006-03-22 09:28:35 +00005367static PyTypeObject DB_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005368 PyObject_HEAD_INIT(NULL)
5369 0, /*ob_size*/
5370 "DB", /*tp_name*/
5371 sizeof(DBObject), /*tp_basicsize*/
5372 0, /*tp_itemsize*/
5373 /* methods */
5374 (destructor)DB_dealloc, /*tp_dealloc*/
5375 0, /*tp_print*/
5376 (getattrfunc)DB_getattr, /*tp_getattr*/
5377 0, /*tp_setattr*/
5378 0, /*tp_compare*/
5379 0, /*tp_repr*/
5380 0, /*tp_as_number*/
5381 0, /*tp_as_sequence*/
5382 &DB_mapping,/*tp_as_mapping*/
5383 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005384#ifdef HAVE_WEAKREF
5385 0, /* tp_call */
5386 0, /* tp_str */
5387 0, /* tp_getattro */
5388 0, /* tp_setattro */
5389 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005390 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005391 0, /* tp_doc */
5392 0, /* tp_traverse */
5393 0, /* tp_clear */
5394 0, /* tp_richcompare */
5395 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5396#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005397};
5398
5399
Neal Norwitz227b5332006-03-22 09:28:35 +00005400static PyTypeObject DBCursor_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005401 PyObject_HEAD_INIT(NULL)
5402 0, /*ob_size*/
5403 "DBCursor", /*tp_name*/
5404 sizeof(DBCursorObject), /*tp_basicsize*/
5405 0, /*tp_itemsize*/
5406 /* methods */
5407 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5408 0, /*tp_print*/
5409 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5410 0, /*tp_setattr*/
5411 0, /*tp_compare*/
5412 0, /*tp_repr*/
5413 0, /*tp_as_number*/
5414 0, /*tp_as_sequence*/
5415 0, /*tp_as_mapping*/
5416 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005417#ifdef HAVE_WEAKREF
5418 0, /* tp_call */
5419 0, /* tp_str */
5420 0, /* tp_getattro */
5421 0, /* tp_setattro */
5422 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005423 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005424 0, /* tp_doc */
5425 0, /* tp_traverse */
5426 0, /* tp_clear */
5427 0, /* tp_richcompare */
5428 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5429#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005430};
5431
5432
Neal Norwitz227b5332006-03-22 09:28:35 +00005433static PyTypeObject DBEnv_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434 PyObject_HEAD_INIT(NULL)
5435 0, /*ob_size*/
5436 "DBEnv", /*tp_name*/
5437 sizeof(DBEnvObject), /*tp_basicsize*/
5438 0, /*tp_itemsize*/
5439 /* methods */
5440 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5441 0, /*tp_print*/
5442 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5443 0, /*tp_setattr*/
5444 0, /*tp_compare*/
5445 0, /*tp_repr*/
5446 0, /*tp_as_number*/
5447 0, /*tp_as_sequence*/
5448 0, /*tp_as_mapping*/
5449 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005450#ifdef HAVE_WEAKREF
5451 0, /* tp_call */
5452 0, /* tp_str */
5453 0, /* tp_getattro */
5454 0, /* tp_setattro */
5455 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005456 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005457 0, /* tp_doc */
5458 0, /* tp_traverse */
5459 0, /* tp_clear */
5460 0, /* tp_richcompare */
5461 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5462#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005463};
5464
Neal Norwitz227b5332006-03-22 09:28:35 +00005465static PyTypeObject DBTxn_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005466 PyObject_HEAD_INIT(NULL)
5467 0, /*ob_size*/
5468 "DBTxn", /*tp_name*/
5469 sizeof(DBTxnObject), /*tp_basicsize*/
5470 0, /*tp_itemsize*/
5471 /* methods */
5472 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5473 0, /*tp_print*/
5474 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5475 0, /*tp_setattr*/
5476 0, /*tp_compare*/
5477 0, /*tp_repr*/
5478 0, /*tp_as_number*/
5479 0, /*tp_as_sequence*/
5480 0, /*tp_as_mapping*/
5481 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005482#ifdef HAVE_WEAKREF
5483 0, /* tp_call */
5484 0, /* tp_str */
5485 0, /* tp_getattro */
5486 0, /* tp_setattro */
5487 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005488 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005489 0, /* tp_doc */
5490 0, /* tp_traverse */
5491 0, /* tp_clear */
5492 0, /* tp_richcompare */
5493 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5494#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005495};
5496
5497
Neal Norwitz227b5332006-03-22 09:28:35 +00005498static PyTypeObject DBLock_Type = {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499 PyObject_HEAD_INIT(NULL)
5500 0, /*ob_size*/
5501 "DBLock", /*tp_name*/
5502 sizeof(DBLockObject), /*tp_basicsize*/
5503 0, /*tp_itemsize*/
5504 /* methods */
5505 (destructor)DBLock_dealloc, /*tp_dealloc*/
5506 0, /*tp_print*/
5507 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5508 0, /*tp_setattr*/
5509 0, /*tp_compare*/
5510 0, /*tp_repr*/
5511 0, /*tp_as_number*/
5512 0, /*tp_as_sequence*/
5513 0, /*tp_as_mapping*/
5514 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005515#ifdef HAVE_WEAKREF
5516 0, /* tp_call */
5517 0, /* tp_str */
5518 0, /* tp_getattro */
5519 0, /* tp_setattro */
5520 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005521 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005522 0, /* tp_doc */
5523 0, /* tp_traverse */
5524 0, /* tp_clear */
5525 0, /* tp_richcompare */
5526 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5527#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005528};
5529
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005530#if (DBVER >= 43)
5531static PyTypeObject DBSequence_Type = {
5532 PyObject_HEAD_INIT(NULL)
5533 0, /*ob_size*/
5534 "DBSequence", /*tp_name*/
5535 sizeof(DBSequenceObject), /*tp_basicsize*/
5536 0, /*tp_itemsize*/
5537 /* methods */
5538 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5539 0, /*tp_print*/
5540 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5541 0, /*tp_setattr*/
5542 0, /*tp_compare*/
5543 0, /*tp_repr*/
5544 0, /*tp_as_number*/
5545 0, /*tp_as_sequence*/
5546 0, /*tp_as_mapping*/
5547 0, /*tp_hash*/
5548#ifdef HAVE_WEAKREF
5549 0, /* tp_call */
5550 0, /* tp_str */
5551 0, /* tp_getattro */
5552 0, /* tp_setattro */
5553 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005554 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005555 0, /* tp_doc */
5556 0, /* tp_traverse */
5557 0, /* tp_clear */
5558 0, /* tp_richcompare */
5559 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5560#endif
5561};
5562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563
5564/* --------------------------------------------------------------------- */
5565/* Module-level functions */
5566
5567static PyObject*
5568DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5569{
5570 PyObject* dbenvobj = NULL;
5571 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005572 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005573
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5575 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005576 return NULL;
5577 if (dbenvobj == Py_None)
5578 dbenvobj = NULL;
5579 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5580 makeTypeError("DBEnv", dbenvobj);
5581 return NULL;
5582 }
5583
5584 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5585}
5586
5587
5588static PyObject*
5589DBEnv_construct(PyObject* self, PyObject* args)
5590{
5591 int flags = 0;
5592 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5593 return (PyObject* )newDBEnvObject(flags);
5594}
5595
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005596#if (DBVER >= 43)
5597static PyObject*
5598DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5599{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005600 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005601 int flags = 0;
5602 static char* kwnames[] = { "db", "flags", NULL};
5603
5604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5605 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005606 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005607 makeTypeError("DB", dbobj);
5608 return NULL;
5609 }
5610 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5611}
5612#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005613
5614static char bsddb_version_doc[] =
5615"Returns a tuple of major, minor, and patch release numbers of the\n\
5616underlying DB library.";
5617
5618static PyObject*
5619bsddb_version(PyObject* self, PyObject* args)
5620{
5621 int major, minor, patch;
5622
5623 if (!PyArg_ParseTuple(args, ":version"))
5624 return NULL;
5625 db_version(&major, &minor, &patch);
5626 return Py_BuildValue("(iii)", major, minor, patch);
5627}
5628
5629
5630/* List of functions defined in the module */
5631
5632static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005633 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5634 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5635#if (DBVER >= 43)
5636 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5637#endif
5638 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005639 {NULL, NULL} /* sentinel */
5640};
5641
5642
5643/* --------------------------------------------------------------------- */
5644/* Module initialization */
5645
5646
5647/* Convenience routine to export an integer value.
5648 * Errors are silently ignored, for better or for worse...
5649 */
5650#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5651
Gregory P. Smith41631e82003-09-21 00:08:14 +00005652#define MODULE_NAME_MAX_LEN 11
5653static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005654
Neal Norwitzf6657e62006-12-28 04:47:50 +00005655PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656{
5657 PyObject* m;
5658 PyObject* d;
5659 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5660 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5661 PyObject* cvsid_s = PyString_FromString( rcs_id );
5662
5663 /* Initialize the type of the new type objects here; doing it here
5664 is required for portability to Windows without requiring C++. */
5665 DB_Type.ob_type = &PyType_Type;
5666 DBCursor_Type.ob_type = &PyType_Type;
5667 DBEnv_Type.ob_type = &PyType_Type;
5668 DBTxn_Type.ob_type = &PyType_Type;
5669 DBLock_Type.ob_type = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005670#if (DBVER >= 43)
5671 DBSequence_Type.ob_type = &PyType_Type;
5672#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673
5674
Mark Hammonda69d4092003-04-22 23:13:27 +00005675#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005676 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005677 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678#endif
5679
5680 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005681 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005682 if (m == NULL)
5683 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005684
5685 /* Add some symbolic constants to the module */
5686 d = PyModule_GetDict(m);
5687 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5688 PyDict_SetItemString(d, "cvsid", cvsid_s);
5689 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5690 Py_DECREF(pybsddb_version_s);
5691 pybsddb_version_s = NULL;
5692 Py_DECREF(cvsid_s);
5693 cvsid_s = NULL;
5694 Py_DECREF(db_version_s);
5695 db_version_s = NULL;
5696
5697 ADD_INT(d, DB_VERSION_MAJOR);
5698 ADD_INT(d, DB_VERSION_MINOR);
5699 ADD_INT(d, DB_VERSION_PATCH);
5700
5701 ADD_INT(d, DB_MAX_PAGES);
5702 ADD_INT(d, DB_MAX_RECORDS);
5703
Gregory P. Smith41631e82003-09-21 00:08:14 +00005704#if (DBVER >= 42)
5705 ADD_INT(d, DB_RPCCLIENT);
5706#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005707 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005708 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5709 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711 ADD_INT(d, DB_XA_CREATE);
5712
5713 ADD_INT(d, DB_CREATE);
5714 ADD_INT(d, DB_NOMMAP);
5715 ADD_INT(d, DB_THREAD);
5716
5717 ADD_INT(d, DB_FORCE);
5718 ADD_INT(d, DB_INIT_CDB);
5719 ADD_INT(d, DB_INIT_LOCK);
5720 ADD_INT(d, DB_INIT_LOG);
5721 ADD_INT(d, DB_INIT_MPOOL);
5722 ADD_INT(d, DB_INIT_TXN);
5723#if (DBVER >= 32)
5724 ADD_INT(d, DB_JOINENV);
5725#endif
5726
5727 ADD_INT(d, DB_RECOVER);
5728 ADD_INT(d, DB_RECOVER_FATAL);
5729 ADD_INT(d, DB_TXN_NOSYNC);
5730 ADD_INT(d, DB_USE_ENVIRON);
5731 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5732
5733 ADD_INT(d, DB_LOCKDOWN);
5734 ADD_INT(d, DB_PRIVATE);
5735 ADD_INT(d, DB_SYSTEM_MEM);
5736
5737 ADD_INT(d, DB_TXN_SYNC);
5738 ADD_INT(d, DB_TXN_NOWAIT);
5739
5740 ADD_INT(d, DB_EXCL);
5741 ADD_INT(d, DB_FCNTL_LOCKING);
5742 ADD_INT(d, DB_ODDFILESIZE);
5743 ADD_INT(d, DB_RDWRMASTER);
5744 ADD_INT(d, DB_RDONLY);
5745 ADD_INT(d, DB_TRUNCATE);
5746#if (DBVER >= 32)
5747 ADD_INT(d, DB_EXTENT);
5748 ADD_INT(d, DB_CDB_ALLDB);
5749 ADD_INT(d, DB_VERIFY);
5750#endif
5751 ADD_INT(d, DB_UPGRADE);
5752
5753 ADD_INT(d, DB_AGGRESSIVE);
5754 ADD_INT(d, DB_NOORDERCHK);
5755 ADD_INT(d, DB_ORDERCHKONLY);
5756 ADD_INT(d, DB_PR_PAGE);
5757#if ! (DBVER >= 33)
5758 ADD_INT(d, DB_VRFY_FLAGMASK);
5759 ADD_INT(d, DB_PR_HEADERS);
5760#endif
5761 ADD_INT(d, DB_PR_RECOVERYTEST);
5762 ADD_INT(d, DB_SALVAGE);
5763
5764 ADD_INT(d, DB_LOCK_NORUN);
5765 ADD_INT(d, DB_LOCK_DEFAULT);
5766 ADD_INT(d, DB_LOCK_OLDEST);
5767 ADD_INT(d, DB_LOCK_RANDOM);
5768 ADD_INT(d, DB_LOCK_YOUNGEST);
5769#if (DBVER >= 33)
5770 ADD_INT(d, DB_LOCK_MAXLOCKS);
5771 ADD_INT(d, DB_LOCK_MINLOCKS);
5772 ADD_INT(d, DB_LOCK_MINWRITE);
5773#endif
5774
5775
5776#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005777 /* docs say to use zero instead */
5778 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005779#else
5780 ADD_INT(d, DB_LOCK_CONFLICT);
5781#endif
5782
5783 ADD_INT(d, DB_LOCK_DUMP);
5784 ADD_INT(d, DB_LOCK_GET);
5785 ADD_INT(d, DB_LOCK_INHERIT);
5786 ADD_INT(d, DB_LOCK_PUT);
5787 ADD_INT(d, DB_LOCK_PUT_ALL);
5788 ADD_INT(d, DB_LOCK_PUT_OBJ);
5789
5790 ADD_INT(d, DB_LOCK_NG);
5791 ADD_INT(d, DB_LOCK_READ);
5792 ADD_INT(d, DB_LOCK_WRITE);
5793 ADD_INT(d, DB_LOCK_NOWAIT);
5794#if (DBVER >= 32)
5795 ADD_INT(d, DB_LOCK_WAIT);
5796#endif
5797 ADD_INT(d, DB_LOCK_IWRITE);
5798 ADD_INT(d, DB_LOCK_IREAD);
5799 ADD_INT(d, DB_LOCK_IWR);
5800#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005801#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005803#else
5804 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5805#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005806 ADD_INT(d, DB_LOCK_WWRITE);
5807#endif
5808
5809 ADD_INT(d, DB_LOCK_RECORD);
5810 ADD_INT(d, DB_LOCK_UPGRADE);
5811#if (DBVER >= 32)
5812 ADD_INT(d, DB_LOCK_SWITCH);
5813#endif
5814#if (DBVER >= 33)
5815 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5816#endif
5817
5818 ADD_INT(d, DB_LOCK_NOWAIT);
5819 ADD_INT(d, DB_LOCK_RECORD);
5820 ADD_INT(d, DB_LOCK_UPGRADE);
5821
5822#if (DBVER >= 33)
5823 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005824#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005826#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005827 ADD_INT(d, DB_LSTAT_FREE);
5828 ADD_INT(d, DB_LSTAT_HELD);
5829#if (DBVER == 33)
5830 ADD_INT(d, DB_LSTAT_NOGRANT);
5831#endif
5832 ADD_INT(d, DB_LSTAT_PENDING);
5833 ADD_INT(d, DB_LSTAT_WAITING);
5834#endif
5835
5836 ADD_INT(d, DB_ARCH_ABS);
5837 ADD_INT(d, DB_ARCH_DATA);
5838 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005839#if (DBVER >= 42)
5840 ADD_INT(d, DB_ARCH_REMOVE);
5841#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005842
5843 ADD_INT(d, DB_BTREE);
5844 ADD_INT(d, DB_HASH);
5845 ADD_INT(d, DB_RECNO);
5846 ADD_INT(d, DB_QUEUE);
5847 ADD_INT(d, DB_UNKNOWN);
5848
5849 ADD_INT(d, DB_DUP);
5850 ADD_INT(d, DB_DUPSORT);
5851 ADD_INT(d, DB_RECNUM);
5852 ADD_INT(d, DB_RENUMBER);
5853 ADD_INT(d, DB_REVSPLITOFF);
5854 ADD_INT(d, DB_SNAPSHOT);
5855
5856 ADD_INT(d, DB_JOIN_NOSORT);
5857
5858 ADD_INT(d, DB_AFTER);
5859 ADD_INT(d, DB_APPEND);
5860 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005861#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005862 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005863#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005864#if (DBVER >= 41)
5865 _addIntToDict(d, "DB_CHECKPOINT", 0);
5866#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005867 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005868 ADD_INT(d, DB_CURLSN);
5869#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005870#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005871 ADD_INT(d, DB_COMMIT);
5872#endif
5873 ADD_INT(d, DB_CONSUME);
5874#if (DBVER >= 32)
5875 ADD_INT(d, DB_CONSUME_WAIT);
5876#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877 ADD_INT(d, DB_CURRENT);
5878#if (DBVER >= 33)
5879 ADD_INT(d, DB_FAST_STAT);
5880#endif
5881 ADD_INT(d, DB_FIRST);
5882 ADD_INT(d, DB_FLUSH);
5883 ADD_INT(d, DB_GET_BOTH);
5884 ADD_INT(d, DB_GET_RECNO);
5885 ADD_INT(d, DB_JOIN_ITEM);
5886 ADD_INT(d, DB_KEYFIRST);
5887 ADD_INT(d, DB_KEYLAST);
5888 ADD_INT(d, DB_LAST);
5889 ADD_INT(d, DB_NEXT);
5890 ADD_INT(d, DB_NEXT_DUP);
5891 ADD_INT(d, DB_NEXT_NODUP);
5892 ADD_INT(d, DB_NODUPDATA);
5893 ADD_INT(d, DB_NOOVERWRITE);
5894 ADD_INT(d, DB_NOSYNC);
5895 ADD_INT(d, DB_POSITION);
5896 ADD_INT(d, DB_PREV);
5897 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005898#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005899 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005900#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005901 ADD_INT(d, DB_SET);
5902 ADD_INT(d, DB_SET_RANGE);
5903 ADD_INT(d, DB_SET_RECNO);
5904 ADD_INT(d, DB_WRITECURSOR);
5905
5906 ADD_INT(d, DB_OPFLAGS_MASK);
5907 ADD_INT(d, DB_RMW);
5908#if (DBVER >= 33)
5909 ADD_INT(d, DB_DIRTY_READ);
5910 ADD_INT(d, DB_MULTIPLE);
5911 ADD_INT(d, DB_MULTIPLE_KEY);
5912#endif
5913
Gregory P. Smith29602d22006-01-24 09:46:48 +00005914#if (DBVER >= 44)
5915 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5916 ADD_INT(d, DB_READ_COMMITTED);
5917#endif
5918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005919#if (DBVER >= 33)
5920 ADD_INT(d, DB_DONOTINDEX);
5921#endif
5922
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005923#if (DBVER >= 41)
5924 _addIntToDict(d, "DB_INCOMPLETE", 0);
5925#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005926 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005927#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005928 ADD_INT(d, DB_KEYEMPTY);
5929 ADD_INT(d, DB_KEYEXIST);
5930 ADD_INT(d, DB_LOCK_DEADLOCK);
5931 ADD_INT(d, DB_LOCK_NOTGRANTED);
5932 ADD_INT(d, DB_NOSERVER);
5933 ADD_INT(d, DB_NOSERVER_HOME);
5934 ADD_INT(d, DB_NOSERVER_ID);
5935 ADD_INT(d, DB_NOTFOUND);
5936 ADD_INT(d, DB_OLD_VERSION);
5937 ADD_INT(d, DB_RUNRECOVERY);
5938 ADD_INT(d, DB_VERIFY_BAD);
5939#if (DBVER >= 33)
5940 ADD_INT(d, DB_PAGE_NOTFOUND);
5941 ADD_INT(d, DB_SECONDARY_BAD);
5942#endif
5943#if (DBVER >= 40)
5944 ADD_INT(d, DB_STAT_CLEAR);
5945 ADD_INT(d, DB_REGION_INIT);
5946 ADD_INT(d, DB_NOLOCKING);
5947 ADD_INT(d, DB_YIELDCPU);
5948 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5949 ADD_INT(d, DB_NOPANIC);
5950#endif
5951
Gregory P. Smith41631e82003-09-21 00:08:14 +00005952#if (DBVER >= 42)
5953 ADD_INT(d, DB_TIME_NOTGRANTED);
5954 ADD_INT(d, DB_TXN_NOT_DURABLE);
5955 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5956 ADD_INT(d, DB_LOG_AUTOREMOVE);
5957 ADD_INT(d, DB_DIRECT_LOG);
5958 ADD_INT(d, DB_DIRECT_DB);
5959 ADD_INT(d, DB_INIT_REP);
5960 ADD_INT(d, DB_ENCRYPT);
5961 ADD_INT(d, DB_CHKSUM);
5962#endif
5963
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005964#if (DBVER >= 43)
5965 ADD_INT(d, DB_LOG_INMEMORY);
5966 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005967 ADD_INT(d, DB_SEQ_DEC);
5968 ADD_INT(d, DB_SEQ_INC);
5969 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005970#endif
5971
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005972#if (DBVER >= 41)
5973 ADD_INT(d, DB_ENCRYPT_AES);
5974 ADD_INT(d, DB_AUTO_COMMIT);
5975#else
5976 /* allow berkeleydb 4.1 aware apps to run on older versions */
5977 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5978#endif
5979
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005980 ADD_INT(d, EINVAL);
5981 ADD_INT(d, EACCES);
5982 ADD_INT(d, ENOSPC);
5983 ADD_INT(d, ENOMEM);
5984 ADD_INT(d, EAGAIN);
5985 ADD_INT(d, EBUSY);
5986 ADD_INT(d, EEXIST);
5987 ADD_INT(d, ENOENT);
5988 ADD_INT(d, EPERM);
5989
Barry Warsaw1baa9822003-03-31 19:51:29 +00005990#if (DBVER >= 40)
5991 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5992 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5993#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005994
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005995 /* The exception name must be correct for pickled exception *
5996 * objects to unpickle properly. */
5997#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5998#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5999#else
6000#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6001#endif
6002
6003 /* All the rest of the exceptions derive only from DBError */
6004#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6005 PyDict_SetItemString(d, #name, name)
6006
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006008 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6009 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010
Gregory P. Smithe9477062005-06-04 06:46:59 +00006011 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6012 * from both DBError and KeyError, since the API only supports
6013 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006015 {
6016 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6017 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6018 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006019 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6020 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006021 Py_file_input, d, d);
6022 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006023 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006024 PyDict_DelItemString(d, "KeyError");
6025
6026
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006027#if !INCOMPLETE_IS_WARNING
6028 MAKE_EX(DBIncompleteError);
6029#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006030 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006031 MAKE_EX(DBKeyEmptyError);
6032 MAKE_EX(DBKeyExistError);
6033 MAKE_EX(DBLockDeadlockError);
6034 MAKE_EX(DBLockNotGrantedError);
6035 MAKE_EX(DBOldVersionError);
6036 MAKE_EX(DBRunRecoveryError);
6037 MAKE_EX(DBVerifyBadError);
6038 MAKE_EX(DBNoServerError);
6039 MAKE_EX(DBNoServerHomeError);
6040 MAKE_EX(DBNoServerIDError);
6041#if (DBVER >= 33)
6042 MAKE_EX(DBPageNotFoundError);
6043 MAKE_EX(DBSecondaryBadError);
6044#endif
6045
6046 MAKE_EX(DBInvalidArgError);
6047 MAKE_EX(DBAccessError);
6048 MAKE_EX(DBNoSpaceError);
6049 MAKE_EX(DBNoMemoryError);
6050 MAKE_EX(DBAgainError);
6051 MAKE_EX(DBBusyError);
6052 MAKE_EX(DBFileExistsError);
6053 MAKE_EX(DBNoSuchFileError);
6054 MAKE_EX(DBPermissionsError);
6055
6056#undef MAKE_EX
6057
6058 /* Check for errors */
6059 if (PyErr_Occurred()) {
6060 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006061 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006062 }
6063}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006064
6065/* allow this module to be named _pybsddb so that it can be installed
6066 * and imported on top of python >= 2.3 that includes its own older
6067 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006068PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006069{
6070 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6071 init_bsddb();
6072}