blob: 195132e3d2542bb82c38c81f796e3153d6297456 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith1a050f52007-01-05 02:09:06 +0000101#define PY_BSDDB_VERSION "4.4.5.2"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
Gregory P. Smith7d9c00e2007-10-09 07:25:24 +0000428 /*
429 * NOTE(gps): I don't like doing a data copy here, it seems
430 * wasteful. But without a clean way to tell FREE_DBT if it
431 * should free key->data or not we have to. Other places in
432 * the code check for DB_THREAD and forceably set DBT_MALLOC
433 * when we otherwise would leave flags 0 to indicate that.
434 */
435 key->data = strdup(PyString_AS_STRING(keyobj));
436 if (key->data == NULL) {
437 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
438 return 0;
439 }
440 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000441 key->size = PyString_GET_SIZE(keyobj);
442 }
443
444 else if (PyInt_Check(keyobj)) {
445 /* verify access method type */
446 type = _DB_get_type(self);
447 if (type == -1)
448 return 0;
449 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000450 /* if BTREE then an Integer key is allowed with the
451 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000452 *pflags |= DB_SET_RECNO;
453 }
454 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000455 PyErr_SetString(
456 PyExc_TypeError,
457 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000458 return 0;
459 }
460
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000461 /* Make a key out of the requested recno, use allocated space so DB
462 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000463 recno = PyInt_AS_LONG(keyobj);
464 key->data = malloc(sizeof(db_recno_t));
465 if (key->data == NULL) {
466 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
467 return 0;
468 }
469 key->ulen = key->size = sizeof(db_recno_t);
470 memcpy(key->data, &recno, sizeof(db_recno_t));
471 key->flags = DB_DBT_REALLOC;
472 }
473 else {
474 PyErr_Format(PyExc_TypeError,
475 "String or Integer object expected for key, %s found",
476 keyobj->ob_type->tp_name);
477 return 0;
478 }
479
480 return 1;
481}
482
483
484/* Add partial record access to an existing DBT data struct.
485 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
486 and the data storage/retrieval will be done using dlen and doff. */
487static int add_partial_dbt(DBT* d, int dlen, int doff) {
488 /* if neither were set we do nothing (-1 is the default value) */
489 if ((dlen == -1) && (doff == -1)) {
490 return 1;
491 }
492
493 if ((dlen < 0) || (doff < 0)) {
494 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
495 return 0;
496 }
497
498 d->flags = d->flags | DB_DBT_PARTIAL;
499 d->dlen = (unsigned int) dlen;
500 d->doff = (unsigned int) doff;
501 return 1;
502}
503
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000504/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
505/* TODO: make this use the native libc strlcpy() when available (BSD) */
506unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
507{
508 unsigned int srclen, copylen;
509
510 srclen = strlen(src);
511 if (n <= 0)
512 return srclen;
513 copylen = (srclen > n-1) ? n-1 : srclen;
514 /* populate dest[0] thru dest[copylen-1] */
515 memcpy(dest, src, copylen);
516 /* guarantee null termination */
517 dest[copylen] = 0;
518
519 return srclen;
520}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000522/* Callback used to save away more information about errors from the DB
523 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000524static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000525#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000526static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000527#else
528static void _db_errorCallback(const DB_ENV *db_env,
529 const char* prefix, const char* msg)
530#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000531{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000532 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533}
534
535
536/* make a nice exception object to raise for errors. */
537static int makeDBError(int err)
538{
539 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000540 PyObject *errObj = NULL;
541 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000542 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000543 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544
545 switch (err) {
546 case 0: /* successful, no error */ break;
547
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000548#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 case DB_INCOMPLETE:
550#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000551 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
552 /* Ensure that bytes_left never goes negative */
553 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
554 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
555 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000557 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000559 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000560#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000561 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
562#else
563 fprintf(stderr, errTxt);
564 fprintf(stderr, "\n");
565#endif
566
567#else /* do an exception instead */
568 errObj = DBIncompleteError;
569#endif
570 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000571#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000572
573 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
574 case DB_KEYEXIST: errObj = DBKeyExistError; break;
575 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
576 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
577 case DB_NOTFOUND: errObj = DBNotFoundError; break;
578 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
579 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
580 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
581 case DB_NOSERVER: errObj = DBNoServerError; break;
582 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
583 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
584#if (DBVER >= 33)
585 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
586 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
587#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000588 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000589
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000590#if (DBVER >= 43)
591 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
592 case ENOMEM: errObj = PyExc_MemoryError; break;
593#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000594 case EINVAL: errObj = DBInvalidArgError; break;
595 case EACCES: errObj = DBAccessError; break;
596 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000597 case EAGAIN: errObj = DBAgainError; break;
598 case EBUSY : errObj = DBBusyError; break;
599 case EEXIST: errObj = DBFileExistsError; break;
600 case ENOENT: errObj = DBNoSuchFileError; break;
601 case EPERM : errObj = DBPermissionsError; break;
602
603 default: errObj = DBError; break;
604 }
605
606 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000607 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
608 /* Ensure that bytes_left never goes negative */
609 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
610 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
611 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000612 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000613 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000615 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000616
617 errTuple = Py_BuildValue("(is)", err, errTxt);
618 PyErr_SetObject(errObj, errTuple);
619 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620 }
621
622 return ((errObj != NULL) || exceptionRaised);
623}
624
625
626
627/* set a type exception */
628static void makeTypeError(char* expected, PyObject* found)
629{
630 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
631 expected, found->ob_type->tp_name);
632}
633
634
635/* verify that an obj is either None or a DBTxn, and set the txn pointer */
636static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
637{
638 if (txnobj == Py_None || txnobj == NULL) {
639 *txn = NULL;
640 return 1;
641 }
642 if (DBTxnObject_Check(txnobj)) {
643 *txn = ((DBTxnObject*)txnobj)->txn;
644 return 1;
645 }
646 else
647 makeTypeError("DBTxn", txnobj);
648 return 0;
649}
650
651
652/* Delete a key from a database
653 Returns 0 on success, -1 on an error. */
654static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
655{
656 int err;
657
658 MYDB_BEGIN_ALLOW_THREADS;
659 err = self->db->del(self->db, txn, key, 0);
660 MYDB_END_ALLOW_THREADS;
661 if (makeDBError(err)) {
662 return -1;
663 }
664 self->haveStat = 0;
665 return 0;
666}
667
668
669/* Store a key into a database
670 Returns 0 on success, -1 on an error. */
671static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
672{
673 int err;
674
675 MYDB_BEGIN_ALLOW_THREADS;
676 err = self->db->put(self->db, txn, key, data, flags);
677 MYDB_END_ALLOW_THREADS;
678 if (makeDBError(err)) {
679 return -1;
680 }
681 self->haveStat = 0;
682 return 0;
683}
684
685/* Get a key/data pair from a cursor */
686static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
687 PyObject *args, PyObject *kwargs, char *format)
688{
689 int err;
690 PyObject* retval = NULL;
691 DBT key, data;
692 int dlen = -1;
693 int doff = -1;
694 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000695 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000696
697 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
698 &flags, &dlen, &doff))
699 return NULL;
700
701 CHECK_CURSOR_NOT_CLOSED(self);
702
703 flags |= extra_flags;
704 CLEAR_DBT(key);
705 CLEAR_DBT(data);
706 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
707 /* Tell BerkeleyDB to malloc the return value (thread safe) */
708 data.flags = DB_DBT_MALLOC;
709 key.flags = DB_DBT_MALLOC;
710 }
711 if (!add_partial_dbt(&data, dlen, doff))
712 return NULL;
713
714 MYDB_BEGIN_ALLOW_THREADS;
715 err = self->dbc->c_get(self->dbc, &key, &data, flags);
716 MYDB_END_ALLOW_THREADS;
717
Gregory P. Smithe9477062005-06-04 06:46:59 +0000718 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
719 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720 Py_INCREF(Py_None);
721 retval = Py_None;
722 }
723 else if (makeDBError(err)) {
724 retval = NULL;
725 }
726 else { /* otherwise, success! */
727
728 /* if Recno or Queue, return the key as an Int */
729 switch (_DB_get_type(self->mydb)) {
730 case -1:
731 retval = NULL;
732 break;
733
734 case DB_RECNO:
735 case DB_QUEUE:
736 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
737 data.data, data.size);
738 break;
739 case DB_HASH:
740 case DB_BTREE:
741 default:
742 retval = Py_BuildValue("s#s#", key.data, key.size,
743 data.data, data.size);
744 break;
745 }
746 }
747 if (!err) {
748 FREE_DBT(key);
749 FREE_DBT(data);
750 }
751 return retval;
752}
753
754
755/* add an integer to a dictionary using the given name as a key */
756static void _addIntToDict(PyObject* dict, char *name, int value)
757{
758 PyObject* v = PyInt_FromLong((long) value);
759 if (!v || PyDict_SetItemString(dict, name, v))
760 PyErr_Clear();
761
762 Py_XDECREF(v);
763}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000764#if (DBVER >= 43)
765/* add an db_seq_t to a dictionary using the given name as a key */
766static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
767{
768 PyObject* v = PyLong_FromLongLong(value);
769 if (!v || PyDict_SetItemString(dict, name, v))
770 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000771
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000772 Py_XDECREF(v);
773}
774#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000775
776
777
778/* --------------------------------------------------------------------- */
779/* Allocators and deallocators */
780
781static DBObject*
782newDBObject(DBEnvObject* arg, int flags)
783{
784 DBObject* self;
785 DB_ENV* db_env = NULL;
786 int err;
787
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000788 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 if (self == NULL)
790 return NULL;
791
792 self->haveStat = 0;
793 self->flags = 0;
794 self->setflags = 0;
795 self->myenvobj = NULL;
796#if (DBVER >= 33)
797 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000798 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 self->primaryDBType = 0;
800#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000801#ifdef HAVE_WEAKREF
802 self->in_weakreflist = NULL;
803#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000804
805 /* keep a reference to our python DBEnv object */
806 if (arg) {
807 Py_INCREF(arg);
808 self->myenvobj = arg;
809 db_env = arg->db_env;
810 }
811
812 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000813 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000815 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
816 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000817
818 MYDB_BEGIN_ALLOW_THREADS;
819 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000820 if (self->db != NULL) {
821 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000822#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000823 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000825 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000827 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
828 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000829 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830 if (makeDBError(err)) {
831 if (self->myenvobj) {
832 Py_DECREF(self->myenvobj);
833 self->myenvobj = NULL;
834 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000835 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 self = NULL;
837 }
838 return self;
839}
840
841
842static void
843DB_dealloc(DBObject* self)
844{
845 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000846 /* avoid closing a DB when its DBEnv has been closed out from under
847 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000848 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000849 (self->myenvobj && self->myenvobj->db_env))
850 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 MYDB_BEGIN_ALLOW_THREADS;
852 self->db->close(self->db, 0);
853 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000854#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000855 } else {
856 PyErr_Warn(PyExc_RuntimeWarning,
857 "DB could not be closed in destructor: DBEnv already closed");
858#endif
859 }
860 self->db = NULL;
861 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000862#ifdef HAVE_WEAKREF
863 if (self->in_weakreflist != NULL) {
864 PyObject_ClearWeakRefs((PyObject *) self);
865 }
866#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867 if (self->myenvobj) {
868 Py_DECREF(self->myenvobj);
869 self->myenvobj = NULL;
870 }
871#if (DBVER >= 33)
872 if (self->associateCallback != NULL) {
873 Py_DECREF(self->associateCallback);
874 self->associateCallback = NULL;
875 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000876 if (self->btCompareCallback != NULL) {
877 Py_DECREF(self->btCompareCallback);
878 self->btCompareCallback = NULL;
879 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000880#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882}
883
884
885static DBCursorObject*
886newDBCursorObject(DBC* dbc, DBObject* db)
887{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000888 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 if (self == NULL)
890 return NULL;
891
892 self->dbc = dbc;
893 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000894#ifdef HAVE_WEAKREF
895 self->in_weakreflist = NULL;
896#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000897 Py_INCREF(self->mydb);
898 return self;
899}
900
901
902static void
903DBCursor_dealloc(DBCursorObject* self)
904{
905 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000906
907#ifdef HAVE_WEAKREF
908 if (self->in_weakreflist != NULL) {
909 PyObject_ClearWeakRefs((PyObject *) self);
910 }
911#endif
912
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000913 if (self->dbc != NULL) {
914 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000915 /* If the underlying database has been closed, we don't
916 need to do anything. If the environment has been closed
917 we need to leak, as BerkeleyDB will crash trying to access
918 the environment. There was an exception when the
919 user closed the environment even though there still was
920 a database open. */
921 if (self->mydb->db && self->mydb->myenvobj &&
922 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000923 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 self->dbc = NULL;
925 MYDB_END_ALLOW_THREADS;
926 }
927 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000929}
930
931
932static DBEnvObject*
933newDBEnvObject(int flags)
934{
935 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000936 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937 if (self == NULL)
938 return NULL;
939
940 self->closed = 1;
941 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000942 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
943 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000944#ifdef HAVE_WEAKREF
945 self->in_weakreflist = NULL;
946#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947
948 MYDB_BEGIN_ALLOW_THREADS;
949 err = db_env_create(&self->db_env, flags);
950 MYDB_END_ALLOW_THREADS;
951 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000952 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953 self = NULL;
954 }
955 else {
956 self->db_env->set_errcall(self->db_env, _db_errorCallback);
957 }
958 return self;
959}
960
961
962static void
963DBEnv_dealloc(DBEnvObject* self)
964{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000965#ifdef HAVE_WEAKREF
966 if (self->in_weakreflist != NULL) {
967 PyObject_ClearWeakRefs((PyObject *) self);
968 }
969#endif
970
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000971 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972 MYDB_BEGIN_ALLOW_THREADS;
973 self->db_env->close(self->db_env, 0);
974 MYDB_END_ALLOW_THREADS;
975 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000977}
978
979
980static DBTxnObject*
981newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
982{
983 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000984 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 if (self == NULL)
986 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000987 Py_INCREF(myenv);
988 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000989#ifdef HAVE_WEAKREF
990 self->in_weakreflist = NULL;
991#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000992
993 MYDB_BEGIN_ALLOW_THREADS;
994#if (DBVER >= 40)
995 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
996#else
997 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
998#endif
999 MYDB_END_ALLOW_THREADS;
1000 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001001 Py_DECREF(self->env);
1002 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001003 self = NULL;
1004 }
1005 return self;
1006}
1007
1008
1009static void
1010DBTxn_dealloc(DBTxnObject* self)
1011{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001012#ifdef HAVE_WEAKREF
1013 if (self->in_weakreflist != NULL) {
1014 PyObject_ClearWeakRefs((PyObject *) self);
1015 }
1016#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017
Gregory P. Smith31c50652004-06-28 01:20:40 +00001018#ifdef HAVE_WARNINGS
1019 if (self->txn) {
1020 /* it hasn't been finalized, abort it! */
1021 MYDB_BEGIN_ALLOW_THREADS;
1022#if (DBVER >= 40)
1023 self->txn->abort(self->txn);
1024#else
1025 txn_abort(self->txn);
1026#endif
1027 MYDB_END_ALLOW_THREADS;
1028 PyErr_Warn(PyExc_RuntimeWarning,
1029 "DBTxn aborted in destructor. No prior commit() or abort().");
1030 }
1031#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032
Neal Norwitz62a21122006-01-25 05:21:55 +00001033 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001034 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001035}
1036
1037
1038static DBLockObject*
1039newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1040 db_lockmode_t lock_mode, int flags)
1041{
1042 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001043 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 if (self == NULL)
1045 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001046#ifdef HAVE_WEAKREF
1047 self->in_weakreflist = NULL;
1048#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001049
1050 MYDB_BEGIN_ALLOW_THREADS;
1051#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001052 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1053 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001054#else
1055 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1056#endif
1057 MYDB_END_ALLOW_THREADS;
1058 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001059 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060 self = NULL;
1061 }
1062
1063 return self;
1064}
1065
1066
1067static void
1068DBLock_dealloc(DBLockObject* self)
1069{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001070#ifdef HAVE_WEAKREF
1071 if (self->in_weakreflist != NULL) {
1072 PyObject_ClearWeakRefs((PyObject *) self);
1073 }
1074#endif
1075 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001076
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001077 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001078}
1079
1080
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001081#if (DBVER >= 43)
1082static DBSequenceObject*
1083newDBSequenceObject(DBObject* mydb, int flags)
1084{
1085 int err;
1086 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1087 if (self == NULL)
1088 return NULL;
1089 Py_INCREF(mydb);
1090 self->mydb = mydb;
1091#ifdef HAVE_WEAKREF
1092 self->in_weakreflist = NULL;
1093#endif
1094
1095
1096 MYDB_BEGIN_ALLOW_THREADS;
1097 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1098 MYDB_END_ALLOW_THREADS;
1099 if (makeDBError(err)) {
1100 Py_DECREF(self->mydb);
1101 PyObject_Del(self);
1102 self = NULL;
1103 }
1104
1105 return self;
1106}
1107
1108
1109static void
1110DBSequence_dealloc(DBSequenceObject* self)
1111{
1112#ifdef HAVE_WEAKREF
1113 if (self->in_weakreflist != NULL) {
1114 PyObject_ClearWeakRefs((PyObject *) self);
1115 }
1116#endif
1117
1118 Py_DECREF(self->mydb);
1119 PyObject_Del(self);
1120}
1121#endif
1122
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001123/* --------------------------------------------------------------------- */
1124/* DB methods */
1125
1126static PyObject*
1127DB_append(DBObject* self, PyObject* args)
1128{
1129 PyObject* txnobj = NULL;
1130 PyObject* dataobj;
1131 db_recno_t recno;
1132 DBT key, data;
1133 DB_TXN *txn = NULL;
1134
Georg Brandl96a8c392006-05-29 21:04:52 +00001135 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136 return NULL;
1137
1138 CHECK_DB_NOT_CLOSED(self);
1139
1140 /* make a dummy key out of a recno */
1141 recno = 0;
1142 CLEAR_DBT(key);
1143 key.data = &recno;
1144 key.size = sizeof(recno);
1145 key.ulen = key.size;
1146 key.flags = DB_DBT_USERMEM;
1147
1148 if (!make_dbt(dataobj, &data)) return NULL;
1149 if (!checkTxnObj(txnobj, &txn)) return NULL;
1150
1151 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1152 return NULL;
1153
1154 return PyInt_FromLong(recno);
1155}
1156
1157
1158#if (DBVER >= 33)
1159
1160static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001161_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1162 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163{
1164 int retval = DB_DONOTINDEX;
1165 DBObject* secondaryDB = (DBObject*)db->app_private;
1166 PyObject* callback = secondaryDB->associateCallback;
1167 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001168 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001169 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170
1171
1172 if (callback != NULL) {
1173 MYDB_BEGIN_BLOCK_THREADS;
1174
Thomas Woutersb3153832006-03-08 01:47:19 +00001175 if (type == DB_RECNO || type == DB_QUEUE)
1176 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1177 priData->data, priData->size);
1178 else
1179 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1180 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001181 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001182 result = PyEval_CallObject(callback, args);
1183 }
1184 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001185 PyErr_Print();
1186 }
1187 else if (result == Py_None) {
1188 retval = DB_DONOTINDEX;
1189 }
1190 else if (PyInt_Check(result)) {
1191 retval = PyInt_AsLong(result);
1192 }
1193 else if (PyString_Check(result)) {
1194 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001195 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001196
1197 CLEAR_DBT(*secKey);
1198#if PYTHON_API_VERSION <= 1007
1199 /* 1.5 compatibility */
1200 size = PyString_Size(result);
1201 data = PyString_AsString(result);
1202#else
1203 PyString_AsStringAndSize(result, &data, &size);
1204#endif
1205 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1206 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001207 if (secKey->data) {
1208 memcpy(secKey->data, data, size);
1209 secKey->size = size;
1210 retval = 0;
1211 }
1212 else {
1213 PyErr_SetString(PyExc_MemoryError,
1214 "malloc failed in _db_associateCallback");
1215 PyErr_Print();
1216 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001217 }
1218 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001219 PyErr_SetString(
1220 PyExc_TypeError,
1221 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001222 PyErr_Print();
1223 }
1224
Thomas Woutersb3153832006-03-08 01:47:19 +00001225 Py_XDECREF(args);
1226 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227
1228 MYDB_END_BLOCK_THREADS;
1229 }
1230 return retval;
1231}
1232
1233
1234static PyObject*
1235DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1236{
1237 int err, flags=0;
1238 DBObject* secondaryDB;
1239 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001240#if (DBVER >= 41)
1241 PyObject *txnobj = NULL;
1242 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001243 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001244 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001245#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001246 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001248
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001249#if (DBVER >= 41)
1250 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1251 &secondaryDB, &callback, &flags,
1252 &txnobj)) {
1253#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001254 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001255 &secondaryDB, &callback, &flags)) {
1256#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001257 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001258 }
1259
1260#if (DBVER >= 41)
1261 if (!checkTxnObj(txnobj, &txn)) return NULL;
1262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001263
1264 CHECK_DB_NOT_CLOSED(self);
1265 if (!DBObject_Check(secondaryDB)) {
1266 makeTypeError("DB", (PyObject*)secondaryDB);
1267 return NULL;
1268 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001269 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001270 if (callback == Py_None) {
1271 callback = NULL;
1272 }
1273 else if (!PyCallable_Check(callback)) {
1274 makeTypeError("Callable", callback);
1275 return NULL;
1276 }
1277
1278 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001279 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001280 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001281 secondaryDB->associateCallback = callback;
1282 secondaryDB->primaryDBType = _DB_get_type(self);
1283
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001284 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1285 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1286 * The global interepreter lock is not initialized until the first
1287 * thread is created using thread.start_new_thread() or fork() is
1288 * called. that would cause the ALLOW_THREADS here to segfault due
1289 * to a null pointer reference if no threads or child processes
1290 * have been created. This works around that and is a no-op if
1291 * threads have already been initialized.
1292 * (see pybsddb-users mailing list post on 2002-08-07)
1293 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001294#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001295 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001296#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001298#if (DBVER >= 41)
1299 err = self->db->associate(self->db,
1300 txn,
1301 secondaryDB->db,
1302 _db_associateCallback,
1303 flags);
1304#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305 err = self->db->associate(self->db,
1306 secondaryDB->db,
1307 _db_associateCallback,
1308 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001309#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310 MYDB_END_ALLOW_THREADS;
1311
1312 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001313 Py_XDECREF(secondaryDB->associateCallback);
1314 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 secondaryDB->primaryDBType = 0;
1316 }
1317
1318 RETURN_IF_ERR();
1319 RETURN_NONE();
1320}
1321
1322
1323#endif
1324
1325
1326static PyObject*
1327DB_close(DBObject* self, PyObject* args)
1328{
1329 int err, flags=0;
1330 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1331 return NULL;
1332 if (self->db != NULL) {
1333 if (self->myenvobj)
1334 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001335 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001336 self->db = NULL;
1337 RETURN_IF_ERR();
1338 }
1339 RETURN_NONE();
1340}
1341
1342
1343#if (DBVER >= 32)
1344static PyObject*
1345_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1346{
1347 int err, flags=0, type;
1348 PyObject* txnobj = NULL;
1349 PyObject* retval = NULL;
1350 DBT key, data;
1351 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001352 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001353
1354 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1355 &txnobj, &flags))
1356 return NULL;
1357
1358 CHECK_DB_NOT_CLOSED(self);
1359 type = _DB_get_type(self);
1360 if (type == -1)
1361 return NULL;
1362 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001363 PyErr_SetString(PyExc_TypeError,
1364 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001365 return NULL;
1366 }
1367 if (!checkTxnObj(txnobj, &txn))
1368 return NULL;
1369
1370 CLEAR_DBT(key);
1371 CLEAR_DBT(data);
1372 if (CHECK_DBFLAG(self, DB_THREAD)) {
1373 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1374 data.flags = DB_DBT_MALLOC;
1375 key.flags = DB_DBT_MALLOC;
1376 }
1377
1378 MYDB_BEGIN_ALLOW_THREADS;
1379 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1380 MYDB_END_ALLOW_THREADS;
1381
Gregory P. Smithe9477062005-06-04 06:46:59 +00001382 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1383 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001384 err = 0;
1385 Py_INCREF(Py_None);
1386 retval = Py_None;
1387 }
1388 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001389 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1390 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391 FREE_DBT(key);
1392 FREE_DBT(data);
1393 }
1394
1395 RETURN_IF_ERR();
1396 return retval;
1397}
1398
1399static PyObject*
1400DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1401{
1402 return _DB_consume(self, args, kwargs, DB_CONSUME);
1403}
1404
1405static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001406DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1407 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001408{
1409 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1410}
1411#endif
1412
1413
1414
1415static PyObject*
1416DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1417{
1418 int err, flags=0;
1419 DBC* dbc;
1420 PyObject* txnobj = NULL;
1421 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001422 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423
1424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1425 &txnobj, &flags))
1426 return NULL;
1427 CHECK_DB_NOT_CLOSED(self);
1428 if (!checkTxnObj(txnobj, &txn))
1429 return NULL;
1430
1431 MYDB_BEGIN_ALLOW_THREADS;
1432 err = self->db->cursor(self->db, txn, &dbc, flags);
1433 MYDB_END_ALLOW_THREADS;
1434 RETURN_IF_ERR();
1435 return (PyObject*) newDBCursorObject(dbc, self);
1436}
1437
1438
1439static PyObject*
1440DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1441{
1442 PyObject* txnobj = NULL;
1443 int flags = 0;
1444 PyObject* keyobj;
1445 DBT key;
1446 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001447 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001448
1449 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1450 &keyobj, &txnobj, &flags))
1451 return NULL;
1452 CHECK_DB_NOT_CLOSED(self);
1453 if (!make_key_dbt(self, keyobj, &key, NULL))
1454 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001455 if (!checkTxnObj(txnobj, &txn)) {
1456 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001457 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001458 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001459
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001460 if (-1 == _DB_delete(self, txn, &key, 0)) {
1461 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001462 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001463 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464
1465 FREE_DBT(key);
1466 RETURN_NONE();
1467}
1468
1469
1470static PyObject*
1471DB_fd(DBObject* self, PyObject* args)
1472{
1473 int err, the_fd;
1474
1475 if (!PyArg_ParseTuple(args,":fd"))
1476 return NULL;
1477 CHECK_DB_NOT_CLOSED(self);
1478
1479 MYDB_BEGIN_ALLOW_THREADS;
1480 err = self->db->fd(self->db, &the_fd);
1481 MYDB_END_ALLOW_THREADS;
1482 RETURN_IF_ERR();
1483 return PyInt_FromLong(the_fd);
1484}
1485
1486
1487static PyObject*
1488DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1489{
1490 int err, flags=0;
1491 PyObject* txnobj = NULL;
1492 PyObject* keyobj;
1493 PyObject* dfltobj = NULL;
1494 PyObject* retval = NULL;
1495 int dlen = -1;
1496 int doff = -1;
1497 DBT key, data;
1498 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001499 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001500 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001501
1502 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001503 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1504 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505 return NULL;
1506
1507 CHECK_DB_NOT_CLOSED(self);
1508 if (!make_key_dbt(self, keyobj, &key, &flags))
1509 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001510 if (!checkTxnObj(txnobj, &txn)) {
1511 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001513 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001514
1515 CLEAR_DBT(data);
1516 if (CHECK_DBFLAG(self, DB_THREAD)) {
1517 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1518 data.flags = DB_DBT_MALLOC;
1519 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001520 if (!add_partial_dbt(&data, dlen, doff)) {
1521 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001523 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524
1525 MYDB_BEGIN_ALLOW_THREADS;
1526 err = self->db->get(self->db, txn, &key, &data, flags);
1527 MYDB_END_ALLOW_THREADS;
1528
Gregory P. Smithe9477062005-06-04 06:46:59 +00001529 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001530 err = 0;
1531 Py_INCREF(dfltobj);
1532 retval = dfltobj;
1533 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001534 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1535 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536 err = 0;
1537 Py_INCREF(Py_None);
1538 retval = Py_None;
1539 }
1540 else if (!err) {
1541 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001542 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1543 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001544 else /* return just the data */
1545 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001546 FREE_DBT(data);
1547 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001548 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001549
1550 RETURN_IF_ERR();
1551 return retval;
1552}
1553
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001554#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001555static PyObject*
1556DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1557{
1558 int err, flags=0;
1559 PyObject* txnobj = NULL;
1560 PyObject* keyobj;
1561 PyObject* dfltobj = NULL;
1562 PyObject* retval = NULL;
1563 int dlen = -1;
1564 int doff = -1;
1565 DBT key, pkey, data;
1566 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001567 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001568 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001569
1570 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1571 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1572 &doff))
1573 return NULL;
1574
1575 CHECK_DB_NOT_CLOSED(self);
1576 if (!make_key_dbt(self, keyobj, &key, &flags))
1577 return NULL;
1578 if (!checkTxnObj(txnobj, &txn)) {
1579 FREE_DBT(key);
1580 return NULL;
1581 }
1582
1583 CLEAR_DBT(data);
1584 if (CHECK_DBFLAG(self, DB_THREAD)) {
1585 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1586 data.flags = DB_DBT_MALLOC;
1587 }
1588 if (!add_partial_dbt(&data, dlen, doff)) {
1589 FREE_DBT(key);
1590 return NULL;
1591 }
1592
1593 CLEAR_DBT(pkey);
1594 pkey.flags = DB_DBT_MALLOC;
1595
1596 MYDB_BEGIN_ALLOW_THREADS;
1597 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1598 MYDB_END_ALLOW_THREADS;
1599
Gregory P. Smithe9477062005-06-04 06:46:59 +00001600 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001601 err = 0;
1602 Py_INCREF(dfltobj);
1603 retval = dfltobj;
1604 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001605 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1606 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 err = 0;
1608 Py_INCREF(Py_None);
1609 retval = Py_None;
1610 }
1611 else if (!err) {
1612 PyObject *pkeyObj;
1613 PyObject *dataObj;
1614 dataObj = PyString_FromStringAndSize(data.data, data.size);
1615
1616 if (self->primaryDBType == DB_RECNO ||
1617 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001618 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001619 else
1620 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1621
1622 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1623 {
1624 PyObject *keyObj;
1625 int type = _DB_get_type(self);
1626 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001627 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001628 else
1629 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001630#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001631 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001632#else
1633 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1634#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001635 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001636 }
1637 else /* return just the pkey and data */
1638 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001639#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001640 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001641#else
1642 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1643#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001644 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001645 Py_DECREF(dataObj);
1646 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001647 FREE_DBT(pkey);
1648 FREE_DBT(data);
1649 }
1650 FREE_DBT(key);
1651
1652 RETURN_IF_ERR();
1653 return retval;
1654}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001655#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001656
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658/* Return size of entry */
1659static PyObject*
1660DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1661{
1662 int err, flags=0;
1663 PyObject* txnobj = NULL;
1664 PyObject* keyobj;
1665 PyObject* retval = NULL;
1666 DBT key, data;
1667 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001668 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001669
1670 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1671 &keyobj, &txnobj))
1672 return NULL;
1673 CHECK_DB_NOT_CLOSED(self);
1674 if (!make_key_dbt(self, keyobj, &key, &flags))
1675 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001676 if (!checkTxnObj(txnobj, &txn)) {
1677 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001679 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001680 CLEAR_DBT(data);
1681
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001682 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1683 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001684 data.flags = DB_DBT_USERMEM;
1685 data.ulen = 0;
1686 MYDB_BEGIN_ALLOW_THREADS;
1687 err = self->db->get(self->db, txn, &key, &data, flags);
1688 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001689 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 retval = PyInt_FromLong((long)data.size);
1691 err = 0;
1692 }
1693
1694 FREE_DBT(key);
1695 FREE_DBT(data);
1696 RETURN_IF_ERR();
1697 return retval;
1698}
1699
1700
1701static PyObject*
1702DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1703{
1704 int err, flags=0;
1705 PyObject* txnobj = NULL;
1706 PyObject* keyobj;
1707 PyObject* dataobj;
1708 PyObject* retval = NULL;
1709 DBT key, data;
Neal Norwitzdf738022007-05-20 02:14:48 +00001710 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001711 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001712 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713
1714
1715 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1716 &keyobj, &dataobj, &txnobj, &flags))
1717 return NULL;
1718
1719 CHECK_DB_NOT_CLOSED(self);
1720 if (!make_key_dbt(self, keyobj, &key, NULL))
1721 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001722 if ( !make_dbt(dataobj, &data) ||
1723 !checkTxnObj(txnobj, &txn) )
1724 {
1725 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001726 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001727 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728
1729 flags |= DB_GET_BOTH;
Neal Norwitzdf738022007-05-20 02:14:48 +00001730 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001731
1732 if (CHECK_DBFLAG(self, DB_THREAD)) {
1733 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitzdf738022007-05-20 02:14:48 +00001734 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001735 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001736 }
1737
1738 MYDB_BEGIN_ALLOW_THREADS;
1739 err = self->db->get(self->db, txn, &key, &data, flags);
1740 MYDB_END_ALLOW_THREADS;
1741
Gregory P. Smithe9477062005-06-04 06:46:59 +00001742 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1743 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001744 err = 0;
1745 Py_INCREF(Py_None);
1746 retval = Py_None;
1747 }
1748 else if (!err) {
Neal Norwitzdf738022007-05-20 02:14:48 +00001749 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitzdf738022007-05-20 02:14:48 +00001751
1752 /* Even though the flags require DB_DBT_MALLOC, data is not always
1753 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1754 if (data.data != orig_data)
1755 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756 }
1757
1758 FREE_DBT(key);
1759 RETURN_IF_ERR();
1760 return retval;
1761}
1762
1763
1764static PyObject*
1765DB_get_byteswapped(DBObject* self, PyObject* args)
1766{
1767#if (DBVER >= 33)
1768 int err = 0;
1769#endif
1770 int retval = -1;
1771
1772 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1773 return NULL;
1774 CHECK_DB_NOT_CLOSED(self);
1775
1776#if (DBVER >= 33)
1777 MYDB_BEGIN_ALLOW_THREADS;
1778 err = self->db->get_byteswapped(self->db, &retval);
1779 MYDB_END_ALLOW_THREADS;
1780 RETURN_IF_ERR();
1781#else
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 retval = self->db->get_byteswapped(self->db);
1784 MYDB_END_ALLOW_THREADS;
1785#endif
1786 return PyInt_FromLong(retval);
1787}
1788
1789
1790static PyObject*
1791DB_get_type(DBObject* self, PyObject* args)
1792{
1793 int type;
1794
1795 if (!PyArg_ParseTuple(args,":get_type"))
1796 return NULL;
1797 CHECK_DB_NOT_CLOSED(self);
1798
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001800 if (type == -1)
1801 return NULL;
1802 return PyInt_FromLong(type);
1803}
1804
1805
1806static PyObject*
1807DB_join(DBObject* self, PyObject* args)
1808{
1809 int err, flags=0;
1810 int length, x;
1811 PyObject* cursorsObj;
1812 DBC** cursors;
1813 DBC* dbc;
1814
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001815 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1816 return NULL;
1817
1818 CHECK_DB_NOT_CLOSED(self);
1819
1820 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001821 PyErr_SetString(PyExc_TypeError,
1822 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 return NULL;
1824 }
1825
1826 length = PyObject_Length(cursorsObj);
1827 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001828 if (!cursors) {
1829 PyErr_NoMemory();
1830 return NULL;
1831 }
1832
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 cursors[length] = NULL;
1834 for (x=0; x<length; x++) {
1835 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001836 if (item == NULL) {
1837 free(cursors);
1838 return NULL;
1839 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001840 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001841 PyErr_SetString(PyExc_TypeError,
1842 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001843 free(cursors);
1844 return NULL;
1845 }
1846 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001847 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 }
1849
1850 MYDB_BEGIN_ALLOW_THREADS;
1851 err = self->db->join(self->db, cursors, &dbc, flags);
1852 MYDB_END_ALLOW_THREADS;
1853 free(cursors);
1854 RETURN_IF_ERR();
1855
Gregory P. Smith7441e652003-11-03 21:35:31 +00001856 /* FIXME: this is a buggy interface. The returned cursor
1857 contains internal references to the passed in cursors
1858 but does not hold python references to them or prevent
1859 them from being closed prematurely. This can cause
1860 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 return (PyObject*) newDBCursorObject(dbc, self);
1862}
1863
1864
1865static PyObject*
1866DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1867{
1868 int err, flags=0;
1869 PyObject* txnobj = NULL;
1870 PyObject* keyobj;
1871 DBT key;
1872 DB_TXN *txn = NULL;
1873 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001874 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875
1876 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1877 &keyobj, &txnobj, &flags))
1878 return NULL;
1879 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001880 if (!make_dbt(keyobj, &key))
1881 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001882 return NULL;
1883 if (!checkTxnObj(txnobj, &txn))
1884 return NULL;
1885
1886 MYDB_BEGIN_ALLOW_THREADS;
1887 err = self->db->key_range(self->db, txn, &key, &range, flags);
1888 MYDB_END_ALLOW_THREADS;
1889
1890 RETURN_IF_ERR();
1891 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1892}
1893
1894
1895static PyObject*
1896DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1897{
1898 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1899 char* filename = NULL;
1900 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001901#if (DBVER >= 41)
1902 PyObject *txnobj = NULL;
1903 DB_TXN *txn = NULL;
1904 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001905 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001906 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1907 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001908 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001909 "filename", "dbtype", "flags", "mode", "txn", NULL};
1910#else
1911 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001912 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001913 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1914 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001915 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001916 "filename", "dbtype", "flags", "mode", NULL};
1917#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001918
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001919#if (DBVER >= 41)
1920 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1921 &filename, &dbname, &type, &flags, &mode,
1922 &txnobj))
1923#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001925 &filename, &dbname, &type, &flags,
1926 &mode))
1927#endif
1928 {
1929 PyErr_Clear();
1930 type = DB_UNKNOWN; flags = 0; mode = 0660;
1931 filename = NULL; dbname = NULL;
1932#if (DBVER >= 41)
1933 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1934 kwnames_basic,
1935 &filename, &type, &flags, &mode,
1936 &txnobj))
1937 return NULL;
1938#else
1939 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1940 kwnames_basic,
1941 &filename, &type, &flags, &mode))
1942 return NULL;
1943#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 }
1945
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946#if (DBVER >= 41)
1947 if (!checkTxnObj(txnobj, &txn)) return NULL;
1948#endif
1949
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001951 PyObject *t = Py_BuildValue("(is)", 0,
1952 "Cannot call open() twice for DB object");
1953 PyErr_SetObject(DBError, t);
1954 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001955 return NULL;
1956 }
1957
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001958#if 0 && (DBVER >= 41)
1959 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1960 && (self->myenvobj->flags & DB_INIT_TXN))
1961 {
1962 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1963 * explicitly passed) but we are in a transaction ready environment:
1964 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1965 * to work on BerkeleyDB 4.1 without needing to modify their
1966 * DBEnv or DB open calls.
1967 * TODO make this behaviour of the library configurable.
1968 */
1969 flags |= DB_AUTO_COMMIT;
1970 }
1971#endif
1972
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001973 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001974#if (DBVER >= 41)
1975 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1976#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001977 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001978#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979 MYDB_END_ALLOW_THREADS;
1980 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001981 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001982 self->db = NULL;
1983 return NULL;
1984 }
1985
1986 self->flags = flags;
1987 RETURN_NONE();
1988}
1989
1990
1991static PyObject*
1992DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1993{
1994 int flags=0;
1995 PyObject* txnobj = NULL;
1996 int dlen = -1;
1997 int doff = -1;
1998 PyObject* keyobj, *dataobj, *retval;
1999 DBT key, data;
2000 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002001 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002002 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002003
2004 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2005 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2006 return NULL;
2007
2008 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002009 if (!make_key_dbt(self, keyobj, &key, NULL))
2010 return NULL;
2011 if ( !make_dbt(dataobj, &data) ||
2012 !add_partial_dbt(&data, dlen, doff) ||
2013 !checkTxnObj(txnobj, &txn) )
2014 {
2015 FREE_DBT(key);
2016 return NULL;
2017 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002018
2019 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2020 FREE_DBT(key);
2021 return NULL;
2022 }
2023
2024 if (flags & DB_APPEND)
2025 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2026 else {
2027 retval = Py_None;
2028 Py_INCREF(retval);
2029 }
2030 FREE_DBT(key);
2031 return retval;
2032}
2033
2034
2035
2036static PyObject*
2037DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2038{
2039 char* filename;
2040 char* database = NULL;
2041 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002042 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002043
2044 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2045 &filename, &database, &flags))
2046 return NULL;
2047 CHECK_DB_NOT_CLOSED(self);
2048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002049 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002050 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051 RETURN_IF_ERR();
2052 RETURN_NONE();
2053}
2054
2055
2056
2057static PyObject*
2058DB_rename(DBObject* self, PyObject* args)
2059{
2060 char* filename;
2061 char* database;
2062 char* newname;
2063 int err, flags=0;
2064
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002065 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2066 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002067 return NULL;
2068 CHECK_DB_NOT_CLOSED(self);
2069
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->rename(self->db, filename, database, newname, flags);
2072 MYDB_END_ALLOW_THREADS;
2073 RETURN_IF_ERR();
2074 RETURN_NONE();
2075}
2076
2077
2078static PyObject*
2079DB_set_bt_minkey(DBObject* self, PyObject* args)
2080{
2081 int err, minkey;
2082
2083 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2084 return NULL;
2085 CHECK_DB_NOT_CLOSED(self);
2086
2087 MYDB_BEGIN_ALLOW_THREADS;
2088 err = self->db->set_bt_minkey(self->db, minkey);
2089 MYDB_END_ALLOW_THREADS;
2090 RETURN_IF_ERR();
2091 RETURN_NONE();
2092}
2093
Neal Norwitz84562352005-10-20 04:30:15 +00002094#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002095static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002096_default_cmp(const DBT *leftKey,
2097 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002098{
2099 int res;
2100 int lsize = leftKey->size, rsize = rightKey->size;
2101
Georg Brandlef1701f2006-03-07 14:57:48 +00002102 res = memcmp(leftKey->data, rightKey->data,
2103 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104
2105 if (res == 0) {
2106 if (lsize < rsize) {
2107 res = -1;
2108 }
2109 else if (lsize > rsize) {
2110 res = 1;
2111 }
2112 }
2113 return res;
2114}
2115
2116static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002117_db_compareCallback(DB* db,
2118 const DBT *leftKey,
2119 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120{
2121 int res = 0;
2122 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002123 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125
2126 if (self == NULL || self->btCompareCallback == NULL) {
2127 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 PyErr_SetString(PyExc_TypeError,
2129 (self == 0
2130 ? "DB_bt_compare db is NULL."
2131 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002132 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 PyErr_Print();
2134 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002135 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002136 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002137 MYDB_BEGIN_BLOCK_THREADS;
2138
Thomas Woutersb3153832006-03-08 01:47:19 +00002139 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2140 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002141 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002142 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002143 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002144 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002145 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002146 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002147 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 PyErr_Print();
2149 res = _default_cmp(leftKey, rightKey);
2150 } else if (PyInt_Check(result)) {
2151 res = PyInt_AsLong(result);
2152 } else {
2153 PyErr_SetString(PyExc_TypeError,
2154 "DB_bt_compare callback MUST return an int.");
2155 /* we're in a callback within the DB code, we can't raise */
2156 PyErr_Print();
2157 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158 }
2159
Thomas Woutersb3153832006-03-08 01:47:19 +00002160 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002161 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162
2163 MYDB_END_BLOCK_THREADS;
2164 }
2165 return res;
2166}
2167
2168static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002169DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002170{
2171 int err;
2172 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002173 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002174
Georg Brandlef1701f2006-03-07 14:57:48 +00002175 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002176 return NULL;
2177
Georg Brandlef1701f2006-03-07 14:57:48 +00002178 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002179
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 if (!PyCallable_Check(comparator)) {
2181 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182 return NULL;
2183 }
2184
2185 /*
2186 * Perform a test call of the comparator function with two empty
2187 * string objects here. verify that it returns an int (0).
2188 * err if not.
2189 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002190 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002191 result = PyEval_CallObject(comparator, tuple);
2192 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002193 if (result == NULL)
2194 return NULL;
2195 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002196 PyErr_SetString(PyExc_TypeError,
2197 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002198 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002199 } else if (PyInt_AsLong(result) != 0) {
2200 PyErr_SetString(PyExc_TypeError,
2201 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002202 return NULL;
2203 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002204 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002205
2206 /* We don't accept multiple set_bt_compare operations, in order to
2207 * simplify the code. This would have no real use, as one cannot
2208 * change the function once the db is opened anyway */
2209 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002210 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211 return NULL;
2212 }
2213
Georg Brandlef1701f2006-03-07 14:57:48 +00002214 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002215 self->btCompareCallback = comparator;
2216
2217 /* This is to workaround a problem with un-initialized threads (see
2218 comment in DB_associate) */
2219#ifdef WITH_THREAD
2220 PyEval_InitThreads();
2221#endif
2222
Thomas Woutersb3153832006-03-08 01:47:19 +00002223 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002224
2225 if (err) {
2226 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002227 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002228 self->btCompareCallback = NULL;
2229 }
2230
Georg Brandlef1701f2006-03-07 14:57:48 +00002231 RETURN_IF_ERR();
2232 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002233}
Neal Norwitz84562352005-10-20 04:30:15 +00002234#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002235
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002236
2237static PyObject*
2238DB_set_cachesize(DBObject* self, PyObject* args)
2239{
2240 int err;
2241 int gbytes = 0, bytes = 0, ncache = 0;
2242
2243 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2244 &gbytes,&bytes,&ncache))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252 RETURN_NONE();
2253}
2254
2255
2256static PyObject*
2257DB_set_flags(DBObject* self, PyObject* args)
2258{
2259 int err, flags;
2260
2261 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2262 return NULL;
2263 CHECK_DB_NOT_CLOSED(self);
2264
2265 MYDB_BEGIN_ALLOW_THREADS;
2266 err = self->db->set_flags(self->db, flags);
2267 MYDB_END_ALLOW_THREADS;
2268 RETURN_IF_ERR();
2269
2270 self->setflags |= flags;
2271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
2276DB_set_h_ffactor(DBObject* self, PyObject* args)
2277{
2278 int err, ffactor;
2279
2280 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_h_ffactor(self->db, ffactor);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
2291
2292static PyObject*
2293DB_set_h_nelem(DBObject* self, PyObject* args)
2294{
2295 int err, nelem;
2296
2297 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2298 return NULL;
2299 CHECK_DB_NOT_CLOSED(self);
2300
2301 MYDB_BEGIN_ALLOW_THREADS;
2302 err = self->db->set_h_nelem(self->db, nelem);
2303 MYDB_END_ALLOW_THREADS;
2304 RETURN_IF_ERR();
2305 RETURN_NONE();
2306}
2307
2308
2309static PyObject*
2310DB_set_lorder(DBObject* self, PyObject* args)
2311{
2312 int err, lorder;
2313
2314 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2315 return NULL;
2316 CHECK_DB_NOT_CLOSED(self);
2317
2318 MYDB_BEGIN_ALLOW_THREADS;
2319 err = self->db->set_lorder(self->db, lorder);
2320 MYDB_END_ALLOW_THREADS;
2321 RETURN_IF_ERR();
2322 RETURN_NONE();
2323}
2324
2325
2326static PyObject*
2327DB_set_pagesize(DBObject* self, PyObject* args)
2328{
2329 int err, pagesize;
2330
2331 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2332 return NULL;
2333 CHECK_DB_NOT_CLOSED(self);
2334
2335 MYDB_BEGIN_ALLOW_THREADS;
2336 err = self->db->set_pagesize(self->db, pagesize);
2337 MYDB_END_ALLOW_THREADS;
2338 RETURN_IF_ERR();
2339 RETURN_NONE();
2340}
2341
2342
2343static PyObject*
2344DB_set_re_delim(DBObject* self, PyObject* args)
2345{
2346 int err;
2347 char delim;
2348
2349 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2350 PyErr_Clear();
2351 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2352 return NULL;
2353 }
2354
2355 CHECK_DB_NOT_CLOSED(self);
2356
2357 MYDB_BEGIN_ALLOW_THREADS;
2358 err = self->db->set_re_delim(self->db, delim);
2359 MYDB_END_ALLOW_THREADS;
2360 RETURN_IF_ERR();
2361 RETURN_NONE();
2362}
2363
2364static PyObject*
2365DB_set_re_len(DBObject* self, PyObject* args)
2366{
2367 int err, len;
2368
2369 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2370 return NULL;
2371 CHECK_DB_NOT_CLOSED(self);
2372
2373 MYDB_BEGIN_ALLOW_THREADS;
2374 err = self->db->set_re_len(self->db, len);
2375 MYDB_END_ALLOW_THREADS;
2376 RETURN_IF_ERR();
2377 RETURN_NONE();
2378}
2379
2380
2381static PyObject*
2382DB_set_re_pad(DBObject* self, PyObject* args)
2383{
2384 int err;
2385 char pad;
2386
2387 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2388 PyErr_Clear();
2389 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2390 return NULL;
2391 }
2392 CHECK_DB_NOT_CLOSED(self);
2393
2394 MYDB_BEGIN_ALLOW_THREADS;
2395 err = self->db->set_re_pad(self->db, pad);
2396 MYDB_END_ALLOW_THREADS;
2397 RETURN_IF_ERR();
2398 RETURN_NONE();
2399}
2400
2401
2402static PyObject*
2403DB_set_re_source(DBObject* self, PyObject* args)
2404{
2405 int err;
2406 char *re_source;
2407
2408 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2409 return NULL;
2410 CHECK_DB_NOT_CLOSED(self);
2411
2412 MYDB_BEGIN_ALLOW_THREADS;
2413 err = self->db->set_re_source(self->db, re_source);
2414 MYDB_END_ALLOW_THREADS;
2415 RETURN_IF_ERR();
2416 RETURN_NONE();
2417}
2418
2419
2420#if (DBVER >= 32)
2421static PyObject*
2422DB_set_q_extentsize(DBObject* self, PyObject* args)
2423{
2424 int err;
2425 int extentsize;
2426
2427 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2428 return NULL;
2429 CHECK_DB_NOT_CLOSED(self);
2430
2431 MYDB_BEGIN_ALLOW_THREADS;
2432 err = self->db->set_q_extentsize(self->db, extentsize);
2433 MYDB_END_ALLOW_THREADS;
2434 RETURN_IF_ERR();
2435 RETURN_NONE();
2436}
2437#endif
2438
2439static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002440DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441{
2442 int err, flags = 0, type;
2443 void* sp;
2444 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002445#if (DBVER >= 43)
2446 PyObject* txnobj = NULL;
2447 DB_TXN *txn = NULL;
Gregory P. Smith6fed7932006-09-30 06:05:07 +00002448 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002449#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002450 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002452
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002453#if (DBVER >= 43)
2454 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2455 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002456 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002457 if (!checkTxnObj(txnobj, &txn))
2458 return NULL;
2459#else
2460 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2461 return NULL;
2462#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002463 CHECK_DB_NOT_CLOSED(self);
2464
2465 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002466#if (DBVER >= 43)
2467 err = self->db->stat(self->db, txn, &sp, flags);
2468#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002469 err = self->db->stat(self->db, &sp, flags);
2470#else
2471 err = self->db->stat(self->db, &sp, NULL, flags);
2472#endif
2473 MYDB_END_ALLOW_THREADS;
2474 RETURN_IF_ERR();
2475
2476 self->haveStat = 1;
2477
2478 /* Turn the stat structure into a dictionary */
2479 type = _DB_get_type(self);
2480 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2481 free(sp);
2482 return NULL;
2483 }
2484
2485#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2486#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2487#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2488
2489 switch (type) {
2490 case DB_HASH:
2491 MAKE_HASH_ENTRY(magic);
2492 MAKE_HASH_ENTRY(version);
2493 MAKE_HASH_ENTRY(nkeys);
2494 MAKE_HASH_ENTRY(ndata);
2495 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002496#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002497 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002499 MAKE_HASH_ENTRY(ffactor);
2500 MAKE_HASH_ENTRY(buckets);
2501 MAKE_HASH_ENTRY(free);
2502 MAKE_HASH_ENTRY(bfree);
2503 MAKE_HASH_ENTRY(bigpages);
2504 MAKE_HASH_ENTRY(big_bfree);
2505 MAKE_HASH_ENTRY(overflows);
2506 MAKE_HASH_ENTRY(ovfl_free);
2507 MAKE_HASH_ENTRY(dup);
2508 MAKE_HASH_ENTRY(dup_free);
2509 break;
2510
2511 case DB_BTREE:
2512 case DB_RECNO:
2513 MAKE_BT_ENTRY(magic);
2514 MAKE_BT_ENTRY(version);
2515 MAKE_BT_ENTRY(nkeys);
2516 MAKE_BT_ENTRY(ndata);
2517 MAKE_BT_ENTRY(pagesize);
2518 MAKE_BT_ENTRY(minkey);
2519 MAKE_BT_ENTRY(re_len);
2520 MAKE_BT_ENTRY(re_pad);
2521 MAKE_BT_ENTRY(levels);
2522 MAKE_BT_ENTRY(int_pg);
2523 MAKE_BT_ENTRY(leaf_pg);
2524 MAKE_BT_ENTRY(dup_pg);
2525 MAKE_BT_ENTRY(over_pg);
2526 MAKE_BT_ENTRY(free);
2527 MAKE_BT_ENTRY(int_pgfree);
2528 MAKE_BT_ENTRY(leaf_pgfree);
2529 MAKE_BT_ENTRY(dup_pgfree);
2530 MAKE_BT_ENTRY(over_pgfree);
2531 break;
2532
2533 case DB_QUEUE:
2534 MAKE_QUEUE_ENTRY(magic);
2535 MAKE_QUEUE_ENTRY(version);
2536 MAKE_QUEUE_ENTRY(nkeys);
2537 MAKE_QUEUE_ENTRY(ndata);
2538 MAKE_QUEUE_ENTRY(pagesize);
2539 MAKE_QUEUE_ENTRY(pages);
2540 MAKE_QUEUE_ENTRY(re_len);
2541 MAKE_QUEUE_ENTRY(re_pad);
2542 MAKE_QUEUE_ENTRY(pgfree);
2543#if (DBVER == 31)
2544 MAKE_QUEUE_ENTRY(start);
2545#endif
2546 MAKE_QUEUE_ENTRY(first_recno);
2547 MAKE_QUEUE_ENTRY(cur_recno);
2548 break;
2549
2550 default:
2551 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2552 Py_DECREF(d);
2553 d = NULL;
2554 }
2555
2556#undef MAKE_HASH_ENTRY
2557#undef MAKE_BT_ENTRY
2558#undef MAKE_QUEUE_ENTRY
2559
2560 free(sp);
2561 return d;
2562}
2563
2564static PyObject*
2565DB_sync(DBObject* self, PyObject* args)
2566{
2567 int err;
2568 int flags = 0;
2569
2570 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2571 return NULL;
2572 CHECK_DB_NOT_CLOSED(self);
2573
2574 MYDB_BEGIN_ALLOW_THREADS;
2575 err = self->db->sync(self->db, flags);
2576 MYDB_END_ALLOW_THREADS;
2577 RETURN_IF_ERR();
2578 RETURN_NONE();
2579}
2580
2581
2582#if (DBVER >= 33)
2583static PyObject*
2584DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2585{
2586 int err, flags=0;
2587 u_int32_t count=0;
2588 PyObject* txnobj = NULL;
2589 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002590 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002591
2592 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2593 &txnobj, &flags))
2594 return NULL;
2595 CHECK_DB_NOT_CLOSED(self);
2596 if (!checkTxnObj(txnobj, &txn))
2597 return NULL;
2598
2599 MYDB_BEGIN_ALLOW_THREADS;
2600 err = self->db->truncate(self->db, txn, &count, flags);
2601 MYDB_END_ALLOW_THREADS;
2602 RETURN_IF_ERR();
2603 return PyInt_FromLong(count);
2604}
2605#endif
2606
2607
2608static PyObject*
2609DB_upgrade(DBObject* self, PyObject* args)
2610{
2611 int err, flags=0;
2612 char *filename;
2613
2614 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2615 return NULL;
2616 CHECK_DB_NOT_CLOSED(self);
2617
2618 MYDB_BEGIN_ALLOW_THREADS;
2619 err = self->db->upgrade(self->db, filename, flags);
2620 MYDB_END_ALLOW_THREADS;
2621 RETURN_IF_ERR();
2622 RETURN_NONE();
2623}
2624
2625
2626static PyObject*
2627DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2628{
2629 int err, flags=0;
2630 char* fileName;
2631 char* dbName=NULL;
2632 char* outFileName=NULL;
2633 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002634 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002635 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636
2637 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2638 &fileName, &dbName, &outFileName, &flags))
2639 return NULL;
2640
2641 CHECK_DB_NOT_CLOSED(self);
2642 if (outFileName)
2643 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002644 /* XXX(nnorwitz): it should probably be an exception if outFile
2645 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002646
2647 MYDB_BEGIN_ALLOW_THREADS;
2648 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2649 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002650 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002652
2653 /* DB.verify acts as a DB handle destructor (like close); this was
2654 * documented in BerkeleyDB 4.2 but had the undocumented effect
2655 * of not being safe in prior versions while still requiring an explicit
2656 * DB.close call afterwards. Lets call close for the user to emulate
2657 * the safe 4.2 behaviour. */
2658#if (DBVER <= 41)
2659 self->db->close(self->db, 0);
2660#endif
2661 self->db = NULL;
2662
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002663 RETURN_IF_ERR();
2664 RETURN_NONE();
2665}
2666
2667
2668static PyObject*
2669DB_set_get_returns_none(DBObject* self, PyObject* args)
2670{
2671 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002672 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002673
2674 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2675 return NULL;
2676 CHECK_DB_NOT_CLOSED(self);
2677
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002678 if (self->moduleFlags.getReturnsNone)
2679 ++oldValue;
2680 if (self->moduleFlags.cursorSetReturnsNone)
2681 ++oldValue;
2682 self->moduleFlags.getReturnsNone = (flags >= 1);
2683 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002684 return PyInt_FromLong(oldValue);
2685}
2686
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002687#if (DBVER >= 41)
2688static PyObject*
2689DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2690{
2691 int err;
2692 u_int32_t flags=0;
2693 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002694 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002695
2696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2697 &passwd, &flags)) {
2698 return NULL;
2699 }
2700
2701 MYDB_BEGIN_ALLOW_THREADS;
2702 err = self->db->set_encrypt(self->db, passwd, flags);
2703 MYDB_END_ALLOW_THREADS;
2704
2705 RETURN_IF_ERR();
2706 RETURN_NONE();
2707}
2708#endif /* DBVER >= 41 */
2709
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710
2711/*-------------------------------------------------------------- */
2712/* Mapping and Dictionary-like access routines */
2713
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002714Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002715{
2716 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002717 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002718 int flags = 0;
2719 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002720 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721
2722 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002723 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2724 PyErr_SetObject(DBError, t);
2725 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726 return -1;
2727 }
2728
2729 if (self->haveStat) { /* Has the stat function been called recently? If
2730 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002731 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732 }
2733
2734 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002735redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002736#if (DBVER >= 43)
2737 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2738#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002739 err = self->db->stat(self->db, &sp, flags);
2740#else
2741 err = self->db->stat(self->db, &sp, NULL, flags);
2742#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002743
2744 /* All the stat structures have matching fields upto the ndata field,
2745 so we can use any of them for the type cast */
2746 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2747
2748 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2749 * redo a full stat to make sure.
2750 * Fixes SF python bug 1493322, pybsddb bug 1184012
2751 */
2752 if (size == 0 && (flags & DB_FAST_STAT)) {
2753 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002754 if (!err)
2755 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002756 goto redo_stat_for_length;
2757 }
2758
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002759 MYDB_END_ALLOW_THREADS;
2760
2761 if (err)
2762 return -1;
2763
2764 self->haveStat = 1;
2765
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002766 free(sp);
2767 return size;
2768}
2769
2770
2771PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2772{
2773 int err;
2774 PyObject* retval;
2775 DBT key;
2776 DBT data;
2777
2778 CHECK_DB_NOT_CLOSED(self);
2779 if (!make_key_dbt(self, keyobj, &key, NULL))
2780 return NULL;
2781
2782 CLEAR_DBT(data);
2783 if (CHECK_DBFLAG(self, DB_THREAD)) {
2784 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2785 data.flags = DB_DBT_MALLOC;
2786 }
2787 MYDB_BEGIN_ALLOW_THREADS;
2788 err = self->db->get(self->db, NULL, &key, &data, 0);
2789 MYDB_END_ALLOW_THREADS;
2790 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2791 PyErr_SetObject(PyExc_KeyError, keyobj);
2792 retval = NULL;
2793 }
2794 else if (makeDBError(err)) {
2795 retval = NULL;
2796 }
2797 else {
2798 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2799 FREE_DBT(data);
2800 }
2801
2802 FREE_DBT(key);
2803 return retval;
2804}
2805
2806
2807static int
2808DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2809{
2810 DBT key, data;
2811 int retval;
2812 int flags = 0;
2813
2814 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002815 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2816 PyErr_SetObject(DBError, t);
2817 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002818 return -1;
2819 }
2820
2821 if (!make_key_dbt(self, keyobj, &key, NULL))
2822 return -1;
2823
2824 if (dataobj != NULL) {
2825 if (!make_dbt(dataobj, &data))
2826 retval = -1;
2827 else {
2828 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002829 /* dictionaries shouldn't have duplicate keys */
2830 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002831 retval = _DB_put(self, NULL, &key, &data, flags);
2832
2833 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002834 /* try deleting any old record that matches and then PUT it
2835 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836 _DB_delete(self, NULL, &key, 0);
2837 PyErr_Clear();
2838 retval = _DB_put(self, NULL, &key, &data, flags);
2839 }
2840 }
2841 }
2842 else {
2843 /* dataobj == NULL, so delete the key */
2844 retval = _DB_delete(self, NULL, &key, 0);
2845 }
2846 FREE_DBT(key);
2847 return retval;
2848}
2849
2850
2851static PyObject*
2852DB_has_key(DBObject* self, PyObject* args)
2853{
2854 int err;
2855 PyObject* keyobj;
2856 DBT key, data;
2857 PyObject* txnobj = NULL;
2858 DB_TXN *txn = NULL;
2859
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002860 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 return NULL;
2862 CHECK_DB_NOT_CLOSED(self);
2863 if (!make_key_dbt(self, keyobj, &key, NULL))
2864 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002865 if (!checkTxnObj(txnobj, &txn)) {
2866 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002867 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002868 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002870 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002871 it has a record but can't allocate a buffer for the data. This saves
2872 having to deal with data we won't be using.
2873 */
2874 CLEAR_DBT(data);
2875 data.flags = DB_DBT_USERMEM;
2876
2877 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002878 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879 MYDB_END_ALLOW_THREADS;
2880 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002881
2882 if (err == DB_BUFFER_SMALL || err == 0) {
2883 return PyInt_FromLong(1);
2884 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2885 return PyInt_FromLong(0);
2886 }
2887
2888 makeDBError(err);
2889 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002890}
2891
2892
2893#define _KEYS_LIST 1
2894#define _VALUES_LIST 2
2895#define _ITEMS_LIST 3
2896
2897static PyObject*
2898_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2899{
2900 int err, dbtype;
2901 DBT key;
2902 DBT data;
2903 DBC *cursor;
2904 PyObject* list;
2905 PyObject* item = NULL;
2906
2907 CHECK_DB_NOT_CLOSED(self);
2908 CLEAR_DBT(key);
2909 CLEAR_DBT(data);
2910
2911 dbtype = _DB_get_type(self);
2912 if (dbtype == -1)
2913 return NULL;
2914
2915 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002916 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002917 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002918
2919 /* get a cursor */
2920 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002921 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002922 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002923 if (makeDBError(err)) {
2924 Py_DECREF(list);
2925 return NULL;
2926 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927
2928 if (CHECK_DBFLAG(self, DB_THREAD)) {
2929 key.flags = DB_DBT_REALLOC;
2930 data.flags = DB_DBT_REALLOC;
2931 }
2932
2933 while (1) { /* use the cursor to traverse the DB, collecting items */
2934 MYDB_BEGIN_ALLOW_THREADS;
2935 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2936 MYDB_END_ALLOW_THREADS;
2937
2938 if (err) {
2939 /* for any error, break out of the loop */
2940 break;
2941 }
2942
2943 switch (type) {
2944 case _KEYS_LIST:
2945 switch(dbtype) {
2946 case DB_BTREE:
2947 case DB_HASH:
2948 default:
2949 item = PyString_FromStringAndSize((char*)key.data, key.size);
2950 break;
2951 case DB_RECNO:
2952 case DB_QUEUE:
2953 item = PyInt_FromLong(*((db_recno_t*)key.data));
2954 break;
2955 }
2956 break;
2957
2958 case _VALUES_LIST:
2959 item = PyString_FromStringAndSize((char*)data.data, data.size);
2960 break;
2961
2962 case _ITEMS_LIST:
2963 switch(dbtype) {
2964 case DB_BTREE:
2965 case DB_HASH:
2966 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002967 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2968 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002969 break;
2970 case DB_RECNO:
2971 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002972 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2973 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002974 break;
2975 }
2976 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002977 default:
2978 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2979 item = NULL;
2980 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002981 }
2982 if (item == NULL) {
2983 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002984 list = NULL;
2985 goto done;
2986 }
2987 PyList_Append(list, item);
2988 Py_DECREF(item);
2989 }
2990
Gregory P. Smithe9477062005-06-04 06:46:59 +00002991 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2992 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002993 Py_DECREF(list);
2994 list = NULL;
2995 }
2996
2997 done:
2998 FREE_DBT(key);
2999 FREE_DBT(data);
3000 MYDB_BEGIN_ALLOW_THREADS;
3001 cursor->c_close(cursor);
3002 MYDB_END_ALLOW_THREADS;
3003 return list;
3004}
3005
3006
3007static PyObject*
3008DB_keys(DBObject* self, PyObject* args)
3009{
3010 PyObject* txnobj = NULL;
3011 DB_TXN *txn = NULL;
3012
Georg Brandl96a8c392006-05-29 21:04:52 +00003013 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003014 return NULL;
3015 if (!checkTxnObj(txnobj, &txn))
3016 return NULL;
3017 return _DB_make_list(self, txn, _KEYS_LIST);
3018}
3019
3020
3021static PyObject*
3022DB_items(DBObject* self, PyObject* args)
3023{
3024 PyObject* txnobj = NULL;
3025 DB_TXN *txn = NULL;
3026
Georg Brandl96a8c392006-05-29 21:04:52 +00003027 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 return NULL;
3029 if (!checkTxnObj(txnobj, &txn))
3030 return NULL;
3031 return _DB_make_list(self, txn, _ITEMS_LIST);
3032}
3033
3034
3035static PyObject*
3036DB_values(DBObject* self, PyObject* args)
3037{
3038 PyObject* txnobj = NULL;
3039 DB_TXN *txn = NULL;
3040
Georg Brandl96a8c392006-05-29 21:04:52 +00003041 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003042 return NULL;
3043 if (!checkTxnObj(txnobj, &txn))
3044 return NULL;
3045 return _DB_make_list(self, txn, _VALUES_LIST);
3046}
3047
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003048/* --------------------------------------------------------------------- */
3049/* DBCursor methods */
3050
3051
3052static PyObject*
3053DBC_close(DBCursorObject* self, PyObject* args)
3054{
3055 int err = 0;
3056
3057 if (!PyArg_ParseTuple(args, ":close"))
3058 return NULL;
3059
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 if (self->dbc != NULL) {
3061 MYDB_BEGIN_ALLOW_THREADS;
3062 err = self->dbc->c_close(self->dbc);
3063 self->dbc = NULL;
3064 MYDB_END_ALLOW_THREADS;
3065 }
3066 RETURN_IF_ERR();
3067 RETURN_NONE();
3068}
3069
3070
3071static PyObject*
3072DBC_count(DBCursorObject* self, PyObject* args)
3073{
3074 int err = 0;
3075 db_recno_t count;
3076 int flags = 0;
3077
3078 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3079 return NULL;
3080
3081 CHECK_CURSOR_NOT_CLOSED(self);
3082
3083 MYDB_BEGIN_ALLOW_THREADS;
3084 err = self->dbc->c_count(self->dbc, &count, flags);
3085 MYDB_END_ALLOW_THREADS;
3086 RETURN_IF_ERR();
3087
3088 return PyInt_FromLong(count);
3089}
3090
3091
3092static PyObject*
3093DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3094{
3095 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3096}
3097
3098
3099static PyObject*
3100DBC_delete(DBCursorObject* self, PyObject* args)
3101{
3102 int err, flags=0;
3103
3104 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3105 return NULL;
3106
3107 CHECK_CURSOR_NOT_CLOSED(self);
3108
3109 MYDB_BEGIN_ALLOW_THREADS;
3110 err = self->dbc->c_del(self->dbc, flags);
3111 MYDB_END_ALLOW_THREADS;
3112 RETURN_IF_ERR();
3113
3114 self->mydb->haveStat = 0;
3115 RETURN_NONE();
3116}
3117
3118
3119static PyObject*
3120DBC_dup(DBCursorObject* self, PyObject* args)
3121{
3122 int err, flags =0;
3123 DBC* dbc = NULL;
3124
3125 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3126 return NULL;
3127
3128 CHECK_CURSOR_NOT_CLOSED(self);
3129
3130 MYDB_BEGIN_ALLOW_THREADS;
3131 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3132 MYDB_END_ALLOW_THREADS;
3133 RETURN_IF_ERR();
3134
3135 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3136}
3137
3138static PyObject*
3139DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3140{
3141 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3142}
3143
3144
3145static PyObject*
3146DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3147{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003148 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149 PyObject* keyobj = NULL;
3150 PyObject* dataobj = NULL;
3151 PyObject* retval = NULL;
3152 int dlen = -1;
3153 int doff = -1;
3154 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003155 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003156 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157
3158 CLEAR_DBT(key);
3159 CLEAR_DBT(data);
3160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003161 &flags, &dlen, &doff))
3162 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3165 &kwnames[1],
3166 &keyobj, &flags, &dlen, &doff))
3167 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003169 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3170 kwnames, &keyobj, &dataobj,
3171 &flags, &dlen, &doff))
3172 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 return NULL;
3174 }
3175 }
3176 }
3177
3178 CHECK_CURSOR_NOT_CLOSED(self);
3179
3180 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3181 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003182 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3183 (!add_partial_dbt(&data, dlen, doff)) )
3184 {
3185 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003187 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188
3189 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3190 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003191 if (!(key.flags & DB_DBT_REALLOC)) {
3192 key.flags |= DB_DBT_MALLOC;
3193 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194 }
3195
3196 MYDB_BEGIN_ALLOW_THREADS;
3197 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3198 MYDB_END_ALLOW_THREADS;
3199
Gregory P. Smithe9477062005-06-04 06:46:59 +00003200 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3201 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003202 Py_INCREF(Py_None);
3203 retval = Py_None;
3204 }
3205 else if (makeDBError(err)) {
3206 retval = NULL;
3207 }
3208 else {
3209 switch (_DB_get_type(self->mydb)) {
3210 case -1:
3211 retval = NULL;
3212 break;
3213 case DB_BTREE:
3214 case DB_HASH:
3215 default:
3216 retval = Py_BuildValue("s#s#", key.data, key.size,
3217 data.data, data.size);
3218 break;
3219 case DB_RECNO:
3220 case DB_QUEUE:
3221 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3222 data.data, data.size);
3223 break;
3224 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225 FREE_DBT(data);
3226 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003227 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003228 return retval;
3229}
3230
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003231#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003232static PyObject*
3233DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3234{
3235 int err, flags=0;
3236 PyObject* keyobj = NULL;
3237 PyObject* dataobj = NULL;
3238 PyObject* retval = NULL;
3239 int dlen = -1;
3240 int doff = -1;
3241 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003242 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3243 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003244
3245 CLEAR_DBT(key);
3246 CLEAR_DBT(data);
3247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3248 &flags, &dlen, &doff))
3249 {
3250 PyErr_Clear();
3251 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003252 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003253 &keyobj, &flags, &dlen, &doff))
3254 {
3255 PyErr_Clear();
3256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3257 kwnames, &keyobj, &dataobj,
3258 &flags, &dlen, &doff))
3259 {
3260 return NULL;
3261 }
3262 }
3263 }
3264
3265 CHECK_CURSOR_NOT_CLOSED(self);
3266
3267 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3268 return NULL;
3269 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3270 (!add_partial_dbt(&data, dlen, doff)) ) {
3271 FREE_DBT(key);
3272 return NULL;
3273 }
3274
3275 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3276 data.flags = DB_DBT_MALLOC;
3277 if (!(key.flags & DB_DBT_REALLOC)) {
3278 key.flags |= DB_DBT_MALLOC;
3279 }
3280 }
3281
3282 CLEAR_DBT(pkey);
3283 pkey.flags = DB_DBT_MALLOC;
3284
3285 MYDB_BEGIN_ALLOW_THREADS;
3286 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3287 MYDB_END_ALLOW_THREADS;
3288
Gregory P. Smithe9477062005-06-04 06:46:59 +00003289 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3290 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003291 Py_INCREF(Py_None);
3292 retval = Py_None;
3293 }
3294 else if (makeDBError(err)) {
3295 retval = NULL;
3296 }
3297 else {
3298 PyObject *pkeyObj;
3299 PyObject *dataObj;
3300 dataObj = PyString_FromStringAndSize(data.data, data.size);
3301
3302 if (self->mydb->primaryDBType == DB_RECNO ||
3303 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003304 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003305 else
3306 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3307
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003308 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003309 {
3310 PyObject *keyObj;
3311 int type = _DB_get_type(self->mydb);
3312 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003313 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003314 else
3315 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003316#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003317 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003318#else
3319 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3320#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003321 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003322 FREE_DBT(key);
3323 }
3324 else /* return just the pkey and data */
3325 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003326#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003327 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003328#else
3329 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3330#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003331 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003332 Py_DECREF(dataObj);
3333 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003334 FREE_DBT(pkey);
3335 FREE_DBT(data);
3336 }
3337 /* the only time REALLOC should be set is if we used an integer
3338 * key that make_key_dbt malloc'd for us. always free these. */
3339 if (key.flags & DB_DBT_REALLOC) {
3340 FREE_DBT(key);
3341 }
3342 return retval;
3343}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003344#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003345
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346
3347static PyObject*
3348DBC_get_recno(DBCursorObject* self, PyObject* args)
3349{
3350 int err;
3351 db_recno_t recno;
3352 DBT key;
3353 DBT data;
3354
3355 if (!PyArg_ParseTuple(args, ":get_recno"))
3356 return NULL;
3357
3358 CHECK_CURSOR_NOT_CLOSED(self);
3359
3360 CLEAR_DBT(key);
3361 CLEAR_DBT(data);
3362 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3363 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3364 data.flags = DB_DBT_MALLOC;
3365 key.flags = DB_DBT_MALLOC;
3366 }
3367
3368 MYDB_BEGIN_ALLOW_THREADS;
3369 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3370 MYDB_END_ALLOW_THREADS;
3371 RETURN_IF_ERR();
3372
3373 recno = *((db_recno_t*)data.data);
3374 FREE_DBT(key);
3375 FREE_DBT(data);
3376 return PyInt_FromLong(recno);
3377}
3378
3379
3380static PyObject*
3381DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3382{
3383 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3384}
3385
3386
3387static PyObject*
3388DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3389{
3390 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3391}
3392
3393
3394static PyObject*
3395DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3396{
3397 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3398}
3399
3400
3401static PyObject*
3402DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3403{
3404 int err, flags = 0;
3405 PyObject* keyobj, *dataobj;
3406 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003407 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003408 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409 int dlen = -1;
3410 int doff = -1;
3411
3412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3413 &keyobj, &dataobj, &flags, &dlen, &doff))
3414 return NULL;
3415
3416 CHECK_CURSOR_NOT_CLOSED(self);
3417
3418 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3419 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003420 if (!make_dbt(dataobj, &data) ||
3421 !add_partial_dbt(&data, dlen, doff) )
3422 {
3423 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003424 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003425 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003426
3427 MYDB_BEGIN_ALLOW_THREADS;
3428 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3429 MYDB_END_ALLOW_THREADS;
3430 FREE_DBT(key);
3431 RETURN_IF_ERR();
3432 self->mydb->haveStat = 0;
3433 RETURN_NONE();
3434}
3435
3436
3437static PyObject*
3438DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3439{
3440 int err, flags = 0;
3441 DBT key, data;
3442 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003443 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444 int dlen = -1;
3445 int doff = -1;
3446
3447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3448 &keyobj, &flags, &dlen, &doff))
3449 return NULL;
3450
3451 CHECK_CURSOR_NOT_CLOSED(self);
3452
3453 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3454 return NULL;
3455
3456 CLEAR_DBT(data);
3457 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3458 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3459 data.flags = DB_DBT_MALLOC;
3460 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003461 if (!add_partial_dbt(&data, dlen, doff)) {
3462 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003464 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465
3466 MYDB_BEGIN_ALLOW_THREADS;
3467 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3468 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003469 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3470 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003471 Py_INCREF(Py_None);
3472 retval = Py_None;
3473 }
3474 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475 retval = NULL;
3476 }
3477 else {
3478 switch (_DB_get_type(self->mydb)) {
3479 case -1:
3480 retval = NULL;
3481 break;
3482 case DB_BTREE:
3483 case DB_HASH:
3484 default:
3485 retval = Py_BuildValue("s#s#", key.data, key.size,
3486 data.data, data.size);
3487 break;
3488 case DB_RECNO:
3489 case DB_QUEUE:
3490 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3491 data.data, data.size);
3492 break;
3493 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003495 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003496 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003497 /* the only time REALLOC should be set is if we used an integer
3498 * key that make_key_dbt malloc'd for us. always free these. */
3499 if (key.flags & DB_DBT_REALLOC) {
3500 FREE_DBT(key);
3501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003502
3503 return retval;
3504}
3505
3506
3507static PyObject*
3508DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3509{
3510 int err, flags = 0;
3511 DBT key, data;
3512 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003513 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003514 int dlen = -1;
3515 int doff = -1;
3516
3517 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3518 &keyobj, &flags, &dlen, &doff))
3519 return NULL;
3520
3521 CHECK_CURSOR_NOT_CLOSED(self);
3522
3523 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3524 return NULL;
3525
3526 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 if (!add_partial_dbt(&data, dlen, doff)) {
3528 FREE_DBT(key);
3529 return NULL;
3530 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3532 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003533 data.flags |= DB_DBT_MALLOC;
3534 /* only BTREE databases will return anything in the key */
3535 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3536 key.flags |= DB_DBT_MALLOC;
3537 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003539 MYDB_BEGIN_ALLOW_THREADS;
3540 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3541 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003542 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3543 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003544 Py_INCREF(Py_None);
3545 retval = Py_None;
3546 }
3547 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003548 retval = NULL;
3549 }
3550 else {
3551 switch (_DB_get_type(self->mydb)) {
3552 case -1:
3553 retval = NULL;
3554 break;
3555 case DB_BTREE:
3556 case DB_HASH:
3557 default:
3558 retval = Py_BuildValue("s#s#", key.data, key.size,
3559 data.data, data.size);
3560 break;
3561 case DB_RECNO:
3562 case DB_QUEUE:
3563 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3564 data.data, data.size);
3565 break;
3566 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003567 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003568 FREE_DBT(data);
3569 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003570 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003571 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003572 if (key.flags & DB_DBT_REALLOC) {
3573 FREE_DBT(key);
3574 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575
3576 return retval;
3577}
3578
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003580_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3581 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003583 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003585 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586
Gregory P. Smith7441e652003-11-03 21:35:31 +00003587 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3589 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003590 if (!make_dbt(dataobj, &data)) {
3591 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594
3595 MYDB_BEGIN_ALLOW_THREADS;
3596 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3597 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003598 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003599 Py_INCREF(Py_None);
3600 retval = Py_None;
3601 }
3602 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003603 retval = NULL;
3604 }
3605 else {
3606 switch (_DB_get_type(self->mydb)) {
3607 case -1:
3608 retval = NULL;
3609 break;
3610 case DB_BTREE:
3611 case DB_HASH:
3612 default:
3613 retval = Py_BuildValue("s#s#", key.data, key.size,
3614 data.data, data.size);
3615 break;
3616 case DB_RECNO:
3617 case DB_QUEUE:
3618 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3619 data.data, data.size);
3620 break;
3621 }
3622 }
3623
3624 FREE_DBT(key);
3625 return retval;
3626}
3627
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003628static PyObject*
3629DBC_get_both(DBCursorObject* self, PyObject* args)
3630{
3631 int flags=0;
3632 PyObject *keyobj, *dataobj;
3633
3634 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3635 return NULL;
3636
Gregory P. Smith7441e652003-11-03 21:35:31 +00003637 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003638 CHECK_CURSOR_NOT_CLOSED(self);
3639
3640 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3641 self->mydb->moduleFlags.getReturnsNone);
3642}
3643
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003644/* Return size of entry */
3645static PyObject*
3646DBC_get_current_size(DBCursorObject* self, PyObject* args)
3647{
3648 int err, flags=DB_CURRENT;
3649 PyObject* retval = NULL;
3650 DBT key, data;
3651
3652 if (!PyArg_ParseTuple(args, ":get_current_size"))
3653 return NULL;
3654 CHECK_CURSOR_NOT_CLOSED(self);
3655 CLEAR_DBT(key);
3656 CLEAR_DBT(data);
3657
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003658 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003659 getting the record size. */
3660 data.flags = DB_DBT_USERMEM;
3661 data.ulen = 0;
3662 MYDB_BEGIN_ALLOW_THREADS;
3663 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3664 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003665 if (err == DB_BUFFER_SMALL || !err) {
3666 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003667 retval = PyInt_FromLong((long)data.size);
3668 err = 0;
3669 }
3670
3671 FREE_DBT(key);
3672 FREE_DBT(data);
3673 RETURN_IF_ERR();
3674 return retval;
3675}
3676
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003677static PyObject*
3678DBC_set_both(DBCursorObject* self, PyObject* args)
3679{
3680 int flags=0;
3681 PyObject *keyobj, *dataobj;
3682
3683 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3684 return NULL;
3685
Gregory P. Smith7441e652003-11-03 21:35:31 +00003686 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003687 CHECK_CURSOR_NOT_CLOSED(self);
3688
3689 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3690 self->mydb->moduleFlags.cursorSetReturnsNone);
3691}
3692
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003693
3694static PyObject*
3695DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3696{
3697 int err, irecno, flags=0;
3698 db_recno_t recno;
3699 DBT key, data;
3700 PyObject* retval;
3701 int dlen = -1;
3702 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003703 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704
3705 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3706 &irecno, &flags, &dlen, &doff))
3707 return NULL;
3708
3709 CHECK_CURSOR_NOT_CLOSED(self);
3710
3711 CLEAR_DBT(key);
3712 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003713 /* use allocated space so DB will be able to realloc room for the real
3714 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003715 key.data = malloc(sizeof(db_recno_t));
3716 if (key.data == NULL) {
3717 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3718 return NULL;
3719 }
3720 key.size = sizeof(db_recno_t);
3721 key.ulen = key.size;
3722 memcpy(key.data, &recno, sizeof(db_recno_t));
3723 key.flags = DB_DBT_REALLOC;
3724
3725 CLEAR_DBT(data);
3726 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3727 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3728 data.flags = DB_DBT_MALLOC;
3729 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003730 if (!add_partial_dbt(&data, dlen, doff)) {
3731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734
3735 MYDB_BEGIN_ALLOW_THREADS;
3736 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3737 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003738 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3739 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003740 Py_INCREF(Py_None);
3741 retval = Py_None;
3742 }
3743 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003744 retval = NULL;
3745 }
3746 else { /* Can only be used for BTrees, so no need to return int key */
3747 retval = Py_BuildValue("s#s#", key.data, key.size,
3748 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749 FREE_DBT(data);
3750 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003751 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003752
3753 return retval;
3754}
3755
3756
3757static PyObject*
3758DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3759{
3760 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3761}
3762
3763
3764static PyObject*
3765DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3766{
3767 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3768}
3769
3770
3771static PyObject*
3772DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3773{
3774 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3775}
3776
3777
3778static PyObject*
3779DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3780{
3781 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3782}
3783
3784
3785static PyObject*
3786DBC_join_item(DBCursorObject* self, PyObject* args)
3787{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003788 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789 DBT key, data;
3790 PyObject* retval;
3791
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003793 return NULL;
3794
3795 CHECK_CURSOR_NOT_CLOSED(self);
3796
3797 CLEAR_DBT(key);
3798 CLEAR_DBT(data);
3799 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3800 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3801 key.flags = DB_DBT_MALLOC;
3802 }
3803
3804 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003805 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003806 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003807 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3808 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003809 Py_INCREF(Py_None);
3810 retval = Py_None;
3811 }
3812 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813 retval = NULL;
3814 }
3815 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003816 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003817 FREE_DBT(key);
3818 }
3819
3820 return retval;
3821}
3822
3823
3824
3825/* --------------------------------------------------------------------- */
3826/* DBEnv methods */
3827
3828
3829static PyObject*
3830DBEnv_close(DBEnvObject* self, PyObject* args)
3831{
3832 int err, flags = 0;
3833
3834 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3835 return NULL;
3836 if (!self->closed) { /* Don't close more than once */
3837 MYDB_BEGIN_ALLOW_THREADS;
3838 err = self->db_env->close(self->db_env, flags);
3839 MYDB_END_ALLOW_THREADS;
3840 /* after calling DBEnv->close, regardless of error, this DBEnv
3841 * may not be accessed again (BerkeleyDB docs). */
3842 self->closed = 1;
3843 self->db_env = NULL;
3844 RETURN_IF_ERR();
3845 }
3846 RETURN_NONE();
3847}
3848
3849
3850static PyObject*
3851DBEnv_open(DBEnvObject* self, PyObject* args)
3852{
3853 int err, flags=0, mode=0660;
3854 char *db_home;
3855
3856 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3857 return NULL;
3858
3859 CHECK_ENV_NOT_CLOSED(self);
3860
3861 MYDB_BEGIN_ALLOW_THREADS;
3862 err = self->db_env->open(self->db_env, db_home, flags, mode);
3863 MYDB_END_ALLOW_THREADS;
3864 RETURN_IF_ERR();
3865 self->closed = 0;
3866 self->flags = flags;
3867 RETURN_NONE();
3868}
3869
3870
3871static PyObject*
3872DBEnv_remove(DBEnvObject* self, PyObject* args)
3873{
3874 int err, flags=0;
3875 char *db_home;
3876
3877 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3878 return NULL;
3879 CHECK_ENV_NOT_CLOSED(self);
3880 MYDB_BEGIN_ALLOW_THREADS;
3881 err = self->db_env->remove(self->db_env, db_home, flags);
3882 MYDB_END_ALLOW_THREADS;
3883 RETURN_IF_ERR();
3884 RETURN_NONE();
3885}
3886
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003887#if (DBVER >= 41)
3888static PyObject*
3889DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3890{
3891 int err;
3892 u_int32_t flags=0;
3893 char *file = NULL;
3894 char *database = NULL;
3895 PyObject *txnobj = NULL;
3896 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003897 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003898 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003899
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003900 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003901 &file, &database, &txnobj, &flags)) {
3902 return NULL;
3903 }
3904 if (!checkTxnObj(txnobj, &txn)) {
3905 return NULL;
3906 }
3907 CHECK_ENV_NOT_CLOSED(self);
3908 MYDB_BEGIN_ALLOW_THREADS;
3909 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3910 MYDB_END_ALLOW_THREADS;
3911 RETURN_IF_ERR();
3912 RETURN_NONE();
3913}
3914
3915static PyObject*
3916DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3917{
3918 int err;
3919 u_int32_t flags=0;
3920 char *file = NULL;
3921 char *database = NULL;
3922 char *newname = NULL;
3923 PyObject *txnobj = NULL;
3924 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003925 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003926 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003927
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003929 &file, &database, &newname, &txnobj, &flags)) {
3930 return NULL;
3931 }
3932 if (!checkTxnObj(txnobj, &txn)) {
3933 return NULL;
3934 }
3935 CHECK_ENV_NOT_CLOSED(self);
3936 MYDB_BEGIN_ALLOW_THREADS;
3937 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3938 flags);
3939 MYDB_END_ALLOW_THREADS;
3940 RETURN_IF_ERR();
3941 RETURN_NONE();
3942}
3943
3944static PyObject*
3945DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3946{
3947 int err;
3948 u_int32_t flags=0;
3949 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003950 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003951
3952 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3953 &passwd, &flags)) {
3954 return NULL;
3955 }
3956
3957 MYDB_BEGIN_ALLOW_THREADS;
3958 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3959 MYDB_END_ALLOW_THREADS;
3960
3961 RETURN_IF_ERR();
3962 RETURN_NONE();
3963}
3964#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003965
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003966#if (DBVER >= 40)
3967static PyObject*
3968DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3969{
3970 int err;
3971 u_int32_t flags=0;
3972 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003973 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003974
3975 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3976 &timeout, &flags)) {
3977 return NULL;
3978 }
3979
3980 MYDB_BEGIN_ALLOW_THREADS;
3981 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3982 MYDB_END_ALLOW_THREADS;
3983
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3986}
3987#endif /* DBVER >= 40 */
3988
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003990DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3991{
3992 int err;
3993 long shm_key = 0;
3994
3995 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3998
3999 err = self->db_env->set_shm_key(self->db_env, shm_key);
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4002}
4003
4004static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004005DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4006{
4007 int err, gbytes=0, bytes=0, ncache=0;
4008
4009 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4010 &gbytes, &bytes, &ncache))
4011 return NULL;
4012 CHECK_ENV_NOT_CLOSED(self);
4013
4014 MYDB_BEGIN_ALLOW_THREADS;
4015 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4016 MYDB_END_ALLOW_THREADS;
4017 RETURN_IF_ERR();
4018 RETURN_NONE();
4019}
4020
4021
4022#if (DBVER >= 32)
4023static PyObject*
4024DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4025{
4026 int err, flags=0, onoff=0;
4027
4028 if (!PyArg_ParseTuple(args, "ii:set_flags",
4029 &flags, &onoff))
4030 return NULL;
4031 CHECK_ENV_NOT_CLOSED(self);
4032
4033 MYDB_BEGIN_ALLOW_THREADS;
4034 err = self->db_env->set_flags(self->db_env, flags, onoff);
4035 MYDB_END_ALLOW_THREADS;
4036 RETURN_IF_ERR();
4037 RETURN_NONE();
4038}
4039#endif
4040
4041
4042static PyObject*
4043DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4044{
4045 int err;
4046 char *dir;
4047
4048 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4051
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_data_dir(self->db_env, dir);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4057}
4058
4059
4060static PyObject*
4061DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4062{
4063 int err, lg_bsize;
4064
4065 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4066 return NULL;
4067 CHECK_ENV_NOT_CLOSED(self);
4068
4069 MYDB_BEGIN_ALLOW_THREADS;
4070 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4071 MYDB_END_ALLOW_THREADS;
4072 RETURN_IF_ERR();
4073 RETURN_NONE();
4074}
4075
4076
4077static PyObject*
4078DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4079{
4080 int err;
4081 char *dir;
4082
4083 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4084 return NULL;
4085 CHECK_ENV_NOT_CLOSED(self);
4086
4087 MYDB_BEGIN_ALLOW_THREADS;
4088 err = self->db_env->set_lg_dir(self->db_env, dir);
4089 MYDB_END_ALLOW_THREADS;
4090 RETURN_IF_ERR();
4091 RETURN_NONE();
4092}
4093
4094static PyObject*
4095DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4096{
4097 int err, lg_max;
4098
4099 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4100 return NULL;
4101 CHECK_ENV_NOT_CLOSED(self);
4102
4103 MYDB_BEGIN_ALLOW_THREADS;
4104 err = self->db_env->set_lg_max(self->db_env, lg_max);
4105 MYDB_END_ALLOW_THREADS;
4106 RETURN_IF_ERR();
4107 RETURN_NONE();
4108}
4109
4110
Neal Norwitz84562352005-10-20 04:30:15 +00004111#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004112static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004113DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4114{
4115 int err, lg_max;
4116
4117 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4118 return NULL;
4119 CHECK_ENV_NOT_CLOSED(self);
4120
4121 MYDB_BEGIN_ALLOW_THREADS;
4122 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4123 MYDB_END_ALLOW_THREADS;
4124 RETURN_IF_ERR();
4125 RETURN_NONE();
4126}
Neal Norwitz84562352005-10-20 04:30:15 +00004127#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004128
4129
4130static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004131DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4132{
4133 int err, lk_detect;
4134
4135 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4136 return NULL;
4137 CHECK_ENV_NOT_CLOSED(self);
4138
4139 MYDB_BEGIN_ALLOW_THREADS;
4140 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4141 MYDB_END_ALLOW_THREADS;
4142 RETURN_IF_ERR();
4143 RETURN_NONE();
4144}
4145
4146
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004147#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004148static PyObject*
4149DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4150{
4151 int err, max;
4152
4153 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4154 return NULL;
4155 CHECK_ENV_NOT_CLOSED(self);
4156
4157 MYDB_BEGIN_ALLOW_THREADS;
4158 err = self->db_env->set_lk_max(self->db_env, max);
4159 MYDB_END_ALLOW_THREADS;
4160 RETURN_IF_ERR();
4161 RETURN_NONE();
4162}
Gregory P. Smith1a050f52007-01-05 02:09:06 +00004163#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004164
4165
4166#if (DBVER >= 32)
4167
4168static PyObject*
4169DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4170{
4171 int err, max;
4172
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_locks(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184
4185static PyObject*
4186DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4187{
4188 int err, max;
4189
4190 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4191 return NULL;
4192 CHECK_ENV_NOT_CLOSED(self);
4193
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4196 MYDB_END_ALLOW_THREADS;
4197 RETURN_IF_ERR();
4198 RETURN_NONE();
4199}
4200
4201
4202static PyObject*
4203DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4204{
4205 int err, max;
4206
4207 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4210
4211 MYDB_BEGIN_ALLOW_THREADS;
4212 err = self->db_env->set_lk_max_objects(self->db_env, max);
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 RETURN_NONE();
4216}
4217
4218#endif
4219
4220
4221static PyObject*
4222DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4223{
4224 int err, mp_mmapsize;
4225
4226 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4227 return NULL;
4228 CHECK_ENV_NOT_CLOSED(self);
4229
4230 MYDB_BEGIN_ALLOW_THREADS;
4231 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4232 MYDB_END_ALLOW_THREADS;
4233 RETURN_IF_ERR();
4234 RETURN_NONE();
4235}
4236
4237
4238static PyObject*
4239DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4240{
4241 int err;
4242 char *dir;
4243
4244 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4245 return NULL;
4246 CHECK_ENV_NOT_CLOSED(self);
4247
4248 MYDB_BEGIN_ALLOW_THREADS;
4249 err = self->db_env->set_tmp_dir(self->db_env, dir);
4250 MYDB_END_ALLOW_THREADS;
4251 RETURN_IF_ERR();
4252 RETURN_NONE();
4253}
4254
4255
4256static PyObject*
4257DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4258{
4259 int flags = 0;
4260 PyObject* txnobj = NULL;
4261 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004262 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004263
4264 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4265 &txnobj, &flags))
4266 return NULL;
4267
4268 if (!checkTxnObj(txnobj, &txn))
4269 return NULL;
4270 CHECK_ENV_NOT_CLOSED(self);
4271
4272 return (PyObject*)newDBTxnObject(self, txn, flags);
4273}
4274
4275
4276static PyObject*
4277DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4278{
4279 int err, kbyte=0, min=0, flags=0;
4280
4281 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4282 return NULL;
4283 CHECK_ENV_NOT_CLOSED(self);
4284
4285 MYDB_BEGIN_ALLOW_THREADS;
4286#if (DBVER >= 40)
4287 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4288#else
4289 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4290#endif
4291 MYDB_END_ALLOW_THREADS;
4292 RETURN_IF_ERR();
4293 RETURN_NONE();
4294}
4295
4296
4297static PyObject*
4298DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4299{
4300 int err, max;
4301
4302 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
4305
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004306 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004307 RETURN_IF_ERR();
4308 RETURN_NONE();
4309}
4310
4311
4312static PyObject*
4313DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4314{
4315 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004316 long stamp;
4317 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004318
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004319 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004320 return NULL;
4321 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004322 timestamp = (time_t)stamp;
4323 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004324 RETURN_IF_ERR();
4325 RETURN_NONE();
4326}
4327
4328
4329static PyObject*
4330DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4331{
4332 int err, atype, flags=0;
4333 int aborted = 0;
4334
4335 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4336 return NULL;
4337 CHECK_ENV_NOT_CLOSED(self);
4338
4339 MYDB_BEGIN_ALLOW_THREADS;
4340#if (DBVER >= 40)
4341 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4342#else
4343 err = lock_detect(self->db_env, flags, atype, &aborted);
4344#endif
4345 MYDB_END_ALLOW_THREADS;
4346 RETURN_IF_ERR();
4347 return PyInt_FromLong(aborted);
4348}
4349
4350
4351static PyObject*
4352DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4353{
4354 int flags=0;
4355 int locker, lock_mode;
4356 DBT obj;
4357 PyObject* objobj;
4358
4359 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4360 return NULL;
4361
4362
4363 if (!make_dbt(objobj, &obj))
4364 return NULL;
4365
4366 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4367}
4368
4369
4370static PyObject*
4371DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4372{
4373 int err;
4374 u_int32_t theID;
4375
4376 if (!PyArg_ParseTuple(args, ":lock_id"))
4377 return NULL;
4378
4379 CHECK_ENV_NOT_CLOSED(self);
4380 MYDB_BEGIN_ALLOW_THREADS;
4381#if (DBVER >= 40)
4382 err = self->db_env->lock_id(self->db_env, &theID);
4383#else
4384 err = lock_id(self->db_env, &theID);
4385#endif
4386 MYDB_END_ALLOW_THREADS;
4387 RETURN_IF_ERR();
4388
4389 return PyInt_FromLong((long)theID);
4390}
4391
4392
4393static PyObject*
4394DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4395{
4396 int err;
4397 DBLockObject* dblockobj;
4398
4399 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4400 return NULL;
4401
4402 CHECK_ENV_NOT_CLOSED(self);
4403 MYDB_BEGIN_ALLOW_THREADS;
4404#if (DBVER >= 40)
4405 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4406#else
4407 err = lock_put(self->db_env, &dblockobj->lock);
4408#endif
4409 MYDB_END_ALLOW_THREADS;
4410 RETURN_IF_ERR();
4411 RETURN_NONE();
4412}
4413
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004414#if (DBVER >= 44)
4415static PyObject*
4416DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4417{
4418 int err;
4419 char *file;
4420 u_int32_t flags = 0;
4421 static char* kwnames[] = { "file", "flags", NULL};
4422
4423 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4424 &file, &flags))
4425 return NULL;
4426 CHECK_ENV_NOT_CLOSED(self);
4427
4428 MYDB_BEGIN_ALLOW_THREADS;
4429 err = self->db_env->lsn_reset(self->db_env, file, flags);
4430 MYDB_END_ALLOW_THREADS;
4431 RETURN_IF_ERR();
4432 RETURN_NONE();
4433}
4434#endif /* DBVER >= 4.4 */
4435
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004436#if (DBVER >= 40)
4437static PyObject*
4438DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4439{
4440 int err;
4441 DB_LOG_STAT* statp = NULL;
4442 PyObject* d = NULL;
4443 u_int32_t flags = 0;
4444
4445 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4446 return NULL;
4447 CHECK_ENV_NOT_CLOSED(self);
4448
4449 MYDB_BEGIN_ALLOW_THREADS;
4450 err = self->db_env->log_stat(self->db_env, &statp, flags);
4451 MYDB_END_ALLOW_THREADS;
4452 RETURN_IF_ERR();
4453
4454 /* Turn the stat structure into a dictionary */
4455 d = PyDict_New();
4456 if (d == NULL) {
4457 if (statp)
4458 free(statp);
4459 return NULL;
4460 }
4461
4462#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4463
4464 MAKE_ENTRY(magic);
4465 MAKE_ENTRY(version);
4466 MAKE_ENTRY(mode);
4467 MAKE_ENTRY(lg_bsize);
4468#if (DBVER >= 44)
4469 MAKE_ENTRY(lg_size);
4470 MAKE_ENTRY(record);
4471#endif
4472#if (DBVER <= 40)
4473 MAKE_ENTRY(lg_max);
4474#endif
4475 MAKE_ENTRY(w_mbytes);
4476 MAKE_ENTRY(w_bytes);
4477 MAKE_ENTRY(wc_mbytes);
4478 MAKE_ENTRY(wc_bytes);
4479 MAKE_ENTRY(wcount);
4480 MAKE_ENTRY(wcount_fill);
4481#if (DBVER >= 44)
4482 MAKE_ENTRY(rcount);
4483#endif
4484 MAKE_ENTRY(scount);
4485 MAKE_ENTRY(cur_file);
4486 MAKE_ENTRY(cur_offset);
4487 MAKE_ENTRY(disk_file);
4488 MAKE_ENTRY(disk_offset);
4489 MAKE_ENTRY(maxcommitperflush);
4490 MAKE_ENTRY(mincommitperflush);
4491 MAKE_ENTRY(regsize);
4492 MAKE_ENTRY(region_wait);
4493 MAKE_ENTRY(region_nowait);
4494
4495#undef MAKE_ENTRY
4496 free(statp);
4497 return d;
4498} /* DBEnv_log_stat */
4499#endif /* DBVER >= 4.0 for log_stat method */
4500
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004501
4502static PyObject*
4503DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4504{
4505 int err;
4506 DB_LOCK_STAT* sp;
4507 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004508 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004509
4510 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4511 return NULL;
4512 CHECK_ENV_NOT_CLOSED(self);
4513
4514 MYDB_BEGIN_ALLOW_THREADS;
4515#if (DBVER >= 40)
4516 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4517#else
4518#if (DBVER >= 33)
4519 err = lock_stat(self->db_env, &sp);
4520#else
4521 err = lock_stat(self->db_env, &sp, NULL);
4522#endif
4523#endif
4524 MYDB_END_ALLOW_THREADS;
4525 RETURN_IF_ERR();
4526
4527 /* Turn the stat structure into a dictionary */
4528 d = PyDict_New();
4529 if (d == NULL) {
4530 free(sp);
4531 return NULL;
4532 }
4533
4534#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4535
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004537 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004538#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 MAKE_ENTRY(nmodes);
4540#if (DBVER >= 32)
4541 MAKE_ENTRY(maxlocks);
4542 MAKE_ENTRY(maxlockers);
4543 MAKE_ENTRY(maxobjects);
4544 MAKE_ENTRY(nlocks);
4545 MAKE_ENTRY(maxnlocks);
4546#endif
4547 MAKE_ENTRY(nlockers);
4548 MAKE_ENTRY(maxnlockers);
4549#if (DBVER >= 32)
4550 MAKE_ENTRY(nobjects);
4551 MAKE_ENTRY(maxnobjects);
4552#endif
4553 MAKE_ENTRY(nrequests);
4554 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004555#if (DBVER < 44)
4556 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004557 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004558#else
4559 MAKE_ENTRY(lock_nowait);
4560 MAKE_ENTRY(lock_wait);
4561#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 MAKE_ENTRY(ndeadlocks);
4563 MAKE_ENTRY(regsize);
4564 MAKE_ENTRY(region_wait);
4565 MAKE_ENTRY(region_nowait);
4566
4567#undef MAKE_ENTRY
4568 free(sp);
4569 return d;
4570}
4571
4572
4573static PyObject*
4574DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4575{
4576 int flags=0;
4577 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004578 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004579 PyObject* list;
4580 PyObject* item = NULL;
4581
4582 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4583 return NULL;
4584
4585 CHECK_ENV_NOT_CLOSED(self);
4586 MYDB_BEGIN_ALLOW_THREADS;
4587#if (DBVER >= 40)
4588 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4589#elif (DBVER == 33)
4590 err = log_archive(self->db_env, &log_list, flags);
4591#else
4592 err = log_archive(self->db_env, &log_list, flags, NULL);
4593#endif
4594 MYDB_END_ALLOW_THREADS;
4595 RETURN_IF_ERR();
4596
Gregory P. Smithbad47452006-06-05 00:33:35 +00004597 list = PyList_New(0);
4598 if (list == NULL) {
4599 if (log_list)
4600 free(log_list);
4601 return NULL;
4602 }
4603
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004604 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004605 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4607 item = PyString_FromString (*log_list);
4608 if (item == NULL) {
4609 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 list = NULL;
4611 break;
4612 }
4613 PyList_Append(list, item);
4614 Py_DECREF(item);
4615 }
4616 free(log_list_start);
4617 }
4618 return list;
4619}
4620
4621
4622static PyObject*
4623DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4624{
4625 int err;
4626 DB_TXN_STAT* sp;
4627 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004628 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004629
4630 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4631 return NULL;
4632 CHECK_ENV_NOT_CLOSED(self);
4633
4634 MYDB_BEGIN_ALLOW_THREADS;
4635#if (DBVER >= 40)
4636 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4637#elif (DBVER == 33)
4638 err = txn_stat(self->db_env, &sp);
4639#else
4640 err = txn_stat(self->db_env, &sp, NULL);
4641#endif
4642 MYDB_END_ALLOW_THREADS;
4643 RETURN_IF_ERR();
4644
4645 /* Turn the stat structure into a dictionary */
4646 d = PyDict_New();
4647 if (d == NULL) {
4648 free(sp);
4649 return NULL;
4650 }
4651
4652#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4653
4654 MAKE_ENTRY(time_ckp);
4655 MAKE_ENTRY(last_txnid);
4656 MAKE_ENTRY(maxtxns);
4657 MAKE_ENTRY(nactive);
4658 MAKE_ENTRY(maxnactive);
4659 MAKE_ENTRY(nbegins);
4660 MAKE_ENTRY(naborts);
4661 MAKE_ENTRY(ncommits);
4662 MAKE_ENTRY(regsize);
4663 MAKE_ENTRY(region_wait);
4664 MAKE_ENTRY(region_nowait);
4665
4666#undef MAKE_ENTRY
4667 free(sp);
4668 return d;
4669}
4670
4671
4672static PyObject*
4673DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4674{
4675 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004676 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004677
4678 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4679 return NULL;
4680 CHECK_ENV_NOT_CLOSED(self);
4681
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004682 if (self->moduleFlags.getReturnsNone)
4683 ++oldValue;
4684 if (self->moduleFlags.cursorSetReturnsNone)
4685 ++oldValue;
4686 self->moduleFlags.getReturnsNone = (flags >= 1);
4687 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004688 return PyInt_FromLong(oldValue);
4689}
4690
4691
4692/* --------------------------------------------------------------------- */
4693/* DBTxn methods */
4694
4695
4696static PyObject*
4697DBTxn_commit(DBTxnObject* self, PyObject* args)
4698{
4699 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004700 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004701
4702 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4703 return NULL;
4704
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004705 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004706 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4707 "after txn_commit or txn_abort");
4708 PyErr_SetObject(DBError, t);
4709 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004710 return NULL;
4711 }
4712 txn = self->txn;
4713 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004714 MYDB_BEGIN_ALLOW_THREADS;
4715#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004716 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004717#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004718 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004719#endif
4720 MYDB_END_ALLOW_THREADS;
4721 RETURN_IF_ERR();
4722 RETURN_NONE();
4723}
4724
4725static PyObject*
4726DBTxn_prepare(DBTxnObject* self, PyObject* args)
4727{
4728#if (DBVER >= 33)
4729 int err;
4730 char* gid=NULL;
4731 int gid_size=0;
4732
4733 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4734 return NULL;
4735
4736 if (gid_size != DB_XIDDATASIZE) {
4737 PyErr_SetString(PyExc_TypeError,
4738 "gid must be DB_XIDDATASIZE bytes long");
4739 return NULL;
4740 }
4741
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004742 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004743 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4744 "after txn_commit or txn_abort");
4745 PyErr_SetObject(DBError, t);
4746 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004747 return NULL;
4748 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004749 MYDB_BEGIN_ALLOW_THREADS;
4750#if (DBVER >= 40)
4751 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4752#else
4753 err = txn_prepare(self->txn, (u_int8_t*)gid);
4754#endif
4755 MYDB_END_ALLOW_THREADS;
4756 RETURN_IF_ERR();
4757 RETURN_NONE();
4758#else
4759 int err;
4760
4761 if (!PyArg_ParseTuple(args, ":prepare"))
4762 return NULL;
4763
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004764 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004765 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4766 "after txn_commit or txn_abort");
4767 PyErr_SetObject(DBError, t);
4768 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004769 return NULL;
4770 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004771 MYDB_BEGIN_ALLOW_THREADS;
4772 err = txn_prepare(self->txn);
4773 MYDB_END_ALLOW_THREADS;
4774 RETURN_IF_ERR();
4775 RETURN_NONE();
4776#endif
4777}
4778
4779
4780static PyObject*
4781DBTxn_abort(DBTxnObject* self, PyObject* args)
4782{
4783 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004784 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785
4786 if (!PyArg_ParseTuple(args, ":abort"))
4787 return NULL;
4788
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004789 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004790 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4791 "after txn_commit or txn_abort");
4792 PyErr_SetObject(DBError, t);
4793 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004794 return NULL;
4795 }
4796 txn = self->txn;
4797 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004798 MYDB_BEGIN_ALLOW_THREADS;
4799#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004800 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004801#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004802 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004803#endif
4804 MYDB_END_ALLOW_THREADS;
4805 RETURN_IF_ERR();
4806 RETURN_NONE();
4807}
4808
4809
4810static PyObject*
4811DBTxn_id(DBTxnObject* self, PyObject* args)
4812{
4813 int id;
4814
4815 if (!PyArg_ParseTuple(args, ":id"))
4816 return NULL;
4817
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004818 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004819 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4820 "after txn_commit or txn_abort");
4821 PyErr_SetObject(DBError, t);
4822 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004823 return NULL;
4824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004825 MYDB_BEGIN_ALLOW_THREADS;
4826#if (DBVER >= 40)
4827 id = self->txn->id(self->txn);
4828#else
4829 id = txn_id(self->txn);
4830#endif
4831 MYDB_END_ALLOW_THREADS;
4832 return PyInt_FromLong(id);
4833}
4834
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004835#if (DBVER >= 43)
4836/* --------------------------------------------------------------------- */
4837/* DBSequence methods */
4838
4839
4840static PyObject*
4841DBSequence_close(DBSequenceObject* self, PyObject* args)
4842{
4843 int err, flags=0;
4844 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4845 return NULL;
4846 CHECK_SEQUENCE_NOT_CLOSED(self)
4847
4848 MYDB_BEGIN_ALLOW_THREADS
4849 err = self->sequence->close(self->sequence, flags);
4850 self->sequence = NULL;
4851 MYDB_END_ALLOW_THREADS
4852
4853 RETURN_IF_ERR();
4854
4855 RETURN_NONE();
4856}
4857
4858static PyObject*
4859DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4860{
4861 int err, flags = 0;
4862 int delta = 1;
4863 db_seq_t value;
4864 PyObject *txnobj = NULL;
4865 DB_TXN *txn = NULL;
4866 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4868 return NULL;
4869 CHECK_SEQUENCE_NOT_CLOSED(self)
4870
4871 if (!checkTxnObj(txnobj, &txn))
4872 return NULL;
4873
4874 MYDB_BEGIN_ALLOW_THREADS
4875 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4876 MYDB_END_ALLOW_THREADS
4877
4878 RETURN_IF_ERR();
4879 return PyLong_FromLongLong(value);
4880
4881}
4882
4883static PyObject*
4884DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4885{
4886 if (!PyArg_ParseTuple(args,":get_dbp"))
4887 return NULL;
4888 CHECK_SEQUENCE_NOT_CLOSED(self)
4889 Py_INCREF(self->mydb);
4890 return (PyObject* )self->mydb;
4891}
4892
4893static PyObject*
4894DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4895{
4896 int err;
4897 DBT key;
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004898 PyObject *retval;
4899 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004900 CHECK_SEQUENCE_NOT_CLOSED(self)
4901 MYDB_BEGIN_ALLOW_THREADS
4902 err = self->sequence->get_key(self->sequence, &key);
4903 MYDB_END_ALLOW_THREADS
4904
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004905 if (!err)
4906 retval = PyString_FromStringAndSize(key.data, key.size);
4907
4908 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004909 RETURN_IF_ERR();
4910
Gregory P. Smith381e1a42007-10-06 16:05:18 +00004911 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004912}
4913
4914static PyObject*
4915DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4916{
4917 int err;
4918 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004919 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004920 return NULL;
4921 CHECK_SEQUENCE_NOT_CLOSED(self)
4922
4923 MYDB_BEGIN_ALLOW_THREADS
4924 err = self->sequence->initial_value(self->sequence, value);
4925 MYDB_END_ALLOW_THREADS
4926
4927 RETURN_IF_ERR();
4928
4929 RETURN_NONE();
4930}
4931
4932static PyObject*
4933DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4934{
4935 int err, flags = 0;
4936 PyObject* keyobj;
4937 PyObject *txnobj = NULL;
4938 DB_TXN *txn = NULL;
4939 DBT key;
4940
4941 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004943 return NULL;
4944
4945 if (!checkTxnObj(txnobj, &txn))
4946 return NULL;
4947
4948 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4949 return NULL;
4950
4951 MYDB_BEGIN_ALLOW_THREADS
4952 err = self->sequence->open(self->sequence, txn, &key, flags);
4953 MYDB_END_ALLOW_THREADS
4954
4955 CLEAR_DBT(key);
4956 RETURN_IF_ERR();
4957
4958 RETURN_NONE();
4959}
4960
4961static PyObject*
4962DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4963{
4964 int err, flags = 0;
4965 PyObject *txnobj = NULL;
4966 DB_TXN *txn = NULL;
4967
4968 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004969 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004970 return NULL;
4971
4972 if (!checkTxnObj(txnobj, &txn))
4973 return NULL;
4974
4975 CHECK_SEQUENCE_NOT_CLOSED(self)
4976
4977 MYDB_BEGIN_ALLOW_THREADS
4978 err = self->sequence->remove(self->sequence, txn, flags);
4979 MYDB_END_ALLOW_THREADS
4980
4981 RETURN_IF_ERR();
4982 RETURN_NONE();
4983}
4984
4985static PyObject*
4986DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4987{
4988 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004989 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004990 return NULL;
4991 CHECK_SEQUENCE_NOT_CLOSED(self)
4992
4993 MYDB_BEGIN_ALLOW_THREADS
4994 err = self->sequence->set_cachesize(self->sequence, size);
4995 MYDB_END_ALLOW_THREADS
4996
4997 RETURN_IF_ERR();
4998 RETURN_NONE();
4999}
5000
5001static PyObject*
5002DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5003{
5004 int err, size;
5005 if (!PyArg_ParseTuple(args,":get_cachesize"))
5006 return NULL;
5007 CHECK_SEQUENCE_NOT_CLOSED(self)
5008
5009 MYDB_BEGIN_ALLOW_THREADS
5010 err = self->sequence->get_cachesize(self->sequence, &size);
5011 MYDB_END_ALLOW_THREADS
5012
5013 RETURN_IF_ERR();
5014 return PyInt_FromLong(size);
5015}
5016
5017static PyObject*
5018DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5019{
5020 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005021 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005022 return NULL;
5023 CHECK_SEQUENCE_NOT_CLOSED(self)
5024
5025 MYDB_BEGIN_ALLOW_THREADS
5026 err = self->sequence->set_flags(self->sequence, flags);
5027 MYDB_END_ALLOW_THREADS
5028
5029 RETURN_IF_ERR();
5030 RETURN_NONE();
5031
5032}
5033
5034static PyObject*
5035DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5036{
5037 unsigned int flags;
5038 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005039 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005040 return NULL;
5041 CHECK_SEQUENCE_NOT_CLOSED(self)
5042
5043 MYDB_BEGIN_ALLOW_THREADS
5044 err = self->sequence->get_flags(self->sequence, &flags);
5045 MYDB_END_ALLOW_THREADS
5046
5047 RETURN_IF_ERR();
5048 return PyInt_FromLong((int)flags);
5049}
5050
5051static PyObject*
5052DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5053{
5054 int err;
5055 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005056 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005057 return NULL;
5058 CHECK_SEQUENCE_NOT_CLOSED(self)
5059
5060 MYDB_BEGIN_ALLOW_THREADS
5061 err = self->sequence->set_range(self->sequence, min, max);
5062 MYDB_END_ALLOW_THREADS
5063
5064 RETURN_IF_ERR();
5065 RETURN_NONE();
5066}
5067
5068static PyObject*
5069DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5070{
5071 int err;
5072 db_seq_t min, max;
5073 if (!PyArg_ParseTuple(args,":get_range"))
5074 return NULL;
5075 CHECK_SEQUENCE_NOT_CLOSED(self)
5076
5077 MYDB_BEGIN_ALLOW_THREADS
5078 err = self->sequence->get_range(self->sequence, &min, &max);
5079 MYDB_END_ALLOW_THREADS
5080
5081 RETURN_IF_ERR();
5082 return Py_BuildValue("(LL)", min, max);
5083}
5084
5085static PyObject*
5086DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5087{
5088 int err, flags = 0;
5089 DB_SEQUENCE_STAT* sp = NULL;
5090 PyObject* dict_stat;
5091 static char* kwnames[] = {"flags", NULL };
5092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5093 return NULL;
5094 CHECK_SEQUENCE_NOT_CLOSED(self);
5095
5096 MYDB_BEGIN_ALLOW_THREADS;
5097 err = self->sequence->stat(self->sequence, &sp, flags);
5098 MYDB_END_ALLOW_THREADS;
5099 RETURN_IF_ERR();
5100
5101 if ((dict_stat = PyDict_New()) == NULL) {
5102 free(sp);
5103 return NULL;
5104 }
5105
5106
5107#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5108#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5109
5110 MAKE_INT_ENTRY(wait);
5111 MAKE_INT_ENTRY(nowait);
5112 MAKE_LONG_LONG_ENTRY(current);
5113 MAKE_LONG_LONG_ENTRY(value);
5114 MAKE_LONG_LONG_ENTRY(last_value);
5115 MAKE_LONG_LONG_ENTRY(min);
5116 MAKE_LONG_LONG_ENTRY(max);
5117 MAKE_INT_ENTRY(cache_size);
5118 MAKE_INT_ENTRY(flags);
5119
5120#undef MAKE_INT_ENTRY
5121#undef MAKE_LONG_LONG_ENTRY
5122
5123 free(sp);
5124 return dict_stat;
5125}
5126#endif
5127
5128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005129/* --------------------------------------------------------------------- */
5130/* Method definition tables and type objects */
5131
5132static PyMethodDef DB_methods[] = {
5133 {"append", (PyCFunction)DB_append, METH_VARARGS},
5134#if (DBVER >= 33)
5135 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5136#endif
5137 {"close", (PyCFunction)DB_close, METH_VARARGS},
5138#if (DBVER >= 32)
5139 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5140 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5141#endif
5142 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5143 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5144 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5145 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005146#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005147 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005148#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005149 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5150 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5151 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5152 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5153 {"join", (PyCFunction)DB_join, METH_VARARGS},
5154 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5155 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5156 {"items", (PyCFunction)DB_items, METH_VARARGS},
5157 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5158 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5159 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5160 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5161 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5162 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005163#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005164 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005166 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005167#if (DBVER >= 41)
5168 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005170 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5171 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5172 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5173 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5174 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5175 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5176 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5177 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5178 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5179#if (DBVER >= 32)
5180 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5181#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005182 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005183 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5184#if (DBVER >= 33)
5185 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5186#endif
5187 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5188 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5189 {"values", (PyCFunction)DB_values, METH_VARARGS},
5190 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5191 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5192 {NULL, NULL} /* sentinel */
5193};
5194
5195
5196static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005197 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005198 (binaryfunc)DB_subscript, /*mp_subscript*/
5199 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5200};
5201
5202
5203static PyMethodDef DBCursor_methods[] = {
5204 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5205 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5206 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5207 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5208 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5209 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5210 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005211#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005212 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005214 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5215 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5216 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5217 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5218 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5219 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5220 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5221 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005222 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005223 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005224 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5225 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5226 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5227 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5228 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5229 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5230 {NULL, NULL} /* sentinel */
5231};
5232
5233
5234static PyMethodDef DBEnv_methods[] = {
5235 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5236 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5237 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005238#if (DBVER >= 41)
5239 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5240 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5241 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5242#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005243#if (DBVER >= 40)
5244 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5245#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005246 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005247 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5248 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5249#if (DBVER >= 32)
5250 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5251#endif
5252 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5253 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5254 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005255#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005256 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005258 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005259#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262#if (DBVER >= 32)
5263 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5264 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5265 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5266#endif
5267 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5268 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5269 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5270 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5271 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5272 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005273 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005274 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5275 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5276 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5277 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5278 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5279 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005280#if (DBVER >= 40)
5281 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5282#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005283#if (DBVER >= 44)
5284 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5285#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005286 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5287 {NULL, NULL} /* sentinel */
5288};
5289
5290
5291static PyMethodDef DBTxn_methods[] = {
5292 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5293 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5294 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5295 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5296 {NULL, NULL} /* sentinel */
5297};
5298
5299
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005300#if (DBVER >= 43)
5301static PyMethodDef DBSequence_methods[] = {
5302 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5303 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5304 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5305 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005306 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5307 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5308 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5309 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5310 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5311 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5312 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5313 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5314 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5315 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5316 {NULL, NULL} /* sentinel */
5317};
5318#endif
5319
5320
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005321static PyObject*
5322DB_getattr(DBObject* self, char *name)
5323{
5324 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5325}
5326
5327
5328static PyObject*
5329DBEnv_getattr(DBEnvObject* self, char *name)
5330{
5331 if (!strcmp(name, "db_home")) {
5332 CHECK_ENV_NOT_CLOSED(self);
5333 if (self->db_env->db_home == NULL) {
5334 RETURN_NONE();
5335 }
5336 return PyString_FromString(self->db_env->db_home);
5337 }
5338
5339 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5340}
5341
5342
5343static PyObject*
5344DBCursor_getattr(DBCursorObject* self, char *name)
5345{
5346 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5347}
5348
5349static PyObject*
5350DBTxn_getattr(DBTxnObject* self, char *name)
5351{
5352 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5353}
5354
5355static PyObject*
5356DBLock_getattr(DBLockObject* self, char *name)
5357{
5358 return NULL;
5359}
5360
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005361#if (DBVER >= 43)
5362static PyObject*
5363DBSequence_getattr(DBSequenceObject* self, char *name)
5364{
5365 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5366}
5367#endif
5368
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005369statichere PyTypeObject DB_Type = {
5370 PyObject_HEAD_INIT(NULL)
5371 0, /*ob_size*/
5372 "DB", /*tp_name*/
5373 sizeof(DBObject), /*tp_basicsize*/
5374 0, /*tp_itemsize*/
5375 /* methods */
5376 (destructor)DB_dealloc, /*tp_dealloc*/
5377 0, /*tp_print*/
5378 (getattrfunc)DB_getattr, /*tp_getattr*/
5379 0, /*tp_setattr*/
5380 0, /*tp_compare*/
5381 0, /*tp_repr*/
5382 0, /*tp_as_number*/
5383 0, /*tp_as_sequence*/
5384 &DB_mapping,/*tp_as_mapping*/
5385 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005386#ifdef HAVE_WEAKREF
5387 0, /* tp_call */
5388 0, /* tp_str */
5389 0, /* tp_getattro */
5390 0, /* tp_setattro */
5391 0, /* tp_as_buffer */
5392 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5393 0, /* tp_doc */
5394 0, /* tp_traverse */
5395 0, /* tp_clear */
5396 0, /* tp_richcompare */
5397 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5398#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005399};
5400
5401
5402statichere PyTypeObject DBCursor_Type = {
5403 PyObject_HEAD_INIT(NULL)
5404 0, /*ob_size*/
5405 "DBCursor", /*tp_name*/
5406 sizeof(DBCursorObject), /*tp_basicsize*/
5407 0, /*tp_itemsize*/
5408 /* methods */
5409 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5410 0, /*tp_print*/
5411 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5412 0, /*tp_setattr*/
5413 0, /*tp_compare*/
5414 0, /*tp_repr*/
5415 0, /*tp_as_number*/
5416 0, /*tp_as_sequence*/
5417 0, /*tp_as_mapping*/
5418 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005419#ifdef HAVE_WEAKREF
5420 0, /* tp_call */
5421 0, /* tp_str */
5422 0, /* tp_getattro */
5423 0, /* tp_setattro */
5424 0, /* tp_as_buffer */
5425 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5426 0, /* tp_doc */
5427 0, /* tp_traverse */
5428 0, /* tp_clear */
5429 0, /* tp_richcompare */
5430 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5431#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005432};
5433
5434
5435statichere PyTypeObject DBEnv_Type = {
5436 PyObject_HEAD_INIT(NULL)
5437 0, /*ob_size*/
5438 "DBEnv", /*tp_name*/
5439 sizeof(DBEnvObject), /*tp_basicsize*/
5440 0, /*tp_itemsize*/
5441 /* methods */
5442 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5443 0, /*tp_print*/
5444 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5445 0, /*tp_setattr*/
5446 0, /*tp_compare*/
5447 0, /*tp_repr*/
5448 0, /*tp_as_number*/
5449 0, /*tp_as_sequence*/
5450 0, /*tp_as_mapping*/
5451 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005452#ifdef HAVE_WEAKREF
5453 0, /* tp_call */
5454 0, /* tp_str */
5455 0, /* tp_getattro */
5456 0, /* tp_setattro */
5457 0, /* tp_as_buffer */
5458 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5459 0, /* tp_doc */
5460 0, /* tp_traverse */
5461 0, /* tp_clear */
5462 0, /* tp_richcompare */
5463 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5464#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005465};
5466
5467statichere PyTypeObject DBTxn_Type = {
5468 PyObject_HEAD_INIT(NULL)
5469 0, /*ob_size*/
5470 "DBTxn", /*tp_name*/
5471 sizeof(DBTxnObject), /*tp_basicsize*/
5472 0, /*tp_itemsize*/
5473 /* methods */
5474 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5475 0, /*tp_print*/
5476 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5477 0, /*tp_setattr*/
5478 0, /*tp_compare*/
5479 0, /*tp_repr*/
5480 0, /*tp_as_number*/
5481 0, /*tp_as_sequence*/
5482 0, /*tp_as_mapping*/
5483 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005484#ifdef HAVE_WEAKREF
5485 0, /* tp_call */
5486 0, /* tp_str */
5487 0, /* tp_getattro */
5488 0, /* tp_setattro */
5489 0, /* tp_as_buffer */
5490 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5491 0, /* tp_doc */
5492 0, /* tp_traverse */
5493 0, /* tp_clear */
5494 0, /* tp_richcompare */
5495 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5496#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005497};
5498
5499
5500statichere PyTypeObject DBLock_Type = {
5501 PyObject_HEAD_INIT(NULL)
5502 0, /*ob_size*/
5503 "DBLock", /*tp_name*/
5504 sizeof(DBLockObject), /*tp_basicsize*/
5505 0, /*tp_itemsize*/
5506 /* methods */
5507 (destructor)DBLock_dealloc, /*tp_dealloc*/
5508 0, /*tp_print*/
5509 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5510 0, /*tp_setattr*/
5511 0, /*tp_compare*/
5512 0, /*tp_repr*/
5513 0, /*tp_as_number*/
5514 0, /*tp_as_sequence*/
5515 0, /*tp_as_mapping*/
5516 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005517#ifdef HAVE_WEAKREF
5518 0, /* tp_call */
5519 0, /* tp_str */
5520 0, /* tp_getattro */
5521 0, /* tp_setattro */
5522 0, /* tp_as_buffer */
5523 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5524 0, /* tp_doc */
5525 0, /* tp_traverse */
5526 0, /* tp_clear */
5527 0, /* tp_richcompare */
5528 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5529#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005530};
5531
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005532#if (DBVER >= 43)
5533statichere PyTypeObject DBSequence_Type = {
5534 PyObject_HEAD_INIT(NULL)
5535 0, /*ob_size*/
5536 "DBSequence", /*tp_name*/
5537 sizeof(DBSequenceObject), /*tp_basicsize*/
5538 0, /*tp_itemsize*/
5539 /* methods */
5540 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5541 0, /*tp_print*/
5542 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5543 0, /*tp_setattr*/
5544 0, /*tp_compare*/
5545 0, /*tp_repr*/
5546 0, /*tp_as_number*/
5547 0, /*tp_as_sequence*/
5548 0, /*tp_as_mapping*/
5549 0, /*tp_hash*/
5550#ifdef HAVE_WEAKREF
5551 0, /* tp_call */
5552 0, /* tp_str */
5553 0, /* tp_getattro */
5554 0, /* tp_setattro */
5555 0, /* tp_as_buffer */
5556 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5557 0, /* tp_doc */
5558 0, /* tp_traverse */
5559 0, /* tp_clear */
5560 0, /* tp_richcompare */
5561 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5562#endif
5563};
5564#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005565
5566/* --------------------------------------------------------------------- */
5567/* Module-level functions */
5568
5569static PyObject*
5570DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5571{
5572 PyObject* dbenvobj = NULL;
5573 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005574 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005575
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5577 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005578 return NULL;
5579 if (dbenvobj == Py_None)
5580 dbenvobj = NULL;
5581 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5582 makeTypeError("DBEnv", dbenvobj);
5583 return NULL;
5584 }
5585
5586 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5587}
5588
5589
5590static PyObject*
5591DBEnv_construct(PyObject* self, PyObject* args)
5592{
5593 int flags = 0;
5594 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5595 return (PyObject* )newDBEnvObject(flags);
5596}
5597
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005598#if (DBVER >= 43)
5599static PyObject*
5600DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5601{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005602 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005603 int flags = 0;
5604 static char* kwnames[] = { "db", "flags", NULL};
5605
5606 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5607 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005608 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005609 makeTypeError("DB", dbobj);
5610 return NULL;
5611 }
5612 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5613}
5614#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005615
5616static char bsddb_version_doc[] =
5617"Returns a tuple of major, minor, and patch release numbers of the\n\
5618underlying DB library.";
5619
5620static PyObject*
5621bsddb_version(PyObject* self, PyObject* args)
5622{
5623 int major, minor, patch;
5624
5625 if (!PyArg_ParseTuple(args, ":version"))
5626 return NULL;
5627 db_version(&major, &minor, &patch);
5628 return Py_BuildValue("(iii)", major, minor, patch);
5629}
5630
5631
5632/* List of functions defined in the module */
5633
5634static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005635 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5636 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5637#if (DBVER >= 43)
5638 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5639#endif
5640 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005641 {NULL, NULL} /* sentinel */
5642};
5643
5644
5645/* --------------------------------------------------------------------- */
5646/* Module initialization */
5647
5648
5649/* Convenience routine to export an integer value.
5650 * Errors are silently ignored, for better or for worse...
5651 */
5652#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5653
Gregory P. Smith41631e82003-09-21 00:08:14 +00005654#define MODULE_NAME_MAX_LEN 11
5655static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656
5657DL_EXPORT(void) init_bsddb(void)
5658{
5659 PyObject* m;
5660 PyObject* d;
5661 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5662 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5663 PyObject* cvsid_s = PyString_FromString( rcs_id );
5664
5665 /* Initialize the type of the new type objects here; doing it here
5666 is required for portability to Windows without requiring C++. */
5667 DB_Type.ob_type = &PyType_Type;
5668 DBCursor_Type.ob_type = &PyType_Type;
5669 DBEnv_Type.ob_type = &PyType_Type;
5670 DBTxn_Type.ob_type = &PyType_Type;
5671 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005672#if (DBVER >= 43)
5673 DBSequence_Type.ob_type = &PyType_Type;
5674#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675
5676
Mark Hammonda69d4092003-04-22 23:13:27 +00005677#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005679 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005680#endif
5681
5682 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005683 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005684 if (m == NULL)
5685 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005686
5687 /* Add some symbolic constants to the module */
5688 d = PyModule_GetDict(m);
5689 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5690 PyDict_SetItemString(d, "cvsid", cvsid_s);
5691 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5692 Py_DECREF(pybsddb_version_s);
5693 pybsddb_version_s = NULL;
5694 Py_DECREF(cvsid_s);
5695 cvsid_s = NULL;
5696 Py_DECREF(db_version_s);
5697 db_version_s = NULL;
5698
5699 ADD_INT(d, DB_VERSION_MAJOR);
5700 ADD_INT(d, DB_VERSION_MINOR);
5701 ADD_INT(d, DB_VERSION_PATCH);
5702
5703 ADD_INT(d, DB_MAX_PAGES);
5704 ADD_INT(d, DB_MAX_RECORDS);
5705
Gregory P. Smith41631e82003-09-21 00:08:14 +00005706#if (DBVER >= 42)
5707 ADD_INT(d, DB_RPCCLIENT);
5708#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005709 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005710 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5711 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5712#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005713 ADD_INT(d, DB_XA_CREATE);
5714
5715 ADD_INT(d, DB_CREATE);
5716 ADD_INT(d, DB_NOMMAP);
5717 ADD_INT(d, DB_THREAD);
5718
5719 ADD_INT(d, DB_FORCE);
5720 ADD_INT(d, DB_INIT_CDB);
5721 ADD_INT(d, DB_INIT_LOCK);
5722 ADD_INT(d, DB_INIT_LOG);
5723 ADD_INT(d, DB_INIT_MPOOL);
5724 ADD_INT(d, DB_INIT_TXN);
5725#if (DBVER >= 32)
5726 ADD_INT(d, DB_JOINENV);
5727#endif
5728
5729 ADD_INT(d, DB_RECOVER);
5730 ADD_INT(d, DB_RECOVER_FATAL);
5731 ADD_INT(d, DB_TXN_NOSYNC);
5732 ADD_INT(d, DB_USE_ENVIRON);
5733 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5734
5735 ADD_INT(d, DB_LOCKDOWN);
5736 ADD_INT(d, DB_PRIVATE);
5737 ADD_INT(d, DB_SYSTEM_MEM);
5738
5739 ADD_INT(d, DB_TXN_SYNC);
5740 ADD_INT(d, DB_TXN_NOWAIT);
5741
5742 ADD_INT(d, DB_EXCL);
5743 ADD_INT(d, DB_FCNTL_LOCKING);
5744 ADD_INT(d, DB_ODDFILESIZE);
5745 ADD_INT(d, DB_RDWRMASTER);
5746 ADD_INT(d, DB_RDONLY);
5747 ADD_INT(d, DB_TRUNCATE);
5748#if (DBVER >= 32)
5749 ADD_INT(d, DB_EXTENT);
5750 ADD_INT(d, DB_CDB_ALLDB);
5751 ADD_INT(d, DB_VERIFY);
5752#endif
5753 ADD_INT(d, DB_UPGRADE);
5754
5755 ADD_INT(d, DB_AGGRESSIVE);
5756 ADD_INT(d, DB_NOORDERCHK);
5757 ADD_INT(d, DB_ORDERCHKONLY);
5758 ADD_INT(d, DB_PR_PAGE);
5759#if ! (DBVER >= 33)
5760 ADD_INT(d, DB_VRFY_FLAGMASK);
5761 ADD_INT(d, DB_PR_HEADERS);
5762#endif
5763 ADD_INT(d, DB_PR_RECOVERYTEST);
5764 ADD_INT(d, DB_SALVAGE);
5765
5766 ADD_INT(d, DB_LOCK_NORUN);
5767 ADD_INT(d, DB_LOCK_DEFAULT);
5768 ADD_INT(d, DB_LOCK_OLDEST);
5769 ADD_INT(d, DB_LOCK_RANDOM);
5770 ADD_INT(d, DB_LOCK_YOUNGEST);
5771#if (DBVER >= 33)
5772 ADD_INT(d, DB_LOCK_MAXLOCKS);
5773 ADD_INT(d, DB_LOCK_MINLOCKS);
5774 ADD_INT(d, DB_LOCK_MINWRITE);
5775#endif
5776
5777
5778#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005779 /* docs say to use zero instead */
5780 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005781#else
5782 ADD_INT(d, DB_LOCK_CONFLICT);
5783#endif
5784
5785 ADD_INT(d, DB_LOCK_DUMP);
5786 ADD_INT(d, DB_LOCK_GET);
5787 ADD_INT(d, DB_LOCK_INHERIT);
5788 ADD_INT(d, DB_LOCK_PUT);
5789 ADD_INT(d, DB_LOCK_PUT_ALL);
5790 ADD_INT(d, DB_LOCK_PUT_OBJ);
5791
5792 ADD_INT(d, DB_LOCK_NG);
5793 ADD_INT(d, DB_LOCK_READ);
5794 ADD_INT(d, DB_LOCK_WRITE);
5795 ADD_INT(d, DB_LOCK_NOWAIT);
5796#if (DBVER >= 32)
5797 ADD_INT(d, DB_LOCK_WAIT);
5798#endif
5799 ADD_INT(d, DB_LOCK_IWRITE);
5800 ADD_INT(d, DB_LOCK_IREAD);
5801 ADD_INT(d, DB_LOCK_IWR);
5802#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005803#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005804 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005805#else
5806 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5807#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005808 ADD_INT(d, DB_LOCK_WWRITE);
5809#endif
5810
5811 ADD_INT(d, DB_LOCK_RECORD);
5812 ADD_INT(d, DB_LOCK_UPGRADE);
5813#if (DBVER >= 32)
5814 ADD_INT(d, DB_LOCK_SWITCH);
5815#endif
5816#if (DBVER >= 33)
5817 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5818#endif
5819
5820 ADD_INT(d, DB_LOCK_NOWAIT);
5821 ADD_INT(d, DB_LOCK_RECORD);
5822 ADD_INT(d, DB_LOCK_UPGRADE);
5823
5824#if (DBVER >= 33)
5825 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005826#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005827 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005828#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_LSTAT_FREE);
5830 ADD_INT(d, DB_LSTAT_HELD);
5831#if (DBVER == 33)
5832 ADD_INT(d, DB_LSTAT_NOGRANT);
5833#endif
5834 ADD_INT(d, DB_LSTAT_PENDING);
5835 ADD_INT(d, DB_LSTAT_WAITING);
5836#endif
5837
5838 ADD_INT(d, DB_ARCH_ABS);
5839 ADD_INT(d, DB_ARCH_DATA);
5840 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005841#if (DBVER >= 42)
5842 ADD_INT(d, DB_ARCH_REMOVE);
5843#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005844
5845 ADD_INT(d, DB_BTREE);
5846 ADD_INT(d, DB_HASH);
5847 ADD_INT(d, DB_RECNO);
5848 ADD_INT(d, DB_QUEUE);
5849 ADD_INT(d, DB_UNKNOWN);
5850
5851 ADD_INT(d, DB_DUP);
5852 ADD_INT(d, DB_DUPSORT);
5853 ADD_INT(d, DB_RECNUM);
5854 ADD_INT(d, DB_RENUMBER);
5855 ADD_INT(d, DB_REVSPLITOFF);
5856 ADD_INT(d, DB_SNAPSHOT);
5857
5858 ADD_INT(d, DB_JOIN_NOSORT);
5859
5860 ADD_INT(d, DB_AFTER);
5861 ADD_INT(d, DB_APPEND);
5862 ADD_INT(d, DB_BEFORE);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005863#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005864 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005865#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005866#if (DBVER >= 41)
5867 _addIntToDict(d, "DB_CHECKPOINT", 0);
5868#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005869 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005870 ADD_INT(d, DB_CURLSN);
5871#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005872#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005873 ADD_INT(d, DB_COMMIT);
5874#endif
5875 ADD_INT(d, DB_CONSUME);
5876#if (DBVER >= 32)
5877 ADD_INT(d, DB_CONSUME_WAIT);
5878#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 ADD_INT(d, DB_CURRENT);
5880#if (DBVER >= 33)
5881 ADD_INT(d, DB_FAST_STAT);
5882#endif
5883 ADD_INT(d, DB_FIRST);
5884 ADD_INT(d, DB_FLUSH);
5885 ADD_INT(d, DB_GET_BOTH);
5886 ADD_INT(d, DB_GET_RECNO);
5887 ADD_INT(d, DB_JOIN_ITEM);
5888 ADD_INT(d, DB_KEYFIRST);
5889 ADD_INT(d, DB_KEYLAST);
5890 ADD_INT(d, DB_LAST);
5891 ADD_INT(d, DB_NEXT);
5892 ADD_INT(d, DB_NEXT_DUP);
5893 ADD_INT(d, DB_NEXT_NODUP);
5894 ADD_INT(d, DB_NODUPDATA);
5895 ADD_INT(d, DB_NOOVERWRITE);
5896 ADD_INT(d, DB_NOSYNC);
5897 ADD_INT(d, DB_POSITION);
5898 ADD_INT(d, DB_PREV);
5899 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005900#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005901 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith1a050f52007-01-05 02:09:06 +00005902#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005903 ADD_INT(d, DB_SET);
5904 ADD_INT(d, DB_SET_RANGE);
5905 ADD_INT(d, DB_SET_RECNO);
5906 ADD_INT(d, DB_WRITECURSOR);
5907
5908 ADD_INT(d, DB_OPFLAGS_MASK);
5909 ADD_INT(d, DB_RMW);
5910#if (DBVER >= 33)
5911 ADD_INT(d, DB_DIRTY_READ);
5912 ADD_INT(d, DB_MULTIPLE);
5913 ADD_INT(d, DB_MULTIPLE_KEY);
5914#endif
5915
Gregory P. Smith29602d22006-01-24 09:46:48 +00005916#if (DBVER >= 44)
5917 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5918 ADD_INT(d, DB_READ_COMMITTED);
5919#endif
5920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005921#if (DBVER >= 33)
5922 ADD_INT(d, DB_DONOTINDEX);
5923#endif
5924
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005925#if (DBVER >= 41)
5926 _addIntToDict(d, "DB_INCOMPLETE", 0);
5927#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005928 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005929#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930 ADD_INT(d, DB_KEYEMPTY);
5931 ADD_INT(d, DB_KEYEXIST);
5932 ADD_INT(d, DB_LOCK_DEADLOCK);
5933 ADD_INT(d, DB_LOCK_NOTGRANTED);
5934 ADD_INT(d, DB_NOSERVER);
5935 ADD_INT(d, DB_NOSERVER_HOME);
5936 ADD_INT(d, DB_NOSERVER_ID);
5937 ADD_INT(d, DB_NOTFOUND);
5938 ADD_INT(d, DB_OLD_VERSION);
5939 ADD_INT(d, DB_RUNRECOVERY);
5940 ADD_INT(d, DB_VERIFY_BAD);
5941#if (DBVER >= 33)
5942 ADD_INT(d, DB_PAGE_NOTFOUND);
5943 ADD_INT(d, DB_SECONDARY_BAD);
5944#endif
5945#if (DBVER >= 40)
5946 ADD_INT(d, DB_STAT_CLEAR);
5947 ADD_INT(d, DB_REGION_INIT);
5948 ADD_INT(d, DB_NOLOCKING);
5949 ADD_INT(d, DB_YIELDCPU);
5950 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5951 ADD_INT(d, DB_NOPANIC);
5952#endif
5953
Gregory P. Smith41631e82003-09-21 00:08:14 +00005954#if (DBVER >= 42)
5955 ADD_INT(d, DB_TIME_NOTGRANTED);
5956 ADD_INT(d, DB_TXN_NOT_DURABLE);
5957 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5958 ADD_INT(d, DB_LOG_AUTOREMOVE);
5959 ADD_INT(d, DB_DIRECT_LOG);
5960 ADD_INT(d, DB_DIRECT_DB);
5961 ADD_INT(d, DB_INIT_REP);
5962 ADD_INT(d, DB_ENCRYPT);
5963 ADD_INT(d, DB_CHKSUM);
5964#endif
5965
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005966#if (DBVER >= 43)
5967 ADD_INT(d, DB_LOG_INMEMORY);
5968 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005969 ADD_INT(d, DB_SEQ_DEC);
5970 ADD_INT(d, DB_SEQ_INC);
5971 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005972#endif
5973
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005974#if (DBVER >= 41)
5975 ADD_INT(d, DB_ENCRYPT_AES);
5976 ADD_INT(d, DB_AUTO_COMMIT);
5977#else
5978 /* allow berkeleydb 4.1 aware apps to run on older versions */
5979 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5980#endif
5981
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005982 ADD_INT(d, EINVAL);
5983 ADD_INT(d, EACCES);
5984 ADD_INT(d, ENOSPC);
5985 ADD_INT(d, ENOMEM);
5986 ADD_INT(d, EAGAIN);
5987 ADD_INT(d, EBUSY);
5988 ADD_INT(d, EEXIST);
5989 ADD_INT(d, ENOENT);
5990 ADD_INT(d, EPERM);
5991
Barry Warsaw1baa9822003-03-31 19:51:29 +00005992#if (DBVER >= 40)
5993 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5994 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005996
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005997 /* The exception name must be correct for pickled exception *
5998 * objects to unpickle properly. */
5999#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6000#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6001#else
6002#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6003#endif
6004
6005 /* All the rest of the exceptions derive only from DBError */
6006#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6007 PyDict_SetItemString(d, #name, name)
6008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006009 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006010 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6011 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006012
Gregory P. Smithe9477062005-06-04 06:46:59 +00006013 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6014 * from both DBError and KeyError, since the API only supports
6015 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006017 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6018 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006019 Py_file_input, d, d);
6020 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006021 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006022 PyDict_DelItemString(d, "KeyError");
6023
6024
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006025#if !INCOMPLETE_IS_WARNING
6026 MAKE_EX(DBIncompleteError);
6027#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006028 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006029 MAKE_EX(DBKeyEmptyError);
6030 MAKE_EX(DBKeyExistError);
6031 MAKE_EX(DBLockDeadlockError);
6032 MAKE_EX(DBLockNotGrantedError);
6033 MAKE_EX(DBOldVersionError);
6034 MAKE_EX(DBRunRecoveryError);
6035 MAKE_EX(DBVerifyBadError);
6036 MAKE_EX(DBNoServerError);
6037 MAKE_EX(DBNoServerHomeError);
6038 MAKE_EX(DBNoServerIDError);
6039#if (DBVER >= 33)
6040 MAKE_EX(DBPageNotFoundError);
6041 MAKE_EX(DBSecondaryBadError);
6042#endif
6043
6044 MAKE_EX(DBInvalidArgError);
6045 MAKE_EX(DBAccessError);
6046 MAKE_EX(DBNoSpaceError);
6047 MAKE_EX(DBNoMemoryError);
6048 MAKE_EX(DBAgainError);
6049 MAKE_EX(DBBusyError);
6050 MAKE_EX(DBFileExistsError);
6051 MAKE_EX(DBNoSuchFileError);
6052 MAKE_EX(DBPermissionsError);
6053
6054#undef MAKE_EX
6055
6056 /* Check for errors */
6057 if (PyErr_Occurred()) {
6058 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006059 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006060 }
6061}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006062
6063/* allow this module to be named _pybsddb so that it can be installed
6064 * and imported on top of python >= 2.3 that includes its own older
6065 * copy of the library named _bsddb without importing the old version. */
6066DL_EXPORT(void) init_pybsddb(void)
6067{
6068 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6069 init_bsddb();
6070}