blob: d03f72b844698169f994acf5f420224cf5f73d25 [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
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
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 *
Gregory P. Smithf8057852007-09-09 20:25:00 +000051 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000052 *
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>
Gregory P. Smith39250532007-10-09 06:02:21 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000100#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000101typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000102#endif
103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Gregory P. Smith39250532007-10-09 06:02:21 +0000194#if PYTHON_API_VERSION < 1010
195#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000196#endif
197
Gregory P. Smith31c50652004-06-28 01:20:40 +0000198
Gregory P. Smith39250532007-10-09 06:02:21 +0000199/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000200#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000201#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000202
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203
204staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
205
Martin v. Löwis68192102007-07-21 06:55:02 +0000206#define DBObject_Check(v) (Py_Type(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_Type(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_Type(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_Type(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_Type(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000211#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +0000212#define DBSequenceObject_Check(v) (Py_Type(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
254#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000255 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000256
257
258static int makeDBError(int err);
259
260
261/* Return the access method type of the DBObject */
262static int _DB_get_type(DBObject* self)
263{
264#if (DBVER >= 33)
265 DBTYPE type;
266 int err;
267 err = self->db->get_type(self->db, &type);
268 if (makeDBError(err)) {
269 return -1;
270 }
271 return type;
272#else
273 return self->db->get_type(self->db);
274#endif
275}
276
277
278/* Create a DBT structure (containing key and data values) from Python
279 strings. Returns 1 on success, 0 on an error. */
280static int make_dbt(PyObject* obj, DBT* dbt)
281{
282 CLEAR_DBT(*dbt);
283 if (obj == Py_None) {
284 /* no need to do anything, the structure has already been zeroed */
285 }
286 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
287 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000288 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000289 return 0;
290 }
291 return 1;
292}
293
294
295/* Recno and Queue DBs can have integer keys. This function figures out
296 what's been given, verifies that it's allowed, and then makes the DBT.
297
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000298 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000299static int
300make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301{
302 db_recno_t recno;
303 int type;
304
305 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000306 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000307 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000308 if (type == -1)
309 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000310 if (type == DB_RECNO || type == DB_QUEUE) {
311 PyErr_SetString(
312 PyExc_TypeError,
313 "None keys not allowed for Recno and Queue DB's");
314 return 0;
315 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000316 /* no need to do anything, the structure has already been zeroed */
317 }
318
319 else if (PyString_Check(keyobj)) {
320 /* verify access method type */
321 type = _DB_get_type(self);
322 if (type == -1)
323 return 0;
324 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000325 PyErr_SetString(
326 PyExc_TypeError,
327 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000328 return 0;
329 }
330
Gregory P. Smith10bed542007-10-09 06:50:43 +0000331 /*
332 * NOTE(gps): I don't like doing a data copy here, it seems
333 * wasteful. But without a clean way to tell FREE_DBT if it
334 * should free key->data or not we have to. Other places in
335 * the code check for DB_THREAD and forceably set DBT_MALLOC
336 * when we otherwise would leave flags 0 to indicate that.
337 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000338 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000339 if (key->data == NULL) {
340 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
341 return 0;
342 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000343 memcpy(key->data, PyString_AS_STRING(keyobj),
344 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000345 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346 key->size = PyString_GET_SIZE(keyobj);
347 }
348
349 else if (PyInt_Check(keyobj)) {
350 /* verify access method type */
351 type = _DB_get_type(self);
352 if (type == -1)
353 return 0;
354 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000355 /* if BTREE then an Integer key is allowed with the
356 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000357 *pflags |= DB_SET_RECNO;
358 }
359 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000360 PyErr_SetString(
361 PyExc_TypeError,
362 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000363 return 0;
364 }
365
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000366 /* Make a key out of the requested recno, use allocated space so DB
367 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000368 recno = PyInt_AS_LONG(keyobj);
369 key->data = malloc(sizeof(db_recno_t));
370 if (key->data == NULL) {
371 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
372 return 0;
373 }
374 key->ulen = key->size = sizeof(db_recno_t);
375 memcpy(key->data, &recno, sizeof(db_recno_t));
376 key->flags = DB_DBT_REALLOC;
377 }
378 else {
379 PyErr_Format(PyExc_TypeError,
380 "String or Integer object expected for key, %s found",
Martin v. Löwis68192102007-07-21 06:55:02 +0000381 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382 return 0;
383 }
384
385 return 1;
386}
387
388
389/* Add partial record access to an existing DBT data struct.
390 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
391 and the data storage/retrieval will be done using dlen and doff. */
392static int add_partial_dbt(DBT* d, int dlen, int doff) {
393 /* if neither were set we do nothing (-1 is the default value) */
394 if ((dlen == -1) && (doff == -1)) {
395 return 1;
396 }
397
398 if ((dlen < 0) || (doff < 0)) {
399 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
400 return 0;
401 }
402
403 d->flags = d->flags | DB_DBT_PARTIAL;
404 d->dlen = (unsigned int) dlen;
405 d->doff = (unsigned int) doff;
406 return 1;
407}
408
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000409/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
410/* TODO: make this use the native libc strlcpy() when available (BSD) */
411unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
412{
413 unsigned int srclen, copylen;
414
415 srclen = strlen(src);
416 if (n <= 0)
417 return srclen;
418 copylen = (srclen > n-1) ? n-1 : srclen;
419 /* populate dest[0] thru dest[copylen-1] */
420 memcpy(dest, src, copylen);
421 /* guarantee null termination */
422 dest[copylen] = 0;
423
424 return srclen;
425}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000426
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000427/* Callback used to save away more information about errors from the DB
428 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000429static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000430#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000432#else
433static void _db_errorCallback(const DB_ENV *db_env,
434 const char* prefix, const char* msg)
435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000436{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000437 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000438}
439
440
441/* make a nice exception object to raise for errors. */
442static int makeDBError(int err)
443{
444 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000445 PyObject *errObj = NULL;
446 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000448 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000449
450 switch (err) {
451 case 0: /* successful, no error */ break;
452
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000453#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 case DB_INCOMPLETE:
455#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000456 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
457 /* Ensure that bytes_left never goes negative */
458 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
459 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
460 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000462 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000463 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000464 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000466
467#else /* do an exception instead */
468 errObj = DBIncompleteError;
469#endif
470 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000471#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000472
473 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
474 case DB_KEYEXIST: errObj = DBKeyExistError; break;
475 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
476 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
477 case DB_NOTFOUND: errObj = DBNotFoundError; break;
478 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
479 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
480 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
481 case DB_NOSERVER: errObj = DBNoServerError; break;
482 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
483 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
484#if (DBVER >= 33)
485 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
486 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
487#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000488 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000489
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000490#if (DBVER >= 43)
491 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
492 case ENOMEM: errObj = PyExc_MemoryError; break;
493#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000494 case EINVAL: errObj = DBInvalidArgError; break;
495 case EACCES: errObj = DBAccessError; break;
496 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000497 case EAGAIN: errObj = DBAgainError; break;
498 case EBUSY : errObj = DBBusyError; break;
499 case EEXIST: errObj = DBFileExistsError; break;
500 case ENOENT: errObj = DBNoSuchFileError; break;
501 case EPERM : errObj = DBPermissionsError; break;
502
503 default: errObj = DBError; break;
504 }
505
506 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000507 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
508 /* Ensure that bytes_left never goes negative */
509 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
510 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
511 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000513 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000515 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000516
517 errTuple = Py_BuildValue("(is)", err, errTxt);
518 PyErr_SetObject(errObj, errTuple);
519 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520 }
521
522 return ((errObj != NULL) || exceptionRaised);
523}
524
525
526
527/* set a type exception */
528static void makeTypeError(char* expected, PyObject* found)
529{
530 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis68192102007-07-21 06:55:02 +0000531 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532}
533
534
535/* verify that an obj is either None or a DBTxn, and set the txn pointer */
536static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
537{
538 if (txnobj == Py_None || txnobj == NULL) {
539 *txn = NULL;
540 return 1;
541 }
542 if (DBTxnObject_Check(txnobj)) {
543 *txn = ((DBTxnObject*)txnobj)->txn;
544 return 1;
545 }
546 else
547 makeTypeError("DBTxn", txnobj);
548 return 0;
549}
550
551
552/* Delete a key from a database
553 Returns 0 on success, -1 on an error. */
554static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
555{
556 int err;
557
558 MYDB_BEGIN_ALLOW_THREADS;
559 err = self->db->del(self->db, txn, key, 0);
560 MYDB_END_ALLOW_THREADS;
561 if (makeDBError(err)) {
562 return -1;
563 }
564 self->haveStat = 0;
565 return 0;
566}
567
568
569/* Store a key into a database
570 Returns 0 on success, -1 on an error. */
571static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
572{
573 int err;
574
575 MYDB_BEGIN_ALLOW_THREADS;
576 err = self->db->put(self->db, txn, key, data, flags);
577 MYDB_END_ALLOW_THREADS;
578 if (makeDBError(err)) {
579 return -1;
580 }
581 self->haveStat = 0;
582 return 0;
583}
584
585/* Get a key/data pair from a cursor */
586static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
587 PyObject *args, PyObject *kwargs, char *format)
588{
589 int err;
590 PyObject* retval = NULL;
591 DBT key, data;
592 int dlen = -1;
593 int doff = -1;
594 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000595 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596
597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
598 &flags, &dlen, &doff))
599 return NULL;
600
601 CHECK_CURSOR_NOT_CLOSED(self);
602
603 flags |= extra_flags;
604 CLEAR_DBT(key);
605 CLEAR_DBT(data);
606 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
607 /* Tell BerkeleyDB to malloc the return value (thread safe) */
608 data.flags = DB_DBT_MALLOC;
609 key.flags = DB_DBT_MALLOC;
610 }
611 if (!add_partial_dbt(&data, dlen, doff))
612 return NULL;
613
614 MYDB_BEGIN_ALLOW_THREADS;
615 err = self->dbc->c_get(self->dbc, &key, &data, flags);
616 MYDB_END_ALLOW_THREADS;
617
Gregory P. Smithe9477062005-06-04 06:46:59 +0000618 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
619 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620 Py_INCREF(Py_None);
621 retval = Py_None;
622 }
623 else if (makeDBError(err)) {
624 retval = NULL;
625 }
626 else { /* otherwise, success! */
627
628 /* if Recno or Queue, return the key as an Int */
629 switch (_DB_get_type(self->mydb)) {
630 case -1:
631 retval = NULL;
632 break;
633
634 case DB_RECNO:
635 case DB_QUEUE:
636 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
637 data.data, data.size);
638 break;
639 case DB_HASH:
640 case DB_BTREE:
641 default:
642 retval = Py_BuildValue("s#s#", key.data, key.size,
643 data.data, data.size);
644 break;
645 }
646 }
647 if (!err) {
648 FREE_DBT(key);
649 FREE_DBT(data);
650 }
651 return retval;
652}
653
654
655/* add an integer to a dictionary using the given name as a key */
656static void _addIntToDict(PyObject* dict, char *name, int value)
657{
658 PyObject* v = PyInt_FromLong((long) value);
659 if (!v || PyDict_SetItemString(dict, name, v))
660 PyErr_Clear();
661
662 Py_XDECREF(v);
663}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000664
665/* The same, when the value is a time_t */
666static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
667{
668 PyObject* v;
669 /* if the value fits in regular int, use that. */
670#ifdef HAVE_LONG_LONG
671 if (sizeof(time_t) > sizeof(long))
672 v = PyLong_FromLongLong((PY_LONG_LONG) value);
673 else
674#endif
675 v = PyInt_FromLong((long) value);
676 if (!v || PyDict_SetItemString(dict, name, v))
677 PyErr_Clear();
678
679 Py_XDECREF(v);
680}
681
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000682#if (DBVER >= 43)
683/* add an db_seq_t to a dictionary using the given name as a key */
684static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
685{
686 PyObject* v = PyLong_FromLongLong(value);
687 if (!v || PyDict_SetItemString(dict, name, v))
688 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000690 Py_XDECREF(v);
691}
692#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000693
694
695
696/* --------------------------------------------------------------------- */
697/* Allocators and deallocators */
698
699static DBObject*
700newDBObject(DBEnvObject* arg, int flags)
701{
702 DBObject* self;
703 DB_ENV* db_env = NULL;
704 int err;
705
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000707 if (self == NULL)
708 return NULL;
709
710 self->haveStat = 0;
711 self->flags = 0;
712 self->setflags = 0;
713 self->myenvobj = NULL;
714#if (DBVER >= 33)
715 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000716 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000717 self->primaryDBType = 0;
718#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000719 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720
721 /* keep a reference to our python DBEnv object */
722 if (arg) {
723 Py_INCREF(arg);
724 self->myenvobj = arg;
725 db_env = arg->db_env;
726 }
727
728 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000729 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000730 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000731 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
732 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000733
734 MYDB_BEGIN_ALLOW_THREADS;
735 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000736 if (self->db != NULL) {
737 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000739 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000740#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000741 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000743 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
744 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000745 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000746 if (makeDBError(err)) {
747 if (self->myenvobj) {
748 Py_DECREF(self->myenvobj);
749 self->myenvobj = NULL;
750 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000751 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 self = NULL;
753 }
754 return self;
755}
756
757
758static void
759DB_dealloc(DBObject* self)
760{
761 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000762 /* avoid closing a DB when its DBEnv has been closed out from under
763 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000764 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000765 (self->myenvobj && self->myenvobj->db_env))
766 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000767 MYDB_BEGIN_ALLOW_THREADS;
768 self->db->close(self->db, 0);
769 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770 } else {
771 PyErr_Warn(PyExc_RuntimeWarning,
772 "DB could not be closed in destructor: DBEnv already closed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773 }
774 self->db = NULL;
775 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000776 if (self->in_weakreflist != NULL) {
777 PyObject_ClearWeakRefs((PyObject *) self);
778 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000779 if (self->myenvobj) {
780 Py_DECREF(self->myenvobj);
781 self->myenvobj = NULL;
782 }
783#if (DBVER >= 33)
784 if (self->associateCallback != NULL) {
785 Py_DECREF(self->associateCallback);
786 self->associateCallback = NULL;
787 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000788 if (self->btCompareCallback != NULL) {
789 Py_DECREF(self->btCompareCallback);
790 self->btCompareCallback = NULL;
791 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794}
795
796
797static DBCursorObject*
798newDBCursorObject(DBC* dbc, DBObject* db)
799{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000800 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000801 if (self == NULL)
802 return NULL;
803
804 self->dbc = dbc;
805 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000806 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000807 Py_INCREF(self->mydb);
808 return self;
809}
810
811
812static void
813DBCursor_dealloc(DBCursorObject* self)
814{
815 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000816
Gregory P. Smitha703a212003-11-03 01:04:41 +0000817 if (self->in_weakreflist != NULL) {
818 PyObject_ClearWeakRefs((PyObject *) self);
819 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000820
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821 if (self->dbc != NULL) {
822 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000823 /* If the underlying database has been closed, we don't
824 need to do anything. If the environment has been closed
825 we need to leak, as BerkeleyDB will crash trying to access
826 the environment. There was an exception when the
827 user closed the environment even though there still was
828 a database open. */
829 if (self->mydb->db && self->mydb->myenvobj &&
830 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000831 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 self->dbc = NULL;
833 MYDB_END_ALLOW_THREADS;
834 }
835 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000837}
838
839
840static DBEnvObject*
841newDBEnvObject(int flags)
842{
843 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000844 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000845 if (self == NULL)
846 return NULL;
847
848 self->closed = 1;
849 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000850 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
851 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000852 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853
854 MYDB_BEGIN_ALLOW_THREADS;
855 err = db_env_create(&self->db_env, flags);
856 MYDB_END_ALLOW_THREADS;
857 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000858 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 self = NULL;
860 }
861 else {
862 self->db_env->set_errcall(self->db_env, _db_errorCallback);
863 }
864 return self;
865}
866
867
868static void
869DBEnv_dealloc(DBEnvObject* self)
870{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000871 if (self->in_weakreflist != NULL) {
872 PyObject_ClearWeakRefs((PyObject *) self);
873 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000874
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000875 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876 MYDB_BEGIN_ALLOW_THREADS;
877 self->db_env->close(self->db_env, 0);
878 MYDB_END_ALLOW_THREADS;
879 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000880 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881}
882
883
884static DBTxnObject*
885newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
886{
887 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000888 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 if (self == NULL)
890 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000891 Py_INCREF(myenv);
892 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000893 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894
895 MYDB_BEGIN_ALLOW_THREADS;
896#if (DBVER >= 40)
897 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
898#else
899 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
900#endif
901 MYDB_END_ALLOW_THREADS;
902 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000903 Py_DECREF(self->env);
904 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905 self = NULL;
906 }
907 return self;
908}
909
910
911static void
912DBTxn_dealloc(DBTxnObject* self)
913{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000914 if (self->in_weakreflist != NULL) {
915 PyObject_ClearWeakRefs((PyObject *) self);
916 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917
Gregory P. Smith31c50652004-06-28 01:20:40 +0000918 if (self->txn) {
919 /* it hasn't been finalized, abort it! */
920 MYDB_BEGIN_ALLOW_THREADS;
921#if (DBVER >= 40)
922 self->txn->abort(self->txn);
923#else
924 txn_abort(self->txn);
925#endif
926 MYDB_END_ALLOW_THREADS;
927 PyErr_Warn(PyExc_RuntimeWarning,
928 "DBTxn aborted in destructor. No prior commit() or abort().");
929 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930
Neal Norwitz62a21122006-01-25 05:21:55 +0000931 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000933}
934
935
936static DBLockObject*
937newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
938 db_lockmode_t lock_mode, int flags)
939{
940 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000941 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 if (self == NULL)
943 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000944 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945
946 MYDB_BEGIN_ALLOW_THREADS;
947#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000948 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
949 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000950#else
951 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
952#endif
953 MYDB_END_ALLOW_THREADS;
954 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000955 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956 self = NULL;
957 }
958
959 return self;
960}
961
962
963static void
964DBLock_dealloc(DBLockObject* self)
965{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000966 if (self->in_weakreflist != NULL) {
967 PyObject_ClearWeakRefs((PyObject *) self);
968 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000969 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972}
973
974
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000975#if (DBVER >= 43)
976static DBSequenceObject*
977newDBSequenceObject(DBObject* mydb, int flags)
978{
979 int err;
980 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
981 if (self == NULL)
982 return NULL;
983 Py_INCREF(mydb);
984 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000985 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000986
987
988 MYDB_BEGIN_ALLOW_THREADS;
989 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
990 MYDB_END_ALLOW_THREADS;
991 if (makeDBError(err)) {
992 Py_DECREF(self->mydb);
993 PyObject_Del(self);
994 self = NULL;
995 }
996
997 return self;
998}
999
1000
1001static void
1002DBSequence_dealloc(DBSequenceObject* self)
1003{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001004 if (self->in_weakreflist != NULL) {
1005 PyObject_ClearWeakRefs((PyObject *) self);
1006 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001007
1008 Py_DECREF(self->mydb);
1009 PyObject_Del(self);
1010}
1011#endif
1012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013/* --------------------------------------------------------------------- */
1014/* DB methods */
1015
1016static PyObject*
1017DB_append(DBObject* self, PyObject* args)
1018{
1019 PyObject* txnobj = NULL;
1020 PyObject* dataobj;
1021 db_recno_t recno;
1022 DBT key, data;
1023 DB_TXN *txn = NULL;
1024
Georg Brandl96a8c392006-05-29 21:04:52 +00001025 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 return NULL;
1027
1028 CHECK_DB_NOT_CLOSED(self);
1029
1030 /* make a dummy key out of a recno */
1031 recno = 0;
1032 CLEAR_DBT(key);
1033 key.data = &recno;
1034 key.size = sizeof(recno);
1035 key.ulen = key.size;
1036 key.flags = DB_DBT_USERMEM;
1037
1038 if (!make_dbt(dataobj, &data)) return NULL;
1039 if (!checkTxnObj(txnobj, &txn)) return NULL;
1040
1041 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1042 return NULL;
1043
1044 return PyInt_FromLong(recno);
1045}
1046
1047
1048#if (DBVER >= 33)
1049
1050static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001051_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1052 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001053{
1054 int retval = DB_DONOTINDEX;
1055 DBObject* secondaryDB = (DBObject*)db->app_private;
1056 PyObject* callback = secondaryDB->associateCallback;
1057 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001059 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060
1061
1062 if (callback != NULL) {
1063 MYDB_BEGIN_BLOCK_THREADS;
1064
Thomas Woutersb3153832006-03-08 01:47:19 +00001065 if (type == DB_RECNO || type == DB_QUEUE)
1066 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1067 priData->data, priData->size);
1068 else
1069 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1070 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001071 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001072 result = PyEval_CallObject(callback, args);
1073 }
1074 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001075 PyErr_Print();
1076 }
1077 else if (result == Py_None) {
1078 retval = DB_DONOTINDEX;
1079 }
1080 else if (PyInt_Check(result)) {
1081 retval = PyInt_AsLong(result);
1082 }
1083 else if (PyString_Check(result)) {
1084 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001085 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086
1087 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001088 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001089 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1090 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001091 if (secKey->data) {
1092 memcpy(secKey->data, data, size);
1093 secKey->size = size;
1094 retval = 0;
1095 }
1096 else {
1097 PyErr_SetString(PyExc_MemoryError,
1098 "malloc failed in _db_associateCallback");
1099 PyErr_Print();
1100 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001101 }
1102 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001103 PyErr_SetString(
1104 PyExc_TypeError,
1105 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106 PyErr_Print();
1107 }
1108
Thomas Woutersb3153832006-03-08 01:47:19 +00001109 Py_XDECREF(args);
1110 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111
1112 MYDB_END_BLOCK_THREADS;
1113 }
1114 return retval;
1115}
1116
1117
1118static PyObject*
1119DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1120{
1121 int err, flags=0;
1122 DBObject* secondaryDB;
1123 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001124#if (DBVER >= 41)
1125 PyObject *txnobj = NULL;
1126 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001127 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001128 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001129#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001130 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001131#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001133#if (DBVER >= 41)
1134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1135 &secondaryDB, &callback, &flags,
1136 &txnobj)) {
1137#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001138 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001139 &secondaryDB, &callback, &flags)) {
1140#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001141 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001142 }
1143
1144#if (DBVER >= 41)
1145 if (!checkTxnObj(txnobj, &txn)) return NULL;
1146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147
1148 CHECK_DB_NOT_CLOSED(self);
1149 if (!DBObject_Check(secondaryDB)) {
1150 makeTypeError("DB", (PyObject*)secondaryDB);
1151 return NULL;
1152 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001153 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154 if (callback == Py_None) {
1155 callback = NULL;
1156 }
1157 else if (!PyCallable_Check(callback)) {
1158 makeTypeError("Callable", callback);
1159 return NULL;
1160 }
1161
1162 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001163 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001164 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001165 secondaryDB->associateCallback = callback;
1166 secondaryDB->primaryDBType = _DB_get_type(self);
1167
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001168 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1169 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1170 * The global interepreter lock is not initialized until the first
1171 * thread is created using thread.start_new_thread() or fork() is
1172 * called. that would cause the ALLOW_THREADS here to segfault due
1173 * to a null pointer reference if no threads or child processes
1174 * have been created. This works around that and is a no-op if
1175 * threads have already been initialized.
1176 * (see pybsddb-users mailing list post on 2002-08-07)
1177 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001178#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001179 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001180#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001182#if (DBVER >= 41)
1183 err = self->db->associate(self->db,
1184 txn,
1185 secondaryDB->db,
1186 _db_associateCallback,
1187 flags);
1188#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001189 err = self->db->associate(self->db,
1190 secondaryDB->db,
1191 _db_associateCallback,
1192 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001194 MYDB_END_ALLOW_THREADS;
1195
1196 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001197 Py_XDECREF(secondaryDB->associateCallback);
1198 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001199 secondaryDB->primaryDBType = 0;
1200 }
1201
1202 RETURN_IF_ERR();
1203 RETURN_NONE();
1204}
1205
1206
1207#endif
1208
1209
1210static PyObject*
1211DB_close(DBObject* self, PyObject* args)
1212{
1213 int err, flags=0;
1214 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1215 return NULL;
1216 if (self->db != NULL) {
1217 if (self->myenvobj)
1218 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001220 self->db = NULL;
1221 RETURN_IF_ERR();
1222 }
1223 RETURN_NONE();
1224}
1225
1226
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227static PyObject*
1228_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1229{
1230 int err, flags=0, type;
1231 PyObject* txnobj = NULL;
1232 PyObject* retval = NULL;
1233 DBT key, data;
1234 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001235 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236
1237 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1238 &txnobj, &flags))
1239 return NULL;
1240
1241 CHECK_DB_NOT_CLOSED(self);
1242 type = _DB_get_type(self);
1243 if (type == -1)
1244 return NULL;
1245 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246 PyErr_SetString(PyExc_TypeError,
1247 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001248 return NULL;
1249 }
1250 if (!checkTxnObj(txnobj, &txn))
1251 return NULL;
1252
1253 CLEAR_DBT(key);
1254 CLEAR_DBT(data);
1255 if (CHECK_DBFLAG(self, DB_THREAD)) {
1256 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1257 data.flags = DB_DBT_MALLOC;
1258 key.flags = DB_DBT_MALLOC;
1259 }
1260
1261 MYDB_BEGIN_ALLOW_THREADS;
1262 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1263 MYDB_END_ALLOW_THREADS;
1264
Gregory P. Smithe9477062005-06-04 06:46:59 +00001265 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1266 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001267 err = 0;
1268 Py_INCREF(Py_None);
1269 retval = Py_None;
1270 }
1271 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001272 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1273 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001274 FREE_DBT(key);
1275 FREE_DBT(data);
1276 }
1277
1278 RETURN_IF_ERR();
1279 return retval;
1280}
1281
1282static PyObject*
1283DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1284{
1285 return _DB_consume(self, args, kwargs, DB_CONSUME);
1286}
1287
1288static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001289DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1290 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291{
1292 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1293}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294
1295
1296static PyObject*
1297DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1298{
1299 int err, flags=0;
1300 DBC* dbc;
1301 PyObject* txnobj = NULL;
1302 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001303 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001304
1305 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1306 &txnobj, &flags))
1307 return NULL;
1308 CHECK_DB_NOT_CLOSED(self);
1309 if (!checkTxnObj(txnobj, &txn))
1310 return NULL;
1311
1312 MYDB_BEGIN_ALLOW_THREADS;
1313 err = self->db->cursor(self->db, txn, &dbc, flags);
1314 MYDB_END_ALLOW_THREADS;
1315 RETURN_IF_ERR();
1316 return (PyObject*) newDBCursorObject(dbc, self);
1317}
1318
1319
1320static PyObject*
1321DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1322{
1323 PyObject* txnobj = NULL;
1324 int flags = 0;
1325 PyObject* keyobj;
1326 DBT key;
1327 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001328 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001329
1330 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1331 &keyobj, &txnobj, &flags))
1332 return NULL;
1333 CHECK_DB_NOT_CLOSED(self);
1334 if (!make_key_dbt(self, keyobj, &key, NULL))
1335 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001336 if (!checkTxnObj(txnobj, &txn)) {
1337 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001339 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001341 if (-1 == _DB_delete(self, txn, &key, 0)) {
1342 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001344 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345
1346 FREE_DBT(key);
1347 RETURN_NONE();
1348}
1349
1350
1351static PyObject*
1352DB_fd(DBObject* self, PyObject* args)
1353{
1354 int err, the_fd;
1355
1356 if (!PyArg_ParseTuple(args,":fd"))
1357 return NULL;
1358 CHECK_DB_NOT_CLOSED(self);
1359
1360 MYDB_BEGIN_ALLOW_THREADS;
1361 err = self->db->fd(self->db, &the_fd);
1362 MYDB_END_ALLOW_THREADS;
1363 RETURN_IF_ERR();
1364 return PyInt_FromLong(the_fd);
1365}
1366
1367
1368static PyObject*
1369DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1370{
1371 int err, flags=0;
1372 PyObject* txnobj = NULL;
1373 PyObject* keyobj;
1374 PyObject* dfltobj = NULL;
1375 PyObject* retval = NULL;
1376 int dlen = -1;
1377 int doff = -1;
1378 DBT key, data;
1379 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001380 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001381 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001382
1383 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001384 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1385 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386 return NULL;
1387
1388 CHECK_DB_NOT_CLOSED(self);
1389 if (!make_key_dbt(self, keyobj, &key, &flags))
1390 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001391 if (!checkTxnObj(txnobj, &txn)) {
1392 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001394 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001395
1396 CLEAR_DBT(data);
1397 if (CHECK_DBFLAG(self, DB_THREAD)) {
1398 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1399 data.flags = DB_DBT_MALLOC;
1400 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001401 if (!add_partial_dbt(&data, dlen, doff)) {
1402 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001404 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405
1406 MYDB_BEGIN_ALLOW_THREADS;
1407 err = self->db->get(self->db, txn, &key, &data, flags);
1408 MYDB_END_ALLOW_THREADS;
1409
Gregory P. Smithe9477062005-06-04 06:46:59 +00001410 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 err = 0;
1412 Py_INCREF(dfltobj);
1413 retval = dfltobj;
1414 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001415 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1416 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001417 err = 0;
1418 Py_INCREF(Py_None);
1419 retval = Py_None;
1420 }
1421 else if (!err) {
1422 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001423 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1424 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425 else /* return just the data */
1426 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 FREE_DBT(data);
1428 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001429 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001430
1431 RETURN_IF_ERR();
1432 return retval;
1433}
1434
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001435#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001436static PyObject*
1437DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1438{
1439 int err, flags=0;
1440 PyObject* txnobj = NULL;
1441 PyObject* keyobj;
1442 PyObject* dfltobj = NULL;
1443 PyObject* retval = NULL;
1444 int dlen = -1;
1445 int doff = -1;
1446 DBT key, pkey, data;
1447 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001448 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001449 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001450
1451 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1452 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1453 &doff))
1454 return NULL;
1455
1456 CHECK_DB_NOT_CLOSED(self);
1457 if (!make_key_dbt(self, keyobj, &key, &flags))
1458 return NULL;
1459 if (!checkTxnObj(txnobj, &txn)) {
1460 FREE_DBT(key);
1461 return NULL;
1462 }
1463
1464 CLEAR_DBT(data);
1465 if (CHECK_DBFLAG(self, DB_THREAD)) {
1466 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1467 data.flags = DB_DBT_MALLOC;
1468 }
1469 if (!add_partial_dbt(&data, dlen, doff)) {
1470 FREE_DBT(key);
1471 return NULL;
1472 }
1473
1474 CLEAR_DBT(pkey);
1475 pkey.flags = DB_DBT_MALLOC;
1476
1477 MYDB_BEGIN_ALLOW_THREADS;
1478 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1479 MYDB_END_ALLOW_THREADS;
1480
Gregory P. Smithe9477062005-06-04 06:46:59 +00001481 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001482 err = 0;
1483 Py_INCREF(dfltobj);
1484 retval = dfltobj;
1485 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001486 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1487 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001488 err = 0;
1489 Py_INCREF(Py_None);
1490 retval = Py_None;
1491 }
1492 else if (!err) {
1493 PyObject *pkeyObj;
1494 PyObject *dataObj;
1495 dataObj = PyString_FromStringAndSize(data.data, data.size);
1496
1497 if (self->primaryDBType == DB_RECNO ||
1498 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001499 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001500 else
1501 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1502
1503 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1504 {
1505 PyObject *keyObj;
1506 int type = _DB_get_type(self);
1507 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001508 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001509 else
1510 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001511#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001512 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001513#else
1514 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1515#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001516 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001517 }
1518 else /* return just the pkey and data */
1519 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001520#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001521 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001522#else
1523 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1524#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001525 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001526 Py_DECREF(dataObj);
1527 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001528 FREE_DBT(pkey);
1529 FREE_DBT(data);
1530 }
1531 FREE_DBT(key);
1532
1533 RETURN_IF_ERR();
1534 return retval;
1535}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001536#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001537
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001538
1539/* Return size of entry */
1540static PyObject*
1541DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1542{
1543 int err, flags=0;
1544 PyObject* txnobj = NULL;
1545 PyObject* keyobj;
1546 PyObject* retval = NULL;
1547 DBT key, data;
1548 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001549 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550
1551 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1552 &keyobj, &txnobj))
1553 return NULL;
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001559 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001560 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001561 CLEAR_DBT(data);
1562
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001563 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1564 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001565 data.flags = DB_DBT_USERMEM;
1566 data.ulen = 0;
1567 MYDB_BEGIN_ALLOW_THREADS;
1568 err = self->db->get(self->db, txn, &key, &data, flags);
1569 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001570 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001571 retval = PyInt_FromLong((long)data.size);
1572 err = 0;
1573 }
1574
1575 FREE_DBT(key);
1576 FREE_DBT(data);
1577 RETURN_IF_ERR();
1578 return retval;
1579}
1580
1581
1582static PyObject*
1583DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1584{
1585 int err, flags=0;
1586 PyObject* txnobj = NULL;
1587 PyObject* keyobj;
1588 PyObject* dataobj;
1589 PyObject* retval = NULL;
1590 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001591 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001592 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001593 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001594
1595
1596 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1597 &keyobj, &dataobj, &txnobj, &flags))
1598 return NULL;
1599
1600 CHECK_DB_NOT_CLOSED(self);
1601 if (!make_key_dbt(self, keyobj, &key, NULL))
1602 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001603 if ( !make_dbt(dataobj, &data) ||
1604 !checkTxnObj(txnobj, &txn) )
1605 {
1606 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001607 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001608 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001609
1610 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001611 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001612
1613 if (CHECK_DBFLAG(self, DB_THREAD)) {
1614 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001615 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001616 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617 }
1618
1619 MYDB_BEGIN_ALLOW_THREADS;
1620 err = self->db->get(self->db, txn, &key, &data, flags);
1621 MYDB_END_ALLOW_THREADS;
1622
Gregory P. Smithe9477062005-06-04 06:46:59 +00001623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1624 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001625 err = 0;
1626 Py_INCREF(Py_None);
1627 retval = Py_None;
1628 }
1629 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001630 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001632
1633 /* Even though the flags require DB_DBT_MALLOC, data is not always
1634 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1635 if (data.data != orig_data)
1636 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637 }
1638
1639 FREE_DBT(key);
1640 RETURN_IF_ERR();
1641 return retval;
1642}
1643
1644
1645static PyObject*
1646DB_get_byteswapped(DBObject* self, PyObject* args)
1647{
1648#if (DBVER >= 33)
1649 int err = 0;
1650#endif
1651 int retval = -1;
1652
1653 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1654 return NULL;
1655 CHECK_DB_NOT_CLOSED(self);
1656
1657#if (DBVER >= 33)
1658 MYDB_BEGIN_ALLOW_THREADS;
1659 err = self->db->get_byteswapped(self->db, &retval);
1660 MYDB_END_ALLOW_THREADS;
1661 RETURN_IF_ERR();
1662#else
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 retval = self->db->get_byteswapped(self->db);
1665 MYDB_END_ALLOW_THREADS;
1666#endif
1667 return PyInt_FromLong(retval);
1668}
1669
1670
1671static PyObject*
1672DB_get_type(DBObject* self, PyObject* args)
1673{
1674 int type;
1675
1676 if (!PyArg_ParseTuple(args,":get_type"))
1677 return NULL;
1678 CHECK_DB_NOT_CLOSED(self);
1679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001680 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001681 if (type == -1)
1682 return NULL;
1683 return PyInt_FromLong(type);
1684}
1685
1686
1687static PyObject*
1688DB_join(DBObject* self, PyObject* args)
1689{
1690 int err, flags=0;
1691 int length, x;
1692 PyObject* cursorsObj;
1693 DBC** cursors;
1694 DBC* dbc;
1695
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1697 return NULL;
1698
1699 CHECK_DB_NOT_CLOSED(self);
1700
1701 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001702 PyErr_SetString(PyExc_TypeError,
1703 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
1705 }
1706
1707 length = PyObject_Length(cursorsObj);
1708 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001709 if (!cursors) {
1710 PyErr_NoMemory();
1711 return NULL;
1712 }
1713
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 cursors[length] = NULL;
1715 for (x=0; x<length; x++) {
1716 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001717 if (item == NULL) {
1718 free(cursors);
1719 return NULL;
1720 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001722 PyErr_SetString(PyExc_TypeError,
1723 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001724 free(cursors);
1725 return NULL;
1726 }
1727 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001728 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729 }
1730
1731 MYDB_BEGIN_ALLOW_THREADS;
1732 err = self->db->join(self->db, cursors, &dbc, flags);
1733 MYDB_END_ALLOW_THREADS;
1734 free(cursors);
1735 RETURN_IF_ERR();
1736
Gregory P. Smith7441e652003-11-03 21:35:31 +00001737 /* FIXME: this is a buggy interface. The returned cursor
1738 contains internal references to the passed in cursors
1739 but does not hold python references to them or prevent
1740 them from being closed prematurely. This can cause
1741 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 return (PyObject*) newDBCursorObject(dbc, self);
1743}
1744
1745
1746static PyObject*
1747DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1748{
1749 int err, flags=0;
1750 PyObject* txnobj = NULL;
1751 PyObject* keyobj;
1752 DBT key;
1753 DB_TXN *txn = NULL;
1754 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001755 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756
1757 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1758 &keyobj, &txnobj, &flags))
1759 return NULL;
1760 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001761 if (!make_dbt(keyobj, &key))
1762 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001763 return NULL;
1764 if (!checkTxnObj(txnobj, &txn))
1765 return NULL;
1766
1767 MYDB_BEGIN_ALLOW_THREADS;
1768 err = self->db->key_range(self->db, txn, &key, &range, flags);
1769 MYDB_END_ALLOW_THREADS;
1770
1771 RETURN_IF_ERR();
1772 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1773}
1774
1775
1776static PyObject*
1777DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1778{
1779 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1780 char* filename = NULL;
1781 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001782#if (DBVER >= 41)
1783 PyObject *txnobj = NULL;
1784 DB_TXN *txn = NULL;
1785 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001786 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001787 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1788 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001789 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001790 "filename", "dbtype", "flags", "mode", "txn", NULL};
1791#else
1792 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001793 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001794 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1795 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001796 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001797 "filename", "dbtype", "flags", "mode", NULL};
1798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001800#if (DBVER >= 41)
1801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1802 &filename, &dbname, &type, &flags, &mode,
1803 &txnobj))
1804#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001806 &filename, &dbname, &type, &flags,
1807 &mode))
1808#endif
1809 {
1810 PyErr_Clear();
1811 type = DB_UNKNOWN; flags = 0; mode = 0660;
1812 filename = NULL; dbname = NULL;
1813#if (DBVER >= 41)
1814 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1815 kwnames_basic,
1816 &filename, &type, &flags, &mode,
1817 &txnobj))
1818 return NULL;
1819#else
1820 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1821 kwnames_basic,
1822 &filename, &type, &flags, &mode))
1823 return NULL;
1824#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 }
1826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827#if (DBVER >= 41)
1828 if (!checkTxnObj(txnobj, &txn)) return NULL;
1829#endif
1830
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001832 PyObject *t = Py_BuildValue("(is)", 0,
1833 "Cannot call open() twice for DB object");
1834 PyErr_SetObject(DBError, t);
1835 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001836 return NULL;
1837 }
1838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001839#if 0 && (DBVER >= 41)
1840 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1841 && (self->myenvobj->flags & DB_INIT_TXN))
1842 {
1843 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1844 * explicitly passed) but we are in a transaction ready environment:
1845 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1846 * to work on BerkeleyDB 4.1 without needing to modify their
1847 * DBEnv or DB open calls.
1848 * TODO make this behaviour of the library configurable.
1849 */
1850 flags |= DB_AUTO_COMMIT;
1851 }
1852#endif
1853
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001855#if (DBVER >= 41)
1856 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1857#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001859#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860 MYDB_END_ALLOW_THREADS;
1861 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001862 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863 self->db = NULL;
1864 return NULL;
1865 }
1866
1867 self->flags = flags;
1868 RETURN_NONE();
1869}
1870
1871
1872static PyObject*
1873DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1874{
1875 int flags=0;
1876 PyObject* txnobj = NULL;
1877 int dlen = -1;
1878 int doff = -1;
1879 PyObject* keyobj, *dataobj, *retval;
1880 DBT key, data;
1881 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001882 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001883 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001884
1885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1886 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1887 return NULL;
1888
1889 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001890 if (!make_key_dbt(self, keyobj, &key, NULL))
1891 return NULL;
1892 if ( !make_dbt(dataobj, &data) ||
1893 !add_partial_dbt(&data, dlen, doff) ||
1894 !checkTxnObj(txnobj, &txn) )
1895 {
1896 FREE_DBT(key);
1897 return NULL;
1898 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001899
1900 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1901 FREE_DBT(key);
1902 return NULL;
1903 }
1904
1905 if (flags & DB_APPEND)
1906 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1907 else {
1908 retval = Py_None;
1909 Py_INCREF(retval);
1910 }
1911 FREE_DBT(key);
1912 return retval;
1913}
1914
1915
1916
1917static PyObject*
1918DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1919{
1920 char* filename;
1921 char* database = NULL;
1922 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001923 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1926 &filename, &database, &flags))
1927 return NULL;
1928 CHECK_DB_NOT_CLOSED(self);
1929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001931 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 RETURN_IF_ERR();
1933 RETURN_NONE();
1934}
1935
1936
1937
1938static PyObject*
1939DB_rename(DBObject* self, PyObject* args)
1940{
1941 char* filename;
1942 char* database;
1943 char* newname;
1944 int err, flags=0;
1945
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1947 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 return NULL;
1949 CHECK_DB_NOT_CLOSED(self);
1950
1951 MYDB_BEGIN_ALLOW_THREADS;
1952 err = self->db->rename(self->db, filename, database, newname, flags);
1953 MYDB_END_ALLOW_THREADS;
1954 RETURN_IF_ERR();
1955 RETURN_NONE();
1956}
1957
1958
1959static PyObject*
1960DB_set_bt_minkey(DBObject* self, PyObject* args)
1961{
1962 int err, minkey;
1963
1964 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1965 return NULL;
1966 CHECK_DB_NOT_CLOSED(self);
1967
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->set_bt_minkey(self->db, minkey);
1970 MYDB_END_ALLOW_THREADS;
1971 RETURN_IF_ERR();
1972 RETURN_NONE();
1973}
1974
Neal Norwitz84562352005-10-20 04:30:15 +00001975#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001976static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001977_default_cmp(const DBT *leftKey,
1978 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001979{
1980 int res;
1981 int lsize = leftKey->size, rsize = rightKey->size;
1982
Georg Brandlef1701f2006-03-07 14:57:48 +00001983 res = memcmp(leftKey->data, rightKey->data,
1984 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001985
1986 if (res == 0) {
1987 if (lsize < rsize) {
1988 res = -1;
1989 }
1990 else if (lsize > rsize) {
1991 res = 1;
1992 }
1993 }
1994 return res;
1995}
1996
1997static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001998_db_compareCallback(DB* db,
1999 const DBT *leftKey,
2000 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002001{
2002 int res = 0;
2003 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002004 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002005 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002006
2007 if (self == NULL || self->btCompareCallback == NULL) {
2008 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002009 PyErr_SetString(PyExc_TypeError,
2010 (self == 0
2011 ? "DB_bt_compare db is NULL."
2012 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002013 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002014 PyErr_Print();
2015 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002016 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002017 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002018 MYDB_BEGIN_BLOCK_THREADS;
2019
Thomas Woutersb3153832006-03-08 01:47:19 +00002020 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2021 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002022 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002023 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002024 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002025 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002026 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002027 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002028 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002029 PyErr_Print();
2030 res = _default_cmp(leftKey, rightKey);
2031 } else if (PyInt_Check(result)) {
2032 res = PyInt_AsLong(result);
2033 } else {
2034 PyErr_SetString(PyExc_TypeError,
2035 "DB_bt_compare callback MUST return an int.");
2036 /* we're in a callback within the DB code, we can't raise */
2037 PyErr_Print();
2038 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002039 }
2040
Thomas Woutersb3153832006-03-08 01:47:19 +00002041 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002042 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002043
2044 MYDB_END_BLOCK_THREADS;
2045 }
2046 return res;
2047}
2048
2049static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002050DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002051{
2052 int err;
2053 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002054 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002055
Georg Brandlef1701f2006-03-07 14:57:48 +00002056 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002057 return NULL;
2058
Georg Brandlef1701f2006-03-07 14:57:48 +00002059 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002060
Georg Brandlef1701f2006-03-07 14:57:48 +00002061 if (!PyCallable_Check(comparator)) {
2062 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002063 return NULL;
2064 }
2065
2066 /*
2067 * Perform a test call of the comparator function with two empty
2068 * string objects here. verify that it returns an int (0).
2069 * err if not.
2070 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002071 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002072 result = PyEval_CallObject(comparator, tuple);
2073 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002074 if (result == NULL)
2075 return NULL;
2076 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002077 PyErr_SetString(PyExc_TypeError,
2078 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002079 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002080 } else if (PyInt_AsLong(result) != 0) {
2081 PyErr_SetString(PyExc_TypeError,
2082 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002083 return NULL;
2084 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002085 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002086
2087 /* We don't accept multiple set_bt_compare operations, in order to
2088 * simplify the code. This would have no real use, as one cannot
2089 * change the function once the db is opened anyway */
2090 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002091 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002092 return NULL;
2093 }
2094
Georg Brandlef1701f2006-03-07 14:57:48 +00002095 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096 self->btCompareCallback = comparator;
2097
2098 /* This is to workaround a problem with un-initialized threads (see
2099 comment in DB_associate) */
2100#ifdef WITH_THREAD
2101 PyEval_InitThreads();
2102#endif
2103
Thomas Woutersb3153832006-03-08 01:47:19 +00002104 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002105
2106 if (err) {
2107 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109 self->btCompareCallback = NULL;
2110 }
2111
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 RETURN_IF_ERR();
2113 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002114}
Neal Norwitz84562352005-10-20 04:30:15 +00002115#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002116
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002117
2118static PyObject*
2119DB_set_cachesize(DBObject* self, PyObject* args)
2120{
2121 int err;
2122 int gbytes = 0, bytes = 0, ncache = 0;
2123
2124 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2125 &gbytes,&bytes,&ncache))
2126 return NULL;
2127 CHECK_DB_NOT_CLOSED(self);
2128
2129 MYDB_BEGIN_ALLOW_THREADS;
2130 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2131 MYDB_END_ALLOW_THREADS;
2132 RETURN_IF_ERR();
2133 RETURN_NONE();
2134}
2135
2136
2137static PyObject*
2138DB_set_flags(DBObject* self, PyObject* args)
2139{
2140 int err, flags;
2141
2142 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2143 return NULL;
2144 CHECK_DB_NOT_CLOSED(self);
2145
2146 MYDB_BEGIN_ALLOW_THREADS;
2147 err = self->db->set_flags(self->db, flags);
2148 MYDB_END_ALLOW_THREADS;
2149 RETURN_IF_ERR();
2150
2151 self->setflags |= flags;
2152 RETURN_NONE();
2153}
2154
2155
2156static PyObject*
2157DB_set_h_ffactor(DBObject* self, PyObject* args)
2158{
2159 int err, ffactor;
2160
2161 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2162 return NULL;
2163 CHECK_DB_NOT_CLOSED(self);
2164
2165 MYDB_BEGIN_ALLOW_THREADS;
2166 err = self->db->set_h_ffactor(self->db, ffactor);
2167 MYDB_END_ALLOW_THREADS;
2168 RETURN_IF_ERR();
2169 RETURN_NONE();
2170}
2171
2172
2173static PyObject*
2174DB_set_h_nelem(DBObject* self, PyObject* args)
2175{
2176 int err, nelem;
2177
2178 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2179 return NULL;
2180 CHECK_DB_NOT_CLOSED(self);
2181
2182 MYDB_BEGIN_ALLOW_THREADS;
2183 err = self->db->set_h_nelem(self->db, nelem);
2184 MYDB_END_ALLOW_THREADS;
2185 RETURN_IF_ERR();
2186 RETURN_NONE();
2187}
2188
2189
2190static PyObject*
2191DB_set_lorder(DBObject* self, PyObject* args)
2192{
2193 int err, lorder;
2194
2195 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2196 return NULL;
2197 CHECK_DB_NOT_CLOSED(self);
2198
2199 MYDB_BEGIN_ALLOW_THREADS;
2200 err = self->db->set_lorder(self->db, lorder);
2201 MYDB_END_ALLOW_THREADS;
2202 RETURN_IF_ERR();
2203 RETURN_NONE();
2204}
2205
2206
2207static PyObject*
2208DB_set_pagesize(DBObject* self, PyObject* args)
2209{
2210 int err, pagesize;
2211
2212 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2213 return NULL;
2214 CHECK_DB_NOT_CLOSED(self);
2215
2216 MYDB_BEGIN_ALLOW_THREADS;
2217 err = self->db->set_pagesize(self->db, pagesize);
2218 MYDB_END_ALLOW_THREADS;
2219 RETURN_IF_ERR();
2220 RETURN_NONE();
2221}
2222
2223
2224static PyObject*
2225DB_set_re_delim(DBObject* self, PyObject* args)
2226{
2227 int err;
2228 char delim;
2229
2230 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2231 PyErr_Clear();
2232 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2233 return NULL;
2234 }
2235
2236 CHECK_DB_NOT_CLOSED(self);
2237
2238 MYDB_BEGIN_ALLOW_THREADS;
2239 err = self->db->set_re_delim(self->db, delim);
2240 MYDB_END_ALLOW_THREADS;
2241 RETURN_IF_ERR();
2242 RETURN_NONE();
2243}
2244
2245static PyObject*
2246DB_set_re_len(DBObject* self, PyObject* args)
2247{
2248 int err, len;
2249
2250 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2251 return NULL;
2252 CHECK_DB_NOT_CLOSED(self);
2253
2254 MYDB_BEGIN_ALLOW_THREADS;
2255 err = self->db->set_re_len(self->db, len);
2256 MYDB_END_ALLOW_THREADS;
2257 RETURN_IF_ERR();
2258 RETURN_NONE();
2259}
2260
2261
2262static PyObject*
2263DB_set_re_pad(DBObject* self, PyObject* args)
2264{
2265 int err;
2266 char pad;
2267
2268 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2269 PyErr_Clear();
2270 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2271 return NULL;
2272 }
2273 CHECK_DB_NOT_CLOSED(self);
2274
2275 MYDB_BEGIN_ALLOW_THREADS;
2276 err = self->db->set_re_pad(self->db, pad);
2277 MYDB_END_ALLOW_THREADS;
2278 RETURN_IF_ERR();
2279 RETURN_NONE();
2280}
2281
2282
2283static PyObject*
2284DB_set_re_source(DBObject* self, PyObject* args)
2285{
2286 int err;
2287 char *re_source;
2288
2289 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2290 return NULL;
2291 CHECK_DB_NOT_CLOSED(self);
2292
2293 MYDB_BEGIN_ALLOW_THREADS;
2294 err = self->db->set_re_source(self->db, re_source);
2295 MYDB_END_ALLOW_THREADS;
2296 RETURN_IF_ERR();
2297 RETURN_NONE();
2298}
2299
2300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002301static PyObject*
2302DB_set_q_extentsize(DBObject* self, PyObject* args)
2303{
2304 int err;
2305 int extentsize;
2306
2307 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2308 return NULL;
2309 CHECK_DB_NOT_CLOSED(self);
2310
2311 MYDB_BEGIN_ALLOW_THREADS;
2312 err = self->db->set_q_extentsize(self->db, extentsize);
2313 MYDB_END_ALLOW_THREADS;
2314 RETURN_IF_ERR();
2315 RETURN_NONE();
2316}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002317
2318static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002319DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002320{
2321 int err, flags = 0, type;
2322 void* sp;
2323 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002324#if (DBVER >= 43)
2325 PyObject* txnobj = NULL;
2326 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002327 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002328#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002329 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002330#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002331
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002332#if (DBVER >= 43)
2333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2334 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002335 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002336 if (!checkTxnObj(txnobj, &txn))
2337 return NULL;
2338#else
2339 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2340 return NULL;
2341#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002342 CHECK_DB_NOT_CLOSED(self);
2343
2344 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002345#if (DBVER >= 43)
2346 err = self->db->stat(self->db, txn, &sp, flags);
2347#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002348 err = self->db->stat(self->db, &sp, flags);
2349#else
2350 err = self->db->stat(self->db, &sp, NULL, flags);
2351#endif
2352 MYDB_END_ALLOW_THREADS;
2353 RETURN_IF_ERR();
2354
2355 self->haveStat = 1;
2356
2357 /* Turn the stat structure into a dictionary */
2358 type = _DB_get_type(self);
2359 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2360 free(sp);
2361 return NULL;
2362 }
2363
2364#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2365#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2366#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2367
2368 switch (type) {
2369 case DB_HASH:
2370 MAKE_HASH_ENTRY(magic);
2371 MAKE_HASH_ENTRY(version);
2372 MAKE_HASH_ENTRY(nkeys);
2373 MAKE_HASH_ENTRY(ndata);
2374 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002375#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002376 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002377#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002378 MAKE_HASH_ENTRY(ffactor);
2379 MAKE_HASH_ENTRY(buckets);
2380 MAKE_HASH_ENTRY(free);
2381 MAKE_HASH_ENTRY(bfree);
2382 MAKE_HASH_ENTRY(bigpages);
2383 MAKE_HASH_ENTRY(big_bfree);
2384 MAKE_HASH_ENTRY(overflows);
2385 MAKE_HASH_ENTRY(ovfl_free);
2386 MAKE_HASH_ENTRY(dup);
2387 MAKE_HASH_ENTRY(dup_free);
2388 break;
2389
2390 case DB_BTREE:
2391 case DB_RECNO:
2392 MAKE_BT_ENTRY(magic);
2393 MAKE_BT_ENTRY(version);
2394 MAKE_BT_ENTRY(nkeys);
2395 MAKE_BT_ENTRY(ndata);
2396 MAKE_BT_ENTRY(pagesize);
2397 MAKE_BT_ENTRY(minkey);
2398 MAKE_BT_ENTRY(re_len);
2399 MAKE_BT_ENTRY(re_pad);
2400 MAKE_BT_ENTRY(levels);
2401 MAKE_BT_ENTRY(int_pg);
2402 MAKE_BT_ENTRY(leaf_pg);
2403 MAKE_BT_ENTRY(dup_pg);
2404 MAKE_BT_ENTRY(over_pg);
2405 MAKE_BT_ENTRY(free);
2406 MAKE_BT_ENTRY(int_pgfree);
2407 MAKE_BT_ENTRY(leaf_pgfree);
2408 MAKE_BT_ENTRY(dup_pgfree);
2409 MAKE_BT_ENTRY(over_pgfree);
2410 break;
2411
2412 case DB_QUEUE:
2413 MAKE_QUEUE_ENTRY(magic);
2414 MAKE_QUEUE_ENTRY(version);
2415 MAKE_QUEUE_ENTRY(nkeys);
2416 MAKE_QUEUE_ENTRY(ndata);
2417 MAKE_QUEUE_ENTRY(pagesize);
2418 MAKE_QUEUE_ENTRY(pages);
2419 MAKE_QUEUE_ENTRY(re_len);
2420 MAKE_QUEUE_ENTRY(re_pad);
2421 MAKE_QUEUE_ENTRY(pgfree);
2422#if (DBVER == 31)
2423 MAKE_QUEUE_ENTRY(start);
2424#endif
2425 MAKE_QUEUE_ENTRY(first_recno);
2426 MAKE_QUEUE_ENTRY(cur_recno);
2427 break;
2428
2429 default:
2430 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2431 Py_DECREF(d);
2432 d = NULL;
2433 }
2434
2435#undef MAKE_HASH_ENTRY
2436#undef MAKE_BT_ENTRY
2437#undef MAKE_QUEUE_ENTRY
2438
2439 free(sp);
2440 return d;
2441}
2442
2443static PyObject*
2444DB_sync(DBObject* self, PyObject* args)
2445{
2446 int err;
2447 int flags = 0;
2448
2449 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2450 return NULL;
2451 CHECK_DB_NOT_CLOSED(self);
2452
2453 MYDB_BEGIN_ALLOW_THREADS;
2454 err = self->db->sync(self->db, flags);
2455 MYDB_END_ALLOW_THREADS;
2456 RETURN_IF_ERR();
2457 RETURN_NONE();
2458}
2459
2460
2461#if (DBVER >= 33)
2462static PyObject*
2463DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2464{
2465 int err, flags=0;
2466 u_int32_t count=0;
2467 PyObject* txnobj = NULL;
2468 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002469 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002470
2471 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2472 &txnobj, &flags))
2473 return NULL;
2474 CHECK_DB_NOT_CLOSED(self);
2475 if (!checkTxnObj(txnobj, &txn))
2476 return NULL;
2477
2478 MYDB_BEGIN_ALLOW_THREADS;
2479 err = self->db->truncate(self->db, txn, &count, flags);
2480 MYDB_END_ALLOW_THREADS;
2481 RETURN_IF_ERR();
2482 return PyInt_FromLong(count);
2483}
2484#endif
2485
2486
2487static PyObject*
2488DB_upgrade(DBObject* self, PyObject* args)
2489{
2490 int err, flags=0;
2491 char *filename;
2492
2493 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2494 return NULL;
2495 CHECK_DB_NOT_CLOSED(self);
2496
2497 MYDB_BEGIN_ALLOW_THREADS;
2498 err = self->db->upgrade(self->db, filename, flags);
2499 MYDB_END_ALLOW_THREADS;
2500 RETURN_IF_ERR();
2501 RETURN_NONE();
2502}
2503
2504
2505static PyObject*
2506DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2507{
2508 int err, flags=0;
2509 char* fileName;
2510 char* dbName=NULL;
2511 char* outFileName=NULL;
2512 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002513 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002514 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002515
2516 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2517 &fileName, &dbName, &outFileName, &flags))
2518 return NULL;
2519
2520 CHECK_DB_NOT_CLOSED(self);
2521 if (outFileName)
2522 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002523 /* XXX(nnorwitz): it should probably be an exception if outFile
2524 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002525
2526 MYDB_BEGIN_ALLOW_THREADS;
2527 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2528 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002529 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002530 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002531
2532 /* DB.verify acts as a DB handle destructor (like close); this was
2533 * documented in BerkeleyDB 4.2 but had the undocumented effect
2534 * of not being safe in prior versions while still requiring an explicit
2535 * DB.close call afterwards. Lets call close for the user to emulate
2536 * the safe 4.2 behaviour. */
2537#if (DBVER <= 41)
2538 self->db->close(self->db, 0);
2539#endif
2540 self->db = NULL;
2541
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002542 RETURN_IF_ERR();
2543 RETURN_NONE();
2544}
2545
2546
2547static PyObject*
2548DB_set_get_returns_none(DBObject* self, PyObject* args)
2549{
2550 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002551 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002552
2553 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2554 return NULL;
2555 CHECK_DB_NOT_CLOSED(self);
2556
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002557 if (self->moduleFlags.getReturnsNone)
2558 ++oldValue;
2559 if (self->moduleFlags.cursorSetReturnsNone)
2560 ++oldValue;
2561 self->moduleFlags.getReturnsNone = (flags >= 1);
2562 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002563 return PyInt_FromLong(oldValue);
2564}
2565
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002566#if (DBVER >= 41)
2567static PyObject*
2568DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2569{
2570 int err;
2571 u_int32_t flags=0;
2572 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002573 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002574
2575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2576 &passwd, &flags)) {
2577 return NULL;
2578 }
2579
2580 MYDB_BEGIN_ALLOW_THREADS;
2581 err = self->db->set_encrypt(self->db, passwd, flags);
2582 MYDB_END_ALLOW_THREADS;
2583
2584 RETURN_IF_ERR();
2585 RETURN_NONE();
2586}
2587#endif /* DBVER >= 41 */
2588
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002589
2590/*-------------------------------------------------------------- */
2591/* Mapping and Dictionary-like access routines */
2592
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002593Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002594{
2595 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002596 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002597 int flags = 0;
2598 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002599 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002600
2601 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002602 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2603 PyErr_SetObject(DBError, t);
2604 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002605 return -1;
2606 }
2607
2608 if (self->haveStat) { /* Has the stat function been called recently? If
2609 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002610 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002611 }
2612
2613 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002614redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002615#if (DBVER >= 43)
2616 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2617#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002618 err = self->db->stat(self->db, &sp, flags);
2619#else
2620 err = self->db->stat(self->db, &sp, NULL, flags);
2621#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002622
2623 /* All the stat structures have matching fields upto the ndata field,
2624 so we can use any of them for the type cast */
2625 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2626
2627 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2628 * redo a full stat to make sure.
2629 * Fixes SF python bug 1493322, pybsddb bug 1184012
2630 */
2631 if (size == 0 && (flags & DB_FAST_STAT)) {
2632 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002633 if (!err)
2634 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002635 goto redo_stat_for_length;
2636 }
2637
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002638 MYDB_END_ALLOW_THREADS;
2639
2640 if (err)
2641 return -1;
2642
2643 self->haveStat = 1;
2644
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002645 free(sp);
2646 return size;
2647}
2648
2649
2650PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2651{
2652 int err;
2653 PyObject* retval;
2654 DBT key;
2655 DBT data;
2656
2657 CHECK_DB_NOT_CLOSED(self);
2658 if (!make_key_dbt(self, keyobj, &key, NULL))
2659 return NULL;
2660
2661 CLEAR_DBT(data);
2662 if (CHECK_DBFLAG(self, DB_THREAD)) {
2663 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2664 data.flags = DB_DBT_MALLOC;
2665 }
2666 MYDB_BEGIN_ALLOW_THREADS;
2667 err = self->db->get(self->db, NULL, &key, &data, 0);
2668 MYDB_END_ALLOW_THREADS;
2669 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2670 PyErr_SetObject(PyExc_KeyError, keyobj);
2671 retval = NULL;
2672 }
2673 else if (makeDBError(err)) {
2674 retval = NULL;
2675 }
2676 else {
2677 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2678 FREE_DBT(data);
2679 }
2680
2681 FREE_DBT(key);
2682 return retval;
2683}
2684
2685
2686static int
2687DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2688{
2689 DBT key, data;
2690 int retval;
2691 int flags = 0;
2692
2693 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002694 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2695 PyErr_SetObject(DBError, t);
2696 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002697 return -1;
2698 }
2699
2700 if (!make_key_dbt(self, keyobj, &key, NULL))
2701 return -1;
2702
2703 if (dataobj != NULL) {
2704 if (!make_dbt(dataobj, &data))
2705 retval = -1;
2706 else {
2707 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002708 /* dictionaries shouldn't have duplicate keys */
2709 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710 retval = _DB_put(self, NULL, &key, &data, flags);
2711
2712 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002713 /* try deleting any old record that matches and then PUT it
2714 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002715 _DB_delete(self, NULL, &key, 0);
2716 PyErr_Clear();
2717 retval = _DB_put(self, NULL, &key, &data, flags);
2718 }
2719 }
2720 }
2721 else {
2722 /* dataobj == NULL, so delete the key */
2723 retval = _DB_delete(self, NULL, &key, 0);
2724 }
2725 FREE_DBT(key);
2726 return retval;
2727}
2728
2729
2730static PyObject*
2731DB_has_key(DBObject* self, PyObject* args)
2732{
2733 int err;
2734 PyObject* keyobj;
2735 DBT key, data;
2736 PyObject* txnobj = NULL;
2737 DB_TXN *txn = NULL;
2738
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002739 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 return NULL;
2741 CHECK_DB_NOT_CLOSED(self);
2742 if (!make_key_dbt(self, keyobj, &key, NULL))
2743 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002744 if (!checkTxnObj(txnobj, &txn)) {
2745 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002747 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002748
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002749 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750 it has a record but can't allocate a buffer for the data. This saves
2751 having to deal with data we won't be using.
2752 */
2753 CLEAR_DBT(data);
2754 data.flags = DB_DBT_USERMEM;
2755
2756 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002757 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002758 MYDB_END_ALLOW_THREADS;
2759 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002760
2761 if (err == DB_BUFFER_SMALL || err == 0) {
2762 return PyInt_FromLong(1);
2763 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2764 return PyInt_FromLong(0);
2765 }
2766
2767 makeDBError(err);
2768 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002769}
2770
2771
2772#define _KEYS_LIST 1
2773#define _VALUES_LIST 2
2774#define _ITEMS_LIST 3
2775
2776static PyObject*
2777_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2778{
2779 int err, dbtype;
2780 DBT key;
2781 DBT data;
2782 DBC *cursor;
2783 PyObject* list;
2784 PyObject* item = NULL;
2785
2786 CHECK_DB_NOT_CLOSED(self);
2787 CLEAR_DBT(key);
2788 CLEAR_DBT(data);
2789
2790 dbtype = _DB_get_type(self);
2791 if (dbtype == -1)
2792 return NULL;
2793
2794 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002795 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002796 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002797
2798 /* get a cursor */
2799 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002800 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002802 if (makeDBError(err)) {
2803 Py_DECREF(list);
2804 return NULL;
2805 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806
2807 if (CHECK_DBFLAG(self, DB_THREAD)) {
2808 key.flags = DB_DBT_REALLOC;
2809 data.flags = DB_DBT_REALLOC;
2810 }
2811
2812 while (1) { /* use the cursor to traverse the DB, collecting items */
2813 MYDB_BEGIN_ALLOW_THREADS;
2814 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2815 MYDB_END_ALLOW_THREADS;
2816
2817 if (err) {
2818 /* for any error, break out of the loop */
2819 break;
2820 }
2821
2822 switch (type) {
2823 case _KEYS_LIST:
2824 switch(dbtype) {
2825 case DB_BTREE:
2826 case DB_HASH:
2827 default:
2828 item = PyString_FromStringAndSize((char*)key.data, key.size);
2829 break;
2830 case DB_RECNO:
2831 case DB_QUEUE:
2832 item = PyInt_FromLong(*((db_recno_t*)key.data));
2833 break;
2834 }
2835 break;
2836
2837 case _VALUES_LIST:
2838 item = PyString_FromStringAndSize((char*)data.data, data.size);
2839 break;
2840
2841 case _ITEMS_LIST:
2842 switch(dbtype) {
2843 case DB_BTREE:
2844 case DB_HASH:
2845 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002846 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2847 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848 break;
2849 case DB_RECNO:
2850 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002851 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2852 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853 break;
2854 }
2855 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002856 default:
2857 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2858 item = NULL;
2859 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860 }
2861 if (item == NULL) {
2862 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002863 list = NULL;
2864 goto done;
2865 }
2866 PyList_Append(list, item);
2867 Py_DECREF(item);
2868 }
2869
Gregory P. Smithe9477062005-06-04 06:46:59 +00002870 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2871 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 Py_DECREF(list);
2873 list = NULL;
2874 }
2875
2876 done:
2877 FREE_DBT(key);
2878 FREE_DBT(data);
2879 MYDB_BEGIN_ALLOW_THREADS;
2880 cursor->c_close(cursor);
2881 MYDB_END_ALLOW_THREADS;
2882 return list;
2883}
2884
2885
2886static PyObject*
2887DB_keys(DBObject* self, PyObject* args)
2888{
2889 PyObject* txnobj = NULL;
2890 DB_TXN *txn = NULL;
2891
Georg Brandl96a8c392006-05-29 21:04:52 +00002892 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002893 return NULL;
2894 if (!checkTxnObj(txnobj, &txn))
2895 return NULL;
2896 return _DB_make_list(self, txn, _KEYS_LIST);
2897}
2898
2899
2900static PyObject*
2901DB_items(DBObject* self, PyObject* args)
2902{
2903 PyObject* txnobj = NULL;
2904 DB_TXN *txn = NULL;
2905
Georg Brandl96a8c392006-05-29 21:04:52 +00002906 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907 return NULL;
2908 if (!checkTxnObj(txnobj, &txn))
2909 return NULL;
2910 return _DB_make_list(self, txn, _ITEMS_LIST);
2911}
2912
2913
2914static PyObject*
2915DB_values(DBObject* self, PyObject* args)
2916{
2917 PyObject* txnobj = NULL;
2918 DB_TXN *txn = NULL;
2919
Georg Brandl96a8c392006-05-29 21:04:52 +00002920 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002921 return NULL;
2922 if (!checkTxnObj(txnobj, &txn))
2923 return NULL;
2924 return _DB_make_list(self, txn, _VALUES_LIST);
2925}
2926
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927/* --------------------------------------------------------------------- */
2928/* DBCursor methods */
2929
2930
2931static PyObject*
2932DBC_close(DBCursorObject* self, PyObject* args)
2933{
2934 int err = 0;
2935
2936 if (!PyArg_ParseTuple(args, ":close"))
2937 return NULL;
2938
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 if (self->dbc != NULL) {
2940 MYDB_BEGIN_ALLOW_THREADS;
2941 err = self->dbc->c_close(self->dbc);
2942 self->dbc = NULL;
2943 MYDB_END_ALLOW_THREADS;
2944 }
2945 RETURN_IF_ERR();
2946 RETURN_NONE();
2947}
2948
2949
2950static PyObject*
2951DBC_count(DBCursorObject* self, PyObject* args)
2952{
2953 int err = 0;
2954 db_recno_t count;
2955 int flags = 0;
2956
2957 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2958 return NULL;
2959
2960 CHECK_CURSOR_NOT_CLOSED(self);
2961
2962 MYDB_BEGIN_ALLOW_THREADS;
2963 err = self->dbc->c_count(self->dbc, &count, flags);
2964 MYDB_END_ALLOW_THREADS;
2965 RETURN_IF_ERR();
2966
2967 return PyInt_FromLong(count);
2968}
2969
2970
2971static PyObject*
2972DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2973{
2974 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2975}
2976
2977
2978static PyObject*
2979DBC_delete(DBCursorObject* self, PyObject* args)
2980{
2981 int err, flags=0;
2982
2983 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2984 return NULL;
2985
2986 CHECK_CURSOR_NOT_CLOSED(self);
2987
2988 MYDB_BEGIN_ALLOW_THREADS;
2989 err = self->dbc->c_del(self->dbc, flags);
2990 MYDB_END_ALLOW_THREADS;
2991 RETURN_IF_ERR();
2992
2993 self->mydb->haveStat = 0;
2994 RETURN_NONE();
2995}
2996
2997
2998static PyObject*
2999DBC_dup(DBCursorObject* self, PyObject* args)
3000{
3001 int err, flags =0;
3002 DBC* dbc = NULL;
3003
3004 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3005 return NULL;
3006
3007 CHECK_CURSOR_NOT_CLOSED(self);
3008
3009 MYDB_BEGIN_ALLOW_THREADS;
3010 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3011 MYDB_END_ALLOW_THREADS;
3012 RETURN_IF_ERR();
3013
3014 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3015}
3016
3017static PyObject*
3018DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3019{
3020 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3021}
3022
3023
3024static PyObject*
3025DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3026{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003027 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 PyObject* keyobj = NULL;
3029 PyObject* dataobj = NULL;
3030 PyObject* retval = NULL;
3031 int dlen = -1;
3032 int doff = -1;
3033 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003034 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003035 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036
3037 CLEAR_DBT(key);
3038 CLEAR_DBT(data);
3039 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003040 &flags, &dlen, &doff))
3041 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003042 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003043 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3044 &kwnames[1],
3045 &keyobj, &flags, &dlen, &doff))
3046 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003047 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003048 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3049 kwnames, &keyobj, &dataobj,
3050 &flags, &dlen, &doff))
3051 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003052 return NULL;
3053 }
3054 }
3055 }
3056
3057 CHECK_CURSOR_NOT_CLOSED(self);
3058
3059 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3060 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003061 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3062 (!add_partial_dbt(&data, dlen, doff)) )
3063 {
3064 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003066 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067
3068 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3069 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003070 if (!(key.flags & DB_DBT_REALLOC)) {
3071 key.flags |= DB_DBT_MALLOC;
3072 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003073 }
3074
3075 MYDB_BEGIN_ALLOW_THREADS;
3076 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3077 MYDB_END_ALLOW_THREADS;
3078
Gregory P. Smithe9477062005-06-04 06:46:59 +00003079 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3080 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003081 Py_INCREF(Py_None);
3082 retval = Py_None;
3083 }
3084 else if (makeDBError(err)) {
3085 retval = NULL;
3086 }
3087 else {
3088 switch (_DB_get_type(self->mydb)) {
3089 case -1:
3090 retval = NULL;
3091 break;
3092 case DB_BTREE:
3093 case DB_HASH:
3094 default:
3095 retval = Py_BuildValue("s#s#", key.data, key.size,
3096 data.data, data.size);
3097 break;
3098 case DB_RECNO:
3099 case DB_QUEUE:
3100 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3101 data.data, data.size);
3102 break;
3103 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003104 FREE_DBT(data);
3105 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003106 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003107 return retval;
3108}
3109
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003110#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003111static PyObject*
3112DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3113{
3114 int err, flags=0;
3115 PyObject* keyobj = NULL;
3116 PyObject* dataobj = NULL;
3117 PyObject* retval = NULL;
3118 int dlen = -1;
3119 int doff = -1;
3120 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003121 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3122 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003123
3124 CLEAR_DBT(key);
3125 CLEAR_DBT(data);
3126 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3127 &flags, &dlen, &doff))
3128 {
3129 PyErr_Clear();
3130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003131 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003132 &keyobj, &flags, &dlen, &doff))
3133 {
3134 PyErr_Clear();
3135 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3136 kwnames, &keyobj, &dataobj,
3137 &flags, &dlen, &doff))
3138 {
3139 return NULL;
3140 }
3141 }
3142 }
3143
3144 CHECK_CURSOR_NOT_CLOSED(self);
3145
3146 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3147 return NULL;
3148 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3149 (!add_partial_dbt(&data, dlen, doff)) ) {
3150 FREE_DBT(key);
3151 return NULL;
3152 }
3153
3154 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3155 data.flags = DB_DBT_MALLOC;
3156 if (!(key.flags & DB_DBT_REALLOC)) {
3157 key.flags |= DB_DBT_MALLOC;
3158 }
3159 }
3160
3161 CLEAR_DBT(pkey);
3162 pkey.flags = DB_DBT_MALLOC;
3163
3164 MYDB_BEGIN_ALLOW_THREADS;
3165 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3166 MYDB_END_ALLOW_THREADS;
3167
Gregory P. Smithe9477062005-06-04 06:46:59 +00003168 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3169 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003170 Py_INCREF(Py_None);
3171 retval = Py_None;
3172 }
3173 else if (makeDBError(err)) {
3174 retval = NULL;
3175 }
3176 else {
3177 PyObject *pkeyObj;
3178 PyObject *dataObj;
3179 dataObj = PyString_FromStringAndSize(data.data, data.size);
3180
3181 if (self->mydb->primaryDBType == DB_RECNO ||
3182 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003183 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003184 else
3185 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3186
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003187 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003188 {
3189 PyObject *keyObj;
3190 int type = _DB_get_type(self->mydb);
3191 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003192 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003193 else
3194 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003195#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003196 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003197#else
3198 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3199#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003200 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003201 FREE_DBT(key);
3202 }
3203 else /* return just the pkey and data */
3204 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003205#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003206 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003207#else
3208 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3209#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003210 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003211 Py_DECREF(dataObj);
3212 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003213 FREE_DBT(pkey);
3214 FREE_DBT(data);
3215 }
3216 /* the only time REALLOC should be set is if we used an integer
3217 * key that make_key_dbt malloc'd for us. always free these. */
3218 if (key.flags & DB_DBT_REALLOC) {
3219 FREE_DBT(key);
3220 }
3221 return retval;
3222}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003223#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225
3226static PyObject*
3227DBC_get_recno(DBCursorObject* self, PyObject* args)
3228{
3229 int err;
3230 db_recno_t recno;
3231 DBT key;
3232 DBT data;
3233
3234 if (!PyArg_ParseTuple(args, ":get_recno"))
3235 return NULL;
3236
3237 CHECK_CURSOR_NOT_CLOSED(self);
3238
3239 CLEAR_DBT(key);
3240 CLEAR_DBT(data);
3241 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3242 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3243 data.flags = DB_DBT_MALLOC;
3244 key.flags = DB_DBT_MALLOC;
3245 }
3246
3247 MYDB_BEGIN_ALLOW_THREADS;
3248 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3249 MYDB_END_ALLOW_THREADS;
3250 RETURN_IF_ERR();
3251
3252 recno = *((db_recno_t*)data.data);
3253 FREE_DBT(key);
3254 FREE_DBT(data);
3255 return PyInt_FromLong(recno);
3256}
3257
3258
3259static PyObject*
3260DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3261{
3262 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3263}
3264
3265
3266static PyObject*
3267DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3268{
3269 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3270}
3271
3272
3273static PyObject*
3274DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3275{
3276 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3277}
3278
3279
3280static PyObject*
3281DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3282{
3283 int err, flags = 0;
3284 PyObject* keyobj, *dataobj;
3285 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003286 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003287 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003288 int dlen = -1;
3289 int doff = -1;
3290
3291 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3292 &keyobj, &dataobj, &flags, &dlen, &doff))
3293 return NULL;
3294
3295 CHECK_CURSOR_NOT_CLOSED(self);
3296
3297 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3298 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003299 if (!make_dbt(dataobj, &data) ||
3300 !add_partial_dbt(&data, dlen, doff) )
3301 {
3302 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003304 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305
3306 MYDB_BEGIN_ALLOW_THREADS;
3307 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3308 MYDB_END_ALLOW_THREADS;
3309 FREE_DBT(key);
3310 RETURN_IF_ERR();
3311 self->mydb->haveStat = 0;
3312 RETURN_NONE();
3313}
3314
3315
3316static PyObject*
3317DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3318{
3319 int err, flags = 0;
3320 DBT key, data;
3321 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003322 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003323 int dlen = -1;
3324 int doff = -1;
3325
3326 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3327 &keyobj, &flags, &dlen, &doff))
3328 return NULL;
3329
3330 CHECK_CURSOR_NOT_CLOSED(self);
3331
3332 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3333 return NULL;
3334
3335 CLEAR_DBT(data);
3336 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3337 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3338 data.flags = DB_DBT_MALLOC;
3339 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003340 if (!add_partial_dbt(&data, dlen, doff)) {
3341 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003343 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003344
3345 MYDB_BEGIN_ALLOW_THREADS;
3346 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3347 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003348 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3349 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003350 Py_INCREF(Py_None);
3351 retval = Py_None;
3352 }
3353 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354 retval = NULL;
3355 }
3356 else {
3357 switch (_DB_get_type(self->mydb)) {
3358 case -1:
3359 retval = NULL;
3360 break;
3361 case DB_BTREE:
3362 case DB_HASH:
3363 default:
3364 retval = Py_BuildValue("s#s#", key.data, key.size,
3365 data.data, data.size);
3366 break;
3367 case DB_RECNO:
3368 case DB_QUEUE:
3369 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3370 data.data, data.size);
3371 break;
3372 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003374 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003375 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003376 /* the only time REALLOC should be set is if we used an integer
3377 * key that make_key_dbt malloc'd for us. always free these. */
3378 if (key.flags & DB_DBT_REALLOC) {
3379 FREE_DBT(key);
3380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003381
3382 return retval;
3383}
3384
3385
3386static PyObject*
3387DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3388{
3389 int err, flags = 0;
3390 DBT key, data;
3391 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003392 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393 int dlen = -1;
3394 int doff = -1;
3395
3396 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3397 &keyobj, &flags, &dlen, &doff))
3398 return NULL;
3399
3400 CHECK_CURSOR_NOT_CLOSED(self);
3401
3402 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3403 return NULL;
3404
3405 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003406 if (!add_partial_dbt(&data, dlen, doff)) {
3407 FREE_DBT(key);
3408 return NULL;
3409 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3411 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003412 data.flags |= DB_DBT_MALLOC;
3413 /* only BTREE databases will return anything in the key */
3414 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3415 key.flags |= DB_DBT_MALLOC;
3416 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 MYDB_BEGIN_ALLOW_THREADS;
3419 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3420 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003421 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3422 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003423 Py_INCREF(Py_None);
3424 retval = Py_None;
3425 }
3426 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427 retval = NULL;
3428 }
3429 else {
3430 switch (_DB_get_type(self->mydb)) {
3431 case -1:
3432 retval = NULL;
3433 break;
3434 case DB_BTREE:
3435 case DB_HASH:
3436 default:
3437 retval = Py_BuildValue("s#s#", key.data, key.size,
3438 data.data, data.size);
3439 break;
3440 case DB_RECNO:
3441 case DB_QUEUE:
3442 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3443 data.data, data.size);
3444 break;
3445 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003446 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447 FREE_DBT(data);
3448 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003450 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003451 if (key.flags & DB_DBT_REALLOC) {
3452 FREE_DBT(key);
3453 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454
3455 return retval;
3456}
3457
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003458static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003459_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3460 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003462 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003464 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465
Gregory P. Smith7441e652003-11-03 21:35:31 +00003466 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3468 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003469 if (!make_dbt(dataobj, &data)) {
3470 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003472 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003473
3474 MYDB_BEGIN_ALLOW_THREADS;
3475 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3476 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003477 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003478 Py_INCREF(Py_None);
3479 retval = Py_None;
3480 }
3481 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 retval = NULL;
3483 }
3484 else {
3485 switch (_DB_get_type(self->mydb)) {
3486 case -1:
3487 retval = NULL;
3488 break;
3489 case DB_BTREE:
3490 case DB_HASH:
3491 default:
3492 retval = Py_BuildValue("s#s#", key.data, key.size,
3493 data.data, data.size);
3494 break;
3495 case DB_RECNO:
3496 case DB_QUEUE:
3497 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3498 data.data, data.size);
3499 break;
3500 }
3501 }
3502
3503 FREE_DBT(key);
3504 return retval;
3505}
3506
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003507static PyObject*
3508DBC_get_both(DBCursorObject* self, PyObject* args)
3509{
3510 int flags=0;
3511 PyObject *keyobj, *dataobj;
3512
3513 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3514 return NULL;
3515
Gregory P. Smith7441e652003-11-03 21:35:31 +00003516 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003517 CHECK_CURSOR_NOT_CLOSED(self);
3518
3519 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3520 self->mydb->moduleFlags.getReturnsNone);
3521}
3522
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003523/* Return size of entry */
3524static PyObject*
3525DBC_get_current_size(DBCursorObject* self, PyObject* args)
3526{
3527 int err, flags=DB_CURRENT;
3528 PyObject* retval = NULL;
3529 DBT key, data;
3530
3531 if (!PyArg_ParseTuple(args, ":get_current_size"))
3532 return NULL;
3533 CHECK_CURSOR_NOT_CLOSED(self);
3534 CLEAR_DBT(key);
3535 CLEAR_DBT(data);
3536
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003537 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003538 getting the record size. */
3539 data.flags = DB_DBT_USERMEM;
3540 data.ulen = 0;
3541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3543 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003544 if (err == DB_BUFFER_SMALL || !err) {
3545 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003546 retval = PyInt_FromLong((long)data.size);
3547 err = 0;
3548 }
3549
3550 FREE_DBT(key);
3551 FREE_DBT(data);
3552 RETURN_IF_ERR();
3553 return retval;
3554}
3555
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003556static PyObject*
3557DBC_set_both(DBCursorObject* self, PyObject* args)
3558{
3559 int flags=0;
3560 PyObject *keyobj, *dataobj;
3561
3562 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3563 return NULL;
3564
Gregory P. Smith7441e652003-11-03 21:35:31 +00003565 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003566 CHECK_CURSOR_NOT_CLOSED(self);
3567
3568 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3569 self->mydb->moduleFlags.cursorSetReturnsNone);
3570}
3571
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572
3573static PyObject*
3574DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3575{
3576 int err, irecno, flags=0;
3577 db_recno_t recno;
3578 DBT key, data;
3579 PyObject* retval;
3580 int dlen = -1;
3581 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003582 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583
3584 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3585 &irecno, &flags, &dlen, &doff))
3586 return NULL;
3587
3588 CHECK_CURSOR_NOT_CLOSED(self);
3589
3590 CLEAR_DBT(key);
3591 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003592 /* use allocated space so DB will be able to realloc room for the real
3593 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 key.data = malloc(sizeof(db_recno_t));
3595 if (key.data == NULL) {
3596 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3597 return NULL;
3598 }
3599 key.size = sizeof(db_recno_t);
3600 key.ulen = key.size;
3601 memcpy(key.data, &recno, sizeof(db_recno_t));
3602 key.flags = DB_DBT_REALLOC;
3603
3604 CLEAR_DBT(data);
3605 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3606 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3607 data.flags = DB_DBT_MALLOC;
3608 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003609 if (!add_partial_dbt(&data, dlen, doff)) {
3610 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003612 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613
3614 MYDB_BEGIN_ALLOW_THREADS;
3615 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3616 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003617 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3618 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003619 Py_INCREF(Py_None);
3620 retval = Py_None;
3621 }
3622 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003623 retval = NULL;
3624 }
3625 else { /* Can only be used for BTrees, so no need to return int key */
3626 retval = Py_BuildValue("s#s#", key.data, key.size,
3627 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003628 FREE_DBT(data);
3629 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003630 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003631
3632 return retval;
3633}
3634
3635
3636static PyObject*
3637DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3638{
3639 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3640}
3641
3642
3643static PyObject*
3644DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3645{
3646 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3647}
3648
3649
3650static PyObject*
3651DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3652{
3653 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3654}
3655
3656
3657static PyObject*
3658DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3659{
3660 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3661}
3662
3663
3664static PyObject*
3665DBC_join_item(DBCursorObject* self, PyObject* args)
3666{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003667 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003668 DBT key, data;
3669 PyObject* retval;
3670
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672 return NULL;
3673
3674 CHECK_CURSOR_NOT_CLOSED(self);
3675
3676 CLEAR_DBT(key);
3677 CLEAR_DBT(data);
3678 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3679 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3680 key.flags = DB_DBT_MALLOC;
3681 }
3682
3683 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003684 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003686 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3687 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 Py_INCREF(Py_None);
3689 retval = Py_None;
3690 }
3691 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 retval = NULL;
3693 }
3694 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003695 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003696 FREE_DBT(key);
3697 }
3698
3699 return retval;
3700}
3701
3702
3703
3704/* --------------------------------------------------------------------- */
3705/* DBEnv methods */
3706
3707
3708static PyObject*
3709DBEnv_close(DBEnvObject* self, PyObject* args)
3710{
3711 int err, flags = 0;
3712
3713 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3714 return NULL;
3715 if (!self->closed) { /* Don't close more than once */
3716 MYDB_BEGIN_ALLOW_THREADS;
3717 err = self->db_env->close(self->db_env, flags);
3718 MYDB_END_ALLOW_THREADS;
3719 /* after calling DBEnv->close, regardless of error, this DBEnv
3720 * may not be accessed again (BerkeleyDB docs). */
3721 self->closed = 1;
3722 self->db_env = NULL;
3723 RETURN_IF_ERR();
3724 }
3725 RETURN_NONE();
3726}
3727
3728
3729static PyObject*
3730DBEnv_open(DBEnvObject* self, PyObject* args)
3731{
3732 int err, flags=0, mode=0660;
3733 char *db_home;
3734
3735 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3736 return NULL;
3737
3738 CHECK_ENV_NOT_CLOSED(self);
3739
3740 MYDB_BEGIN_ALLOW_THREADS;
3741 err = self->db_env->open(self->db_env, db_home, flags, mode);
3742 MYDB_END_ALLOW_THREADS;
3743 RETURN_IF_ERR();
3744 self->closed = 0;
3745 self->flags = flags;
3746 RETURN_NONE();
3747}
3748
3749
3750static PyObject*
3751DBEnv_remove(DBEnvObject* self, PyObject* args)
3752{
3753 int err, flags=0;
3754 char *db_home;
3755
3756 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3757 return NULL;
3758 CHECK_ENV_NOT_CLOSED(self);
3759 MYDB_BEGIN_ALLOW_THREADS;
3760 err = self->db_env->remove(self->db_env, db_home, flags);
3761 MYDB_END_ALLOW_THREADS;
3762 RETURN_IF_ERR();
3763 RETURN_NONE();
3764}
3765
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003766#if (DBVER >= 41)
3767static PyObject*
3768DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3769{
3770 int err;
3771 u_int32_t flags=0;
3772 char *file = NULL;
3773 char *database = NULL;
3774 PyObject *txnobj = NULL;
3775 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003776 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003777 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003778
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003779 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003780 &file, &database, &txnobj, &flags)) {
3781 return NULL;
3782 }
3783 if (!checkTxnObj(txnobj, &txn)) {
3784 return NULL;
3785 }
3786 CHECK_ENV_NOT_CLOSED(self);
3787 MYDB_BEGIN_ALLOW_THREADS;
3788 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3789 MYDB_END_ALLOW_THREADS;
3790 RETURN_IF_ERR();
3791 RETURN_NONE();
3792}
3793
3794static PyObject*
3795DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3796{
3797 int err;
3798 u_int32_t flags=0;
3799 char *file = NULL;
3800 char *database = NULL;
3801 char *newname = NULL;
3802 PyObject *txnobj = NULL;
3803 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003804 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003805 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003806
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003807 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003808 &file, &database, &newname, &txnobj, &flags)) {
3809 return NULL;
3810 }
3811 if (!checkTxnObj(txnobj, &txn)) {
3812 return NULL;
3813 }
3814 CHECK_ENV_NOT_CLOSED(self);
3815 MYDB_BEGIN_ALLOW_THREADS;
3816 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3817 flags);
3818 MYDB_END_ALLOW_THREADS;
3819 RETURN_IF_ERR();
3820 RETURN_NONE();
3821}
3822
3823static PyObject*
3824DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3825{
3826 int err;
3827 u_int32_t flags=0;
3828 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003829 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003830
3831 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3832 &passwd, &flags)) {
3833 return NULL;
3834 }
3835
3836 MYDB_BEGIN_ALLOW_THREADS;
3837 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3838 MYDB_END_ALLOW_THREADS;
3839
3840 RETURN_IF_ERR();
3841 RETURN_NONE();
3842}
3843#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003844
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003845#if (DBVER >= 40)
3846static PyObject*
3847DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3848{
3849 int err;
3850 u_int32_t flags=0;
3851 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003852 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003853
3854 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3855 &timeout, &flags)) {
3856 return NULL;
3857 }
3858
3859 MYDB_BEGIN_ALLOW_THREADS;
3860 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3861 MYDB_END_ALLOW_THREADS;
3862
3863 RETURN_IF_ERR();
3864 RETURN_NONE();
3865}
3866#endif /* DBVER >= 40 */
3867
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003868static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003869DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3870{
3871 int err;
3872 long shm_key = 0;
3873
3874 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3875 return NULL;
3876 CHECK_ENV_NOT_CLOSED(self);
3877
3878 err = self->db_env->set_shm_key(self->db_env, shm_key);
3879 RETURN_IF_ERR();
3880 RETURN_NONE();
3881}
3882
3883static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003884DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3885{
3886 int err, gbytes=0, bytes=0, ncache=0;
3887
3888 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3889 &gbytes, &bytes, &ncache))
3890 return NULL;
3891 CHECK_ENV_NOT_CLOSED(self);
3892
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3898}
3899
3900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003901static PyObject*
3902DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3903{
3904 int err, flags=0, onoff=0;
3905
3906 if (!PyArg_ParseTuple(args, "ii:set_flags",
3907 &flags, &onoff))
3908 return NULL;
3909 CHECK_ENV_NOT_CLOSED(self);
3910
3911 MYDB_BEGIN_ALLOW_THREADS;
3912 err = self->db_env->set_flags(self->db_env, flags, onoff);
3913 MYDB_END_ALLOW_THREADS;
3914 RETURN_IF_ERR();
3915 RETURN_NONE();
3916}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003917
3918
3919static PyObject*
3920DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3921{
3922 int err;
3923 char *dir;
3924
3925 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3926 return NULL;
3927 CHECK_ENV_NOT_CLOSED(self);
3928
3929 MYDB_BEGIN_ALLOW_THREADS;
3930 err = self->db_env->set_data_dir(self->db_env, dir);
3931 MYDB_END_ALLOW_THREADS;
3932 RETURN_IF_ERR();
3933 RETURN_NONE();
3934}
3935
3936
3937static PyObject*
3938DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3939{
3940 int err, lg_bsize;
3941
3942 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3943 return NULL;
3944 CHECK_ENV_NOT_CLOSED(self);
3945
3946 MYDB_BEGIN_ALLOW_THREADS;
3947 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3948 MYDB_END_ALLOW_THREADS;
3949 RETURN_IF_ERR();
3950 RETURN_NONE();
3951}
3952
3953
3954static PyObject*
3955DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3956{
3957 int err;
3958 char *dir;
3959
3960 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3961 return NULL;
3962 CHECK_ENV_NOT_CLOSED(self);
3963
3964 MYDB_BEGIN_ALLOW_THREADS;
3965 err = self->db_env->set_lg_dir(self->db_env, dir);
3966 MYDB_END_ALLOW_THREADS;
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3969}
3970
3971static PyObject*
3972DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3973{
3974 int err, lg_max;
3975
3976 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3977 return NULL;
3978 CHECK_ENV_NOT_CLOSED(self);
3979
3980 MYDB_BEGIN_ALLOW_THREADS;
3981 err = self->db_env->set_lg_max(self->db_env, lg_max);
3982 MYDB_END_ALLOW_THREADS;
3983 RETURN_IF_ERR();
3984 RETURN_NONE();
3985}
3986
3987
Neal Norwitz84562352005-10-20 04:30:15 +00003988#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003990DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3991{
3992 int err, lg_max;
3993
3994 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3995 return NULL;
3996 CHECK_ENV_NOT_CLOSED(self);
3997
3998 MYDB_BEGIN_ALLOW_THREADS;
3999 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4000 MYDB_END_ALLOW_THREADS;
4001 RETURN_IF_ERR();
4002 RETURN_NONE();
4003}
Neal Norwitz84562352005-10-20 04:30:15 +00004004#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004005
4006
4007static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004008DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4009{
4010 int err, lk_detect;
4011
4012 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4015
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4021}
4022
4023
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004024#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004025static PyObject*
4026DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4027{
4028 int err, max;
4029
4030 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4031 return NULL;
4032 CHECK_ENV_NOT_CLOSED(self);
4033
4034 MYDB_BEGIN_ALLOW_THREADS;
4035 err = self->db_env->set_lk_max(self->db_env, max);
4036 MYDB_END_ALLOW_THREADS;
4037 RETURN_IF_ERR();
4038 RETURN_NONE();
4039}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004040#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004041
4042
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004043
4044static PyObject*
4045DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4046{
4047 int err, max;
4048
4049 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4050 return NULL;
4051 CHECK_ENV_NOT_CLOSED(self);
4052
4053 MYDB_BEGIN_ALLOW_THREADS;
4054 err = self->db_env->set_lk_max_locks(self->db_env, max);
4055 MYDB_END_ALLOW_THREADS;
4056 RETURN_IF_ERR();
4057 RETURN_NONE();
4058}
4059
4060
4061static PyObject*
4062DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4063{
4064 int err, max;
4065
4066 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4069
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4075}
4076
4077
4078static PyObject*
4079DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4080{
4081 int err, max;
4082
4083 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4084 return NULL;
4085 CHECK_ENV_NOT_CLOSED(self);
4086
4087 MYDB_BEGIN_ALLOW_THREADS;
4088 err = self->db_env->set_lk_max_objects(self->db_env, max);
4089 MYDB_END_ALLOW_THREADS;
4090 RETURN_IF_ERR();
4091 RETURN_NONE();
4092}
4093
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004094
4095static PyObject*
4096DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4097{
4098 int err, mp_mmapsize;
4099
4100 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4103
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4109}
4110
4111
4112static PyObject*
4113DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4114{
4115 int err;
4116 char *dir;
4117
4118 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4121
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_tmp_dir(self->db_env, dir);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4127}
4128
4129
4130static PyObject*
4131DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4132{
4133 int flags = 0;
4134 PyObject* txnobj = NULL;
4135 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004136 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004137
4138 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4139 &txnobj, &flags))
4140 return NULL;
4141
4142 if (!checkTxnObj(txnobj, &txn))
4143 return NULL;
4144 CHECK_ENV_NOT_CLOSED(self);
4145
4146 return (PyObject*)newDBTxnObject(self, txn, flags);
4147}
4148
4149
4150static PyObject*
4151DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4152{
4153 int err, kbyte=0, min=0, flags=0;
4154
4155 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160#if (DBVER >= 40)
4161 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4162#else
4163 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4164#endif
4165 MYDB_END_ALLOW_THREADS;
4166 RETURN_IF_ERR();
4167 RETURN_NONE();
4168}
4169
4170
4171static PyObject*
4172DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4173{
4174 int err, max;
4175
4176 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4177 return NULL;
4178 CHECK_ENV_NOT_CLOSED(self);
4179
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004180 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004181 RETURN_IF_ERR();
4182 RETURN_NONE();
4183}
4184
4185
4186static PyObject*
4187DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4188{
4189 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004190 long stamp;
4191 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004192
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004193 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004194 return NULL;
4195 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004196 timestamp = (time_t)stamp;
4197 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
4201
4202
4203static PyObject*
4204DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4205{
4206 int err, atype, flags=0;
4207 int aborted = 0;
4208
4209 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214#if (DBVER >= 40)
4215 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4216#else
4217 err = lock_detect(self->db_env, flags, atype, &aborted);
4218#endif
4219 MYDB_END_ALLOW_THREADS;
4220 RETURN_IF_ERR();
4221 return PyInt_FromLong(aborted);
4222}
4223
4224
4225static PyObject*
4226DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4227{
4228 int flags=0;
4229 int locker, lock_mode;
4230 DBT obj;
4231 PyObject* objobj;
4232
4233 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4234 return NULL;
4235
4236
4237 if (!make_dbt(objobj, &obj))
4238 return NULL;
4239
4240 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4241}
4242
4243
4244static PyObject*
4245DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4246{
4247 int err;
4248 u_int32_t theID;
4249
4250 if (!PyArg_ParseTuple(args, ":lock_id"))
4251 return NULL;
4252
4253 CHECK_ENV_NOT_CLOSED(self);
4254 MYDB_BEGIN_ALLOW_THREADS;
4255#if (DBVER >= 40)
4256 err = self->db_env->lock_id(self->db_env, &theID);
4257#else
4258 err = lock_id(self->db_env, &theID);
4259#endif
4260 MYDB_END_ALLOW_THREADS;
4261 RETURN_IF_ERR();
4262
4263 return PyInt_FromLong((long)theID);
4264}
4265
4266
4267static PyObject*
4268DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4269{
4270 int err;
4271 DBLockObject* dblockobj;
4272
4273 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4274 return NULL;
4275
4276 CHECK_ENV_NOT_CLOSED(self);
4277 MYDB_BEGIN_ALLOW_THREADS;
4278#if (DBVER >= 40)
4279 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4280#else
4281 err = lock_put(self->db_env, &dblockobj->lock);
4282#endif
4283 MYDB_END_ALLOW_THREADS;
4284 RETURN_IF_ERR();
4285 RETURN_NONE();
4286}
4287
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004288#if (DBVER >= 44)
4289static PyObject*
4290DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4291{
4292 int err;
4293 char *file;
4294 u_int32_t flags = 0;
4295 static char* kwnames[] = { "file", "flags", NULL};
4296
4297 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4298 &file, &flags))
4299 return NULL;
4300 CHECK_ENV_NOT_CLOSED(self);
4301
4302 MYDB_BEGIN_ALLOW_THREADS;
4303 err = self->db_env->lsn_reset(self->db_env, file, flags);
4304 MYDB_END_ALLOW_THREADS;
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307}
4308#endif /* DBVER >= 4.4 */
4309
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004310#if (DBVER >= 40)
4311static PyObject*
4312DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4313{
4314 int err;
4315 DB_LOG_STAT* statp = NULL;
4316 PyObject* d = NULL;
4317 u_int32_t flags = 0;
4318
4319 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4320 return NULL;
4321 CHECK_ENV_NOT_CLOSED(self);
4322
4323 MYDB_BEGIN_ALLOW_THREADS;
4324 err = self->db_env->log_stat(self->db_env, &statp, flags);
4325 MYDB_END_ALLOW_THREADS;
4326 RETURN_IF_ERR();
4327
4328 /* Turn the stat structure into a dictionary */
4329 d = PyDict_New();
4330 if (d == NULL) {
4331 if (statp)
4332 free(statp);
4333 return NULL;
4334 }
4335
4336#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4337
4338 MAKE_ENTRY(magic);
4339 MAKE_ENTRY(version);
4340 MAKE_ENTRY(mode);
4341 MAKE_ENTRY(lg_bsize);
4342#if (DBVER >= 44)
4343 MAKE_ENTRY(lg_size);
4344 MAKE_ENTRY(record);
4345#endif
4346#if (DBVER <= 40)
4347 MAKE_ENTRY(lg_max);
4348#endif
4349 MAKE_ENTRY(w_mbytes);
4350 MAKE_ENTRY(w_bytes);
4351 MAKE_ENTRY(wc_mbytes);
4352 MAKE_ENTRY(wc_bytes);
4353 MAKE_ENTRY(wcount);
4354 MAKE_ENTRY(wcount_fill);
4355#if (DBVER >= 44)
4356 MAKE_ENTRY(rcount);
4357#endif
4358 MAKE_ENTRY(scount);
4359 MAKE_ENTRY(cur_file);
4360 MAKE_ENTRY(cur_offset);
4361 MAKE_ENTRY(disk_file);
4362 MAKE_ENTRY(disk_offset);
4363 MAKE_ENTRY(maxcommitperflush);
4364 MAKE_ENTRY(mincommitperflush);
4365 MAKE_ENTRY(regsize);
4366 MAKE_ENTRY(region_wait);
4367 MAKE_ENTRY(region_nowait);
4368
4369#undef MAKE_ENTRY
4370 free(statp);
4371 return d;
4372} /* DBEnv_log_stat */
4373#endif /* DBVER >= 4.0 for log_stat method */
4374
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004375
4376static PyObject*
4377DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4378{
4379 int err;
4380 DB_LOCK_STAT* sp;
4381 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004382 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004383
4384 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4385 return NULL;
4386 CHECK_ENV_NOT_CLOSED(self);
4387
4388 MYDB_BEGIN_ALLOW_THREADS;
4389#if (DBVER >= 40)
4390 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4391#else
4392#if (DBVER >= 33)
4393 err = lock_stat(self->db_env, &sp);
4394#else
4395 err = lock_stat(self->db_env, &sp, NULL);
4396#endif
4397#endif
4398 MYDB_END_ALLOW_THREADS;
4399 RETURN_IF_ERR();
4400
4401 /* Turn the stat structure into a dictionary */
4402 d = PyDict_New();
4403 if (d == NULL) {
4404 free(sp);
4405 return NULL;
4406 }
4407
4408#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4409
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004410#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004411 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004412#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004413 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004414 MAKE_ENTRY(maxlocks);
4415 MAKE_ENTRY(maxlockers);
4416 MAKE_ENTRY(maxobjects);
4417 MAKE_ENTRY(nlocks);
4418 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004419 MAKE_ENTRY(nlockers);
4420 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004421 MAKE_ENTRY(nobjects);
4422 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004423 MAKE_ENTRY(nrequests);
4424 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004425#if (DBVER < 44)
4426 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004427 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004428#else
4429 MAKE_ENTRY(lock_nowait);
4430 MAKE_ENTRY(lock_wait);
4431#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004432 MAKE_ENTRY(ndeadlocks);
4433 MAKE_ENTRY(regsize);
4434 MAKE_ENTRY(region_wait);
4435 MAKE_ENTRY(region_nowait);
4436
4437#undef MAKE_ENTRY
4438 free(sp);
4439 return d;
4440}
4441
4442
4443static PyObject*
4444DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4445{
4446 int flags=0;
4447 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004448 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004449 PyObject* list;
4450 PyObject* item = NULL;
4451
4452 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4453 return NULL;
4454
4455 CHECK_ENV_NOT_CLOSED(self);
4456 MYDB_BEGIN_ALLOW_THREADS;
4457#if (DBVER >= 40)
4458 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4459#elif (DBVER == 33)
4460 err = log_archive(self->db_env, &log_list, flags);
4461#else
4462 err = log_archive(self->db_env, &log_list, flags, NULL);
4463#endif
4464 MYDB_END_ALLOW_THREADS;
4465 RETURN_IF_ERR();
4466
Gregory P. Smithbad47452006-06-05 00:33:35 +00004467 list = PyList_New(0);
4468 if (list == NULL) {
4469 if (log_list)
4470 free(log_list);
4471 return NULL;
4472 }
4473
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004474 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004475 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004476 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4477 item = PyString_FromString (*log_list);
4478 if (item == NULL) {
4479 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004480 list = NULL;
4481 break;
4482 }
4483 PyList_Append(list, item);
4484 Py_DECREF(item);
4485 }
4486 free(log_list_start);
4487 }
4488 return list;
4489}
4490
4491
4492static PyObject*
4493DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4494{
4495 int err;
4496 DB_TXN_STAT* sp;
4497 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004498 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004499
4500 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4501 return NULL;
4502 CHECK_ENV_NOT_CLOSED(self);
4503
4504 MYDB_BEGIN_ALLOW_THREADS;
4505#if (DBVER >= 40)
4506 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4507#elif (DBVER == 33)
4508 err = txn_stat(self->db_env, &sp);
4509#else
4510 err = txn_stat(self->db_env, &sp, NULL);
4511#endif
4512 MYDB_END_ALLOW_THREADS;
4513 RETURN_IF_ERR();
4514
4515 /* Turn the stat structure into a dictionary */
4516 d = PyDict_New();
4517 if (d == NULL) {
4518 free(sp);
4519 return NULL;
4520 }
4521
4522#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004523#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004524
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004525 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004526 MAKE_ENTRY(last_txnid);
4527 MAKE_ENTRY(maxtxns);
4528 MAKE_ENTRY(nactive);
4529 MAKE_ENTRY(maxnactive);
4530 MAKE_ENTRY(nbegins);
4531 MAKE_ENTRY(naborts);
4532 MAKE_ENTRY(ncommits);
4533 MAKE_ENTRY(regsize);
4534 MAKE_ENTRY(region_wait);
4535 MAKE_ENTRY(region_nowait);
4536
4537#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004538#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 free(sp);
4540 return d;
4541}
4542
4543
4544static PyObject*
4545DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4546{
4547 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004548 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004549
4550 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4551 return NULL;
4552 CHECK_ENV_NOT_CLOSED(self);
4553
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004554 if (self->moduleFlags.getReturnsNone)
4555 ++oldValue;
4556 if (self->moduleFlags.cursorSetReturnsNone)
4557 ++oldValue;
4558 self->moduleFlags.getReturnsNone = (flags >= 1);
4559 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560 return PyInt_FromLong(oldValue);
4561}
4562
4563
4564/* --------------------------------------------------------------------- */
4565/* DBTxn methods */
4566
4567
4568static PyObject*
4569DBTxn_commit(DBTxnObject* self, PyObject* args)
4570{
4571 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004572 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004573
4574 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4575 return NULL;
4576
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004577 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004578 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4579 "after txn_commit or txn_abort");
4580 PyErr_SetObject(DBError, t);
4581 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004582 return NULL;
4583 }
4584 txn = self->txn;
4585 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004586 MYDB_BEGIN_ALLOW_THREADS;
4587#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004588 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004590 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004591#endif
4592 MYDB_END_ALLOW_THREADS;
4593 RETURN_IF_ERR();
4594 RETURN_NONE();
4595}
4596
4597static PyObject*
4598DBTxn_prepare(DBTxnObject* self, PyObject* args)
4599{
4600#if (DBVER >= 33)
4601 int err;
4602 char* gid=NULL;
4603 int gid_size=0;
4604
4605 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4606 return NULL;
4607
4608 if (gid_size != DB_XIDDATASIZE) {
4609 PyErr_SetString(PyExc_TypeError,
4610 "gid must be DB_XIDDATASIZE bytes long");
4611 return NULL;
4612 }
4613
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004614 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004615 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4616 "after txn_commit or txn_abort");
4617 PyErr_SetObject(DBError, t);
4618 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004619 return NULL;
4620 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004621 MYDB_BEGIN_ALLOW_THREADS;
4622#if (DBVER >= 40)
4623 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4624#else
4625 err = txn_prepare(self->txn, (u_int8_t*)gid);
4626#endif
4627 MYDB_END_ALLOW_THREADS;
4628 RETURN_IF_ERR();
4629 RETURN_NONE();
4630#else
4631 int err;
4632
4633 if (!PyArg_ParseTuple(args, ":prepare"))
4634 return NULL;
4635
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004636 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004637 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4638 "after txn_commit or txn_abort");
4639 PyErr_SetObject(DBError, t);
4640 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004641 return NULL;
4642 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004643 MYDB_BEGIN_ALLOW_THREADS;
4644 err = txn_prepare(self->txn);
4645 MYDB_END_ALLOW_THREADS;
4646 RETURN_IF_ERR();
4647 RETURN_NONE();
4648#endif
4649}
4650
4651
4652static PyObject*
4653DBTxn_abort(DBTxnObject* self, PyObject* args)
4654{
4655 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004656 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004657
4658 if (!PyArg_ParseTuple(args, ":abort"))
4659 return NULL;
4660
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004661 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004662 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4663 "after txn_commit or txn_abort");
4664 PyErr_SetObject(DBError, t);
4665 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004666 return NULL;
4667 }
4668 txn = self->txn;
4669 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004670 MYDB_BEGIN_ALLOW_THREADS;
4671#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004672 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004673#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004674 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004675#endif
4676 MYDB_END_ALLOW_THREADS;
4677 RETURN_IF_ERR();
4678 RETURN_NONE();
4679}
4680
4681
4682static PyObject*
4683DBTxn_id(DBTxnObject* self, PyObject* args)
4684{
4685 int id;
4686
4687 if (!PyArg_ParseTuple(args, ":id"))
4688 return NULL;
4689
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004690 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004691 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4692 "after txn_commit or txn_abort");
4693 PyErr_SetObject(DBError, t);
4694 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004695 return NULL;
4696 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004697 MYDB_BEGIN_ALLOW_THREADS;
4698#if (DBVER >= 40)
4699 id = self->txn->id(self->txn);
4700#else
4701 id = txn_id(self->txn);
4702#endif
4703 MYDB_END_ALLOW_THREADS;
4704 return PyInt_FromLong(id);
4705}
4706
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004707#if (DBVER >= 43)
4708/* --------------------------------------------------------------------- */
4709/* DBSequence methods */
4710
4711
4712static PyObject*
4713DBSequence_close(DBSequenceObject* self, PyObject* args)
4714{
4715 int err, flags=0;
4716 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4717 return NULL;
4718 CHECK_SEQUENCE_NOT_CLOSED(self)
4719
4720 MYDB_BEGIN_ALLOW_THREADS
4721 err = self->sequence->close(self->sequence, flags);
4722 self->sequence = NULL;
4723 MYDB_END_ALLOW_THREADS
4724
4725 RETURN_IF_ERR();
4726
4727 RETURN_NONE();
4728}
4729
4730static PyObject*
4731DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4732{
4733 int err, flags = 0;
4734 int delta = 1;
4735 db_seq_t value;
4736 PyObject *txnobj = NULL;
4737 DB_TXN *txn = NULL;
4738 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4739 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4740 return NULL;
4741 CHECK_SEQUENCE_NOT_CLOSED(self)
4742
4743 if (!checkTxnObj(txnobj, &txn))
4744 return NULL;
4745
4746 MYDB_BEGIN_ALLOW_THREADS
4747 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4748 MYDB_END_ALLOW_THREADS
4749
4750 RETURN_IF_ERR();
4751 return PyLong_FromLongLong(value);
4752
4753}
4754
4755static PyObject*
4756DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4757{
4758 if (!PyArg_ParseTuple(args,":get_dbp"))
4759 return NULL;
4760 CHECK_SEQUENCE_NOT_CLOSED(self)
4761 Py_INCREF(self->mydb);
4762 return (PyObject* )self->mydb;
4763}
4764
4765static PyObject*
4766DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4767{
4768 int err;
4769 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00004770 PyObject *retval = NULL;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004771 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004772 CHECK_SEQUENCE_NOT_CLOSED(self)
4773 MYDB_BEGIN_ALLOW_THREADS
4774 err = self->sequence->get_key(self->sequence, &key);
4775 MYDB_END_ALLOW_THREADS
4776
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004777 if (!err)
4778 retval = PyString_FromStringAndSize(key.data, key.size);
4779
4780 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004781 RETURN_IF_ERR();
4782
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004783 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004784}
4785
4786static PyObject*
4787DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4788{
4789 int err;
4790 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004791 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004792 return NULL;
4793 CHECK_SEQUENCE_NOT_CLOSED(self)
4794
4795 MYDB_BEGIN_ALLOW_THREADS
4796 err = self->sequence->initial_value(self->sequence, value);
4797 MYDB_END_ALLOW_THREADS
4798
4799 RETURN_IF_ERR();
4800
4801 RETURN_NONE();
4802}
4803
4804static PyObject*
4805DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4806{
4807 int err, flags = 0;
4808 PyObject* keyobj;
4809 PyObject *txnobj = NULL;
4810 DB_TXN *txn = NULL;
4811 DBT key;
4812
4813 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004814 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004815 return NULL;
4816
4817 if (!checkTxnObj(txnobj, &txn))
4818 return NULL;
4819
4820 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4821 return NULL;
4822
4823 MYDB_BEGIN_ALLOW_THREADS
4824 err = self->sequence->open(self->sequence, txn, &key, flags);
4825 MYDB_END_ALLOW_THREADS
4826
4827 CLEAR_DBT(key);
4828 RETURN_IF_ERR();
4829
4830 RETURN_NONE();
4831}
4832
4833static PyObject*
4834DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4835{
4836 int err, flags = 0;
4837 PyObject *txnobj = NULL;
4838 DB_TXN *txn = NULL;
4839
4840 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004841 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004842 return NULL;
4843
4844 if (!checkTxnObj(txnobj, &txn))
4845 return NULL;
4846
4847 CHECK_SEQUENCE_NOT_CLOSED(self)
4848
4849 MYDB_BEGIN_ALLOW_THREADS
4850 err = self->sequence->remove(self->sequence, txn, flags);
4851 MYDB_END_ALLOW_THREADS
4852
4853 RETURN_IF_ERR();
4854 RETURN_NONE();
4855}
4856
4857static PyObject*
4858DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4859{
4860 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004861 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004862 return NULL;
4863 CHECK_SEQUENCE_NOT_CLOSED(self)
4864
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err = self->sequence->set_cachesize(self->sequence, size);
4867 MYDB_END_ALLOW_THREADS
4868
4869 RETURN_IF_ERR();
4870 RETURN_NONE();
4871}
4872
4873static PyObject*
4874DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4875{
4876 int err, size;
4877 if (!PyArg_ParseTuple(args,":get_cachesize"))
4878 return NULL;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err = self->sequence->get_cachesize(self->sequence, &size);
4883 MYDB_END_ALLOW_THREADS
4884
4885 RETURN_IF_ERR();
4886 return PyInt_FromLong(size);
4887}
4888
4889static PyObject*
4890DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4891{
4892 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004893 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004894 return NULL;
4895 CHECK_SEQUENCE_NOT_CLOSED(self)
4896
4897 MYDB_BEGIN_ALLOW_THREADS
4898 err = self->sequence->set_flags(self->sequence, flags);
4899 MYDB_END_ALLOW_THREADS
4900
4901 RETURN_IF_ERR();
4902 RETURN_NONE();
4903
4904}
4905
4906static PyObject*
4907DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4908{
4909 unsigned int flags;
4910 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004911 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004912 return NULL;
4913 CHECK_SEQUENCE_NOT_CLOSED(self)
4914
4915 MYDB_BEGIN_ALLOW_THREADS
4916 err = self->sequence->get_flags(self->sequence, &flags);
4917 MYDB_END_ALLOW_THREADS
4918
4919 RETURN_IF_ERR();
4920 return PyInt_FromLong((int)flags);
4921}
4922
4923static PyObject*
4924DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4925{
4926 int err;
4927 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004928 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004929 return NULL;
4930 CHECK_SEQUENCE_NOT_CLOSED(self)
4931
4932 MYDB_BEGIN_ALLOW_THREADS
4933 err = self->sequence->set_range(self->sequence, min, max);
4934 MYDB_END_ALLOW_THREADS
4935
4936 RETURN_IF_ERR();
4937 RETURN_NONE();
4938}
4939
4940static PyObject*
4941DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4942{
4943 int err;
4944 db_seq_t min, max;
4945 if (!PyArg_ParseTuple(args,":get_range"))
4946 return NULL;
4947 CHECK_SEQUENCE_NOT_CLOSED(self)
4948
4949 MYDB_BEGIN_ALLOW_THREADS
4950 err = self->sequence->get_range(self->sequence, &min, &max);
4951 MYDB_END_ALLOW_THREADS
4952
4953 RETURN_IF_ERR();
4954 return Py_BuildValue("(LL)", min, max);
4955}
4956
4957static PyObject*
4958DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4959{
4960 int err, flags = 0;
4961 DB_SEQUENCE_STAT* sp = NULL;
4962 PyObject* dict_stat;
4963 static char* kwnames[] = {"flags", NULL };
4964 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4965 return NULL;
4966 CHECK_SEQUENCE_NOT_CLOSED(self);
4967
4968 MYDB_BEGIN_ALLOW_THREADS;
4969 err = self->sequence->stat(self->sequence, &sp, flags);
4970 MYDB_END_ALLOW_THREADS;
4971 RETURN_IF_ERR();
4972
4973 if ((dict_stat = PyDict_New()) == NULL) {
4974 free(sp);
4975 return NULL;
4976 }
4977
4978
4979#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4980#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4981
4982 MAKE_INT_ENTRY(wait);
4983 MAKE_INT_ENTRY(nowait);
4984 MAKE_LONG_LONG_ENTRY(current);
4985 MAKE_LONG_LONG_ENTRY(value);
4986 MAKE_LONG_LONG_ENTRY(last_value);
4987 MAKE_LONG_LONG_ENTRY(min);
4988 MAKE_LONG_LONG_ENTRY(max);
4989 MAKE_INT_ENTRY(cache_size);
4990 MAKE_INT_ENTRY(flags);
4991
4992#undef MAKE_INT_ENTRY
4993#undef MAKE_LONG_LONG_ENTRY
4994
4995 free(sp);
4996 return dict_stat;
4997}
4998#endif
4999
5000
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005001/* --------------------------------------------------------------------- */
5002/* Method definition tables and type objects */
5003
5004static PyMethodDef DB_methods[] = {
5005 {"append", (PyCFunction)DB_append, METH_VARARGS},
5006#if (DBVER >= 33)
5007 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5008#endif
5009 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005010 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5011 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005012 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5013 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5014 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5015 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005016#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005017 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005018#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005019 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5020 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5021 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5022 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5023 {"join", (PyCFunction)DB_join, METH_VARARGS},
5024 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5025 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5026 {"items", (PyCFunction)DB_items, METH_VARARGS},
5027 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5028 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5029 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5030 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5031 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5032 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005033#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005034 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005035#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005036 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005037#if (DBVER >= 41)
5038 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5039#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005040 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5041 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5042 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5043 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5044 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5045 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5046 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5047 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5048 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005049 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005050 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005051 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5052#if (DBVER >= 33)
5053 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5054#endif
5055 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5056 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5057 {"values", (PyCFunction)DB_values, METH_VARARGS},
5058 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5059 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5060 {NULL, NULL} /* sentinel */
5061};
5062
5063
5064static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005065 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005066 (binaryfunc)DB_subscript, /*mp_subscript*/
5067 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5068};
5069
5070
5071static PyMethodDef DBCursor_methods[] = {
5072 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5073 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5074 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5075 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5076 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5077 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5078 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005079#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005080 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005081#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005082 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5083 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5084 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5085 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5086 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5087 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5088 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5089 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005090 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005091 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005092 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5093 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5094 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5095 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5096 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5097 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5098 {NULL, NULL} /* sentinel */
5099};
5100
5101
5102static PyMethodDef DBEnv_methods[] = {
5103 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5104 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5105 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005106#if (DBVER >= 41)
5107 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5108 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5109 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5110#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005111#if (DBVER >= 40)
5112 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5113#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005114 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005115 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5116 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005117 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005118 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5119 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5120 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005121#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005122 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005123#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005124 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005125#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005127#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005128 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5129 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5130 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005131 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5132 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5133 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5134 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5135 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5136 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005137 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005138 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5139 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5140 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5141 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5142 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5143 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005144#if (DBVER >= 40)
5145 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5146#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005147#if (DBVER >= 44)
5148 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5149#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5151 {NULL, NULL} /* sentinel */
5152};
5153
5154
5155static PyMethodDef DBTxn_methods[] = {
5156 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5157 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5158 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5159 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5160 {NULL, NULL} /* sentinel */
5161};
5162
5163
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005164#if (DBVER >= 43)
5165static PyMethodDef DBSequence_methods[] = {
5166 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5167 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5168 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5169 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005170 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5171 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5172 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5173 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5174 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5175 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5176 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5177 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5178 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5179 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5180 {NULL, NULL} /* sentinel */
5181};
5182#endif
5183
5184
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005185static PyObject*
5186DB_getattr(DBObject* self, char *name)
5187{
5188 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5189}
5190
5191
5192static PyObject*
5193DBEnv_getattr(DBEnvObject* self, char *name)
5194{
5195 if (!strcmp(name, "db_home")) {
5196 CHECK_ENV_NOT_CLOSED(self);
5197 if (self->db_env->db_home == NULL) {
5198 RETURN_NONE();
5199 }
5200 return PyString_FromString(self->db_env->db_home);
5201 }
5202
5203 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5204}
5205
5206
5207static PyObject*
5208DBCursor_getattr(DBCursorObject* self, char *name)
5209{
5210 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5211}
5212
5213static PyObject*
5214DBTxn_getattr(DBTxnObject* self, char *name)
5215{
5216 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5217}
5218
5219static PyObject*
5220DBLock_getattr(DBLockObject* self, char *name)
5221{
5222 return NULL;
5223}
5224
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005225#if (DBVER >= 43)
5226static PyObject*
5227DBSequence_getattr(DBSequenceObject* self, char *name)
5228{
5229 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5230}
5231#endif
5232
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005233statichere PyTypeObject DB_Type = {
5234 PyObject_HEAD_INIT(NULL)
5235 0, /*ob_size*/
5236 "DB", /*tp_name*/
5237 sizeof(DBObject), /*tp_basicsize*/
5238 0, /*tp_itemsize*/
5239 /* methods */
5240 (destructor)DB_dealloc, /*tp_dealloc*/
5241 0, /*tp_print*/
5242 (getattrfunc)DB_getattr, /*tp_getattr*/
5243 0, /*tp_setattr*/
5244 0, /*tp_compare*/
5245 0, /*tp_repr*/
5246 0, /*tp_as_number*/
5247 0, /*tp_as_sequence*/
5248 &DB_mapping,/*tp_as_mapping*/
5249 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005250 0, /* tp_call */
5251 0, /* tp_str */
5252 0, /* tp_getattro */
5253 0, /* tp_setattro */
5254 0, /* tp_as_buffer */
5255 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5256 0, /* tp_doc */
5257 0, /* tp_traverse */
5258 0, /* tp_clear */
5259 0, /* tp_richcompare */
5260 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005261};
5262
5263
5264statichere PyTypeObject DBCursor_Type = {
5265 PyObject_HEAD_INIT(NULL)
5266 0, /*ob_size*/
5267 "DBCursor", /*tp_name*/
5268 sizeof(DBCursorObject), /*tp_basicsize*/
5269 0, /*tp_itemsize*/
5270 /* methods */
5271 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5272 0, /*tp_print*/
5273 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5274 0, /*tp_setattr*/
5275 0, /*tp_compare*/
5276 0, /*tp_repr*/
5277 0, /*tp_as_number*/
5278 0, /*tp_as_sequence*/
5279 0, /*tp_as_mapping*/
5280 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005281 0, /* tp_call */
5282 0, /* tp_str */
5283 0, /* tp_getattro */
5284 0, /* tp_setattro */
5285 0, /* tp_as_buffer */
5286 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5287 0, /* tp_doc */
5288 0, /* tp_traverse */
5289 0, /* tp_clear */
5290 0, /* tp_richcompare */
5291 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005292};
5293
5294
5295statichere PyTypeObject DBEnv_Type = {
5296 PyObject_HEAD_INIT(NULL)
5297 0, /*ob_size*/
5298 "DBEnv", /*tp_name*/
5299 sizeof(DBEnvObject), /*tp_basicsize*/
5300 0, /*tp_itemsize*/
5301 /* methods */
5302 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5303 0, /*tp_print*/
5304 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5305 0, /*tp_setattr*/
5306 0, /*tp_compare*/
5307 0, /*tp_repr*/
5308 0, /*tp_as_number*/
5309 0, /*tp_as_sequence*/
5310 0, /*tp_as_mapping*/
5311 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005312 0, /* tp_call */
5313 0, /* tp_str */
5314 0, /* tp_getattro */
5315 0, /* tp_setattro */
5316 0, /* tp_as_buffer */
5317 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5318 0, /* tp_doc */
5319 0, /* tp_traverse */
5320 0, /* tp_clear */
5321 0, /* tp_richcompare */
5322 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005323};
5324
5325statichere PyTypeObject DBTxn_Type = {
5326 PyObject_HEAD_INIT(NULL)
5327 0, /*ob_size*/
5328 "DBTxn", /*tp_name*/
5329 sizeof(DBTxnObject), /*tp_basicsize*/
5330 0, /*tp_itemsize*/
5331 /* methods */
5332 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5333 0, /*tp_print*/
5334 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5335 0, /*tp_setattr*/
5336 0, /*tp_compare*/
5337 0, /*tp_repr*/
5338 0, /*tp_as_number*/
5339 0, /*tp_as_sequence*/
5340 0, /*tp_as_mapping*/
5341 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005342 0, /* tp_call */
5343 0, /* tp_str */
5344 0, /* tp_getattro */
5345 0, /* tp_setattro */
5346 0, /* tp_as_buffer */
5347 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5348 0, /* tp_doc */
5349 0, /* tp_traverse */
5350 0, /* tp_clear */
5351 0, /* tp_richcompare */
5352 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005353};
5354
5355
5356statichere PyTypeObject DBLock_Type = {
5357 PyObject_HEAD_INIT(NULL)
5358 0, /*ob_size*/
5359 "DBLock", /*tp_name*/
5360 sizeof(DBLockObject), /*tp_basicsize*/
5361 0, /*tp_itemsize*/
5362 /* methods */
5363 (destructor)DBLock_dealloc, /*tp_dealloc*/
5364 0, /*tp_print*/
5365 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5366 0, /*tp_setattr*/
5367 0, /*tp_compare*/
5368 0, /*tp_repr*/
5369 0, /*tp_as_number*/
5370 0, /*tp_as_sequence*/
5371 0, /*tp_as_mapping*/
5372 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005373 0, /* tp_call */
5374 0, /* tp_str */
5375 0, /* tp_getattro */
5376 0, /* tp_setattro */
5377 0, /* tp_as_buffer */
5378 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5379 0, /* tp_doc */
5380 0, /* tp_traverse */
5381 0, /* tp_clear */
5382 0, /* tp_richcompare */
5383 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005384};
5385
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005386#if (DBVER >= 43)
5387statichere PyTypeObject DBSequence_Type = {
5388 PyObject_HEAD_INIT(NULL)
5389 0, /*ob_size*/
5390 "DBSequence", /*tp_name*/
5391 sizeof(DBSequenceObject), /*tp_basicsize*/
5392 0, /*tp_itemsize*/
5393 /* methods */
5394 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5395 0, /*tp_print*/
5396 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5397 0, /*tp_setattr*/
5398 0, /*tp_compare*/
5399 0, /*tp_repr*/
5400 0, /*tp_as_number*/
5401 0, /*tp_as_sequence*/
5402 0, /*tp_as_mapping*/
5403 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005404 0, /* tp_call */
5405 0, /* tp_str */
5406 0, /* tp_getattro */
5407 0, /* tp_setattro */
5408 0, /* tp_as_buffer */
5409 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5410 0, /* tp_doc */
5411 0, /* tp_traverse */
5412 0, /* tp_clear */
5413 0, /* tp_richcompare */
5414 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005415};
5416#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005417
5418/* --------------------------------------------------------------------- */
5419/* Module-level functions */
5420
5421static PyObject*
5422DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5423{
5424 PyObject* dbenvobj = NULL;
5425 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005426 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005427
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5429 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005430 return NULL;
5431 if (dbenvobj == Py_None)
5432 dbenvobj = NULL;
5433 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5434 makeTypeError("DBEnv", dbenvobj);
5435 return NULL;
5436 }
5437
5438 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5439}
5440
5441
5442static PyObject*
5443DBEnv_construct(PyObject* self, PyObject* args)
5444{
5445 int flags = 0;
5446 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5447 return (PyObject* )newDBEnvObject(flags);
5448}
5449
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005450#if (DBVER >= 43)
5451static PyObject*
5452DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5453{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005454 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005455 int flags = 0;
5456 static char* kwnames[] = { "db", "flags", NULL};
5457
5458 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5459 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005460 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005461 makeTypeError("DB", dbobj);
5462 return NULL;
5463 }
5464 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5465}
5466#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005467
5468static char bsddb_version_doc[] =
5469"Returns a tuple of major, minor, and patch release numbers of the\n\
5470underlying DB library.";
5471
5472static PyObject*
5473bsddb_version(PyObject* self, PyObject* args)
5474{
5475 int major, minor, patch;
5476
5477 if (!PyArg_ParseTuple(args, ":version"))
5478 return NULL;
5479 db_version(&major, &minor, &patch);
5480 return Py_BuildValue("(iii)", major, minor, patch);
5481}
5482
5483
5484/* List of functions defined in the module */
5485
5486static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005487 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5488 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5489#if (DBVER >= 43)
5490 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5491#endif
5492 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005493 {NULL, NULL} /* sentinel */
5494};
5495
Gregory P. Smith39250532007-10-09 06:02:21 +00005496/* API structure */
5497static BSDDB_api bsddb_api;
5498
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499
5500/* --------------------------------------------------------------------- */
5501/* Module initialization */
5502
5503
5504/* Convenience routine to export an integer value.
5505 * Errors are silently ignored, for better or for worse...
5506 */
5507#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5508
Gregory P. Smith41631e82003-09-21 00:08:14 +00005509#define MODULE_NAME_MAX_LEN 11
5510static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005511
5512DL_EXPORT(void) init_bsddb(void)
5513{
5514 PyObject* m;
5515 PyObject* d;
5516 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5517 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5518 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005519 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005520
5521 /* Initialize the type of the new type objects here; doing it here
5522 is required for portability to Windows without requiring C++. */
Martin v. Löwis68192102007-07-21 06:55:02 +00005523 Py_Type(&DB_Type) = &PyType_Type;
5524 Py_Type(&DBCursor_Type) = &PyType_Type;
5525 Py_Type(&DBEnv_Type) = &PyType_Type;
5526 Py_Type(&DBTxn_Type) = &PyType_Type;
5527 Py_Type(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005528#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +00005529 Py_Type(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005530#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005531
5532
Mark Hammonda69d4092003-04-22 23:13:27 +00005533#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005534 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005535 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536#endif
5537
5538 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005539 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005540 if (m == NULL)
5541 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005542
5543 /* Add some symbolic constants to the module */
5544 d = PyModule_GetDict(m);
5545 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5546 PyDict_SetItemString(d, "cvsid", cvsid_s);
5547 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5548 Py_DECREF(pybsddb_version_s);
5549 pybsddb_version_s = NULL;
5550 Py_DECREF(cvsid_s);
5551 cvsid_s = NULL;
5552 Py_DECREF(db_version_s);
5553 db_version_s = NULL;
5554
5555 ADD_INT(d, DB_VERSION_MAJOR);
5556 ADD_INT(d, DB_VERSION_MINOR);
5557 ADD_INT(d, DB_VERSION_PATCH);
5558
5559 ADD_INT(d, DB_MAX_PAGES);
5560 ADD_INT(d, DB_MAX_RECORDS);
5561
Gregory P. Smith41631e82003-09-21 00:08:14 +00005562#if (DBVER >= 42)
5563 ADD_INT(d, DB_RPCCLIENT);
5564#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005565 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005566 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5567 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5568#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005569 ADD_INT(d, DB_XA_CREATE);
5570
5571 ADD_INT(d, DB_CREATE);
5572 ADD_INT(d, DB_NOMMAP);
5573 ADD_INT(d, DB_THREAD);
5574
5575 ADD_INT(d, DB_FORCE);
5576 ADD_INT(d, DB_INIT_CDB);
5577 ADD_INT(d, DB_INIT_LOCK);
5578 ADD_INT(d, DB_INIT_LOG);
5579 ADD_INT(d, DB_INIT_MPOOL);
5580 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005581 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005582
5583 ADD_INT(d, DB_RECOVER);
5584 ADD_INT(d, DB_RECOVER_FATAL);
5585 ADD_INT(d, DB_TXN_NOSYNC);
5586 ADD_INT(d, DB_USE_ENVIRON);
5587 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5588
5589 ADD_INT(d, DB_LOCKDOWN);
5590 ADD_INT(d, DB_PRIVATE);
5591 ADD_INT(d, DB_SYSTEM_MEM);
5592
5593 ADD_INT(d, DB_TXN_SYNC);
5594 ADD_INT(d, DB_TXN_NOWAIT);
5595
5596 ADD_INT(d, DB_EXCL);
5597 ADD_INT(d, DB_FCNTL_LOCKING);
5598 ADD_INT(d, DB_ODDFILESIZE);
5599 ADD_INT(d, DB_RDWRMASTER);
5600 ADD_INT(d, DB_RDONLY);
5601 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005602 ADD_INT(d, DB_EXTENT);
5603 ADD_INT(d, DB_CDB_ALLDB);
5604 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005605 ADD_INT(d, DB_UPGRADE);
5606
5607 ADD_INT(d, DB_AGGRESSIVE);
5608 ADD_INT(d, DB_NOORDERCHK);
5609 ADD_INT(d, DB_ORDERCHKONLY);
5610 ADD_INT(d, DB_PR_PAGE);
5611#if ! (DBVER >= 33)
5612 ADD_INT(d, DB_VRFY_FLAGMASK);
5613 ADD_INT(d, DB_PR_HEADERS);
5614#endif
5615 ADD_INT(d, DB_PR_RECOVERYTEST);
5616 ADD_INT(d, DB_SALVAGE);
5617
5618 ADD_INT(d, DB_LOCK_NORUN);
5619 ADD_INT(d, DB_LOCK_DEFAULT);
5620 ADD_INT(d, DB_LOCK_OLDEST);
5621 ADD_INT(d, DB_LOCK_RANDOM);
5622 ADD_INT(d, DB_LOCK_YOUNGEST);
5623#if (DBVER >= 33)
5624 ADD_INT(d, DB_LOCK_MAXLOCKS);
5625 ADD_INT(d, DB_LOCK_MINLOCKS);
5626 ADD_INT(d, DB_LOCK_MINWRITE);
5627#endif
5628
5629
5630#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005631 /* docs say to use zero instead */
5632 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633#else
5634 ADD_INT(d, DB_LOCK_CONFLICT);
5635#endif
5636
5637 ADD_INT(d, DB_LOCK_DUMP);
5638 ADD_INT(d, DB_LOCK_GET);
5639 ADD_INT(d, DB_LOCK_INHERIT);
5640 ADD_INT(d, DB_LOCK_PUT);
5641 ADD_INT(d, DB_LOCK_PUT_ALL);
5642 ADD_INT(d, DB_LOCK_PUT_OBJ);
5643
5644 ADD_INT(d, DB_LOCK_NG);
5645 ADD_INT(d, DB_LOCK_READ);
5646 ADD_INT(d, DB_LOCK_WRITE);
5647 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005648 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649 ADD_INT(d, DB_LOCK_IWRITE);
5650 ADD_INT(d, DB_LOCK_IREAD);
5651 ADD_INT(d, DB_LOCK_IWR);
5652#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005653#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005654 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005655#else
5656 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5657#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005658 ADD_INT(d, DB_LOCK_WWRITE);
5659#endif
5660
5661 ADD_INT(d, DB_LOCK_RECORD);
5662 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005663 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664#if (DBVER >= 33)
5665 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5666#endif
5667
5668 ADD_INT(d, DB_LOCK_NOWAIT);
5669 ADD_INT(d, DB_LOCK_RECORD);
5670 ADD_INT(d, DB_LOCK_UPGRADE);
5671
5672#if (DBVER >= 33)
5673 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005674#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005676#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005677 ADD_INT(d, DB_LSTAT_FREE);
5678 ADD_INT(d, DB_LSTAT_HELD);
5679#if (DBVER == 33)
5680 ADD_INT(d, DB_LSTAT_NOGRANT);
5681#endif
5682 ADD_INT(d, DB_LSTAT_PENDING);
5683 ADD_INT(d, DB_LSTAT_WAITING);
5684#endif
5685
5686 ADD_INT(d, DB_ARCH_ABS);
5687 ADD_INT(d, DB_ARCH_DATA);
5688 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005689#if (DBVER >= 42)
5690 ADD_INT(d, DB_ARCH_REMOVE);
5691#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005692
5693 ADD_INT(d, DB_BTREE);
5694 ADD_INT(d, DB_HASH);
5695 ADD_INT(d, DB_RECNO);
5696 ADD_INT(d, DB_QUEUE);
5697 ADD_INT(d, DB_UNKNOWN);
5698
5699 ADD_INT(d, DB_DUP);
5700 ADD_INT(d, DB_DUPSORT);
5701 ADD_INT(d, DB_RECNUM);
5702 ADD_INT(d, DB_RENUMBER);
5703 ADD_INT(d, DB_REVSPLITOFF);
5704 ADD_INT(d, DB_SNAPSHOT);
5705
5706 ADD_INT(d, DB_JOIN_NOSORT);
5707
5708 ADD_INT(d, DB_AFTER);
5709 ADD_INT(d, DB_APPEND);
5710 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005711#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005712 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005713#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005714#if (DBVER >= 41)
5715 _addIntToDict(d, "DB_CHECKPOINT", 0);
5716#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005717 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005718 ADD_INT(d, DB_CURLSN);
5719#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005720#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005721 ADD_INT(d, DB_COMMIT);
5722#endif
5723 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005724 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005725 ADD_INT(d, DB_CURRENT);
5726#if (DBVER >= 33)
5727 ADD_INT(d, DB_FAST_STAT);
5728#endif
5729 ADD_INT(d, DB_FIRST);
5730 ADD_INT(d, DB_FLUSH);
5731 ADD_INT(d, DB_GET_BOTH);
5732 ADD_INT(d, DB_GET_RECNO);
5733 ADD_INT(d, DB_JOIN_ITEM);
5734 ADD_INT(d, DB_KEYFIRST);
5735 ADD_INT(d, DB_KEYLAST);
5736 ADD_INT(d, DB_LAST);
5737 ADD_INT(d, DB_NEXT);
5738 ADD_INT(d, DB_NEXT_DUP);
5739 ADD_INT(d, DB_NEXT_NODUP);
5740 ADD_INT(d, DB_NODUPDATA);
5741 ADD_INT(d, DB_NOOVERWRITE);
5742 ADD_INT(d, DB_NOSYNC);
5743 ADD_INT(d, DB_POSITION);
5744 ADD_INT(d, DB_PREV);
5745 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005746#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005747 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005748#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005749 ADD_INT(d, DB_SET);
5750 ADD_INT(d, DB_SET_RANGE);
5751 ADD_INT(d, DB_SET_RECNO);
5752 ADD_INT(d, DB_WRITECURSOR);
5753
5754 ADD_INT(d, DB_OPFLAGS_MASK);
5755 ADD_INT(d, DB_RMW);
5756#if (DBVER >= 33)
5757 ADD_INT(d, DB_DIRTY_READ);
5758 ADD_INT(d, DB_MULTIPLE);
5759 ADD_INT(d, DB_MULTIPLE_KEY);
5760#endif
5761
Gregory P. Smith29602d22006-01-24 09:46:48 +00005762#if (DBVER >= 44)
5763 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5764 ADD_INT(d, DB_READ_COMMITTED);
5765#endif
5766
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005767#if (DBVER >= 33)
5768 ADD_INT(d, DB_DONOTINDEX);
5769#endif
5770
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005771#if (DBVER >= 41)
5772 _addIntToDict(d, "DB_INCOMPLETE", 0);
5773#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005774 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005776 ADD_INT(d, DB_KEYEMPTY);
5777 ADD_INT(d, DB_KEYEXIST);
5778 ADD_INT(d, DB_LOCK_DEADLOCK);
5779 ADD_INT(d, DB_LOCK_NOTGRANTED);
5780 ADD_INT(d, DB_NOSERVER);
5781 ADD_INT(d, DB_NOSERVER_HOME);
5782 ADD_INT(d, DB_NOSERVER_ID);
5783 ADD_INT(d, DB_NOTFOUND);
5784 ADD_INT(d, DB_OLD_VERSION);
5785 ADD_INT(d, DB_RUNRECOVERY);
5786 ADD_INT(d, DB_VERIFY_BAD);
5787#if (DBVER >= 33)
5788 ADD_INT(d, DB_PAGE_NOTFOUND);
5789 ADD_INT(d, DB_SECONDARY_BAD);
5790#endif
5791#if (DBVER >= 40)
5792 ADD_INT(d, DB_STAT_CLEAR);
5793 ADD_INT(d, DB_REGION_INIT);
5794 ADD_INT(d, DB_NOLOCKING);
5795 ADD_INT(d, DB_YIELDCPU);
5796 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5797 ADD_INT(d, DB_NOPANIC);
5798#endif
5799
Gregory P. Smithaae141a2007-11-01 21:08:14 +00005800#ifdef DB_REGISTER
5801 ADD_INT(d, DB_REGISTER);
5802#endif
5803
Gregory P. Smith41631e82003-09-21 00:08:14 +00005804#if (DBVER >= 42)
5805 ADD_INT(d, DB_TIME_NOTGRANTED);
5806 ADD_INT(d, DB_TXN_NOT_DURABLE);
5807 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5808 ADD_INT(d, DB_LOG_AUTOREMOVE);
5809 ADD_INT(d, DB_DIRECT_LOG);
5810 ADD_INT(d, DB_DIRECT_DB);
5811 ADD_INT(d, DB_INIT_REP);
5812 ADD_INT(d, DB_ENCRYPT);
5813 ADD_INT(d, DB_CHKSUM);
5814#endif
5815
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005816#if (DBVER >= 43)
5817 ADD_INT(d, DB_LOG_INMEMORY);
5818 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005819 ADD_INT(d, DB_SEQ_DEC);
5820 ADD_INT(d, DB_SEQ_INC);
5821 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005822#endif
5823
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005824#if (DBVER >= 41)
5825 ADD_INT(d, DB_ENCRYPT_AES);
5826 ADD_INT(d, DB_AUTO_COMMIT);
5827#else
5828 /* allow berkeleydb 4.1 aware apps to run on older versions */
5829 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5830#endif
5831
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005832 ADD_INT(d, EINVAL);
5833 ADD_INT(d, EACCES);
5834 ADD_INT(d, ENOSPC);
5835 ADD_INT(d, ENOMEM);
5836 ADD_INT(d, EAGAIN);
5837 ADD_INT(d, EBUSY);
5838 ADD_INT(d, EEXIST);
5839 ADD_INT(d, ENOENT);
5840 ADD_INT(d, EPERM);
5841
Barry Warsaw1baa9822003-03-31 19:51:29 +00005842#if (DBVER >= 40)
5843 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5844 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005847 /* The exception name must be correct for pickled exception *
5848 * objects to unpickle properly. */
5849#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5850#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5851#else
5852#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5853#endif
5854
5855 /* All the rest of the exceptions derive only from DBError */
5856#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5857 PyDict_SetItemString(d, #name, name)
5858
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005859 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005860 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5861 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005862
Gregory P. Smithe9477062005-06-04 06:46:59 +00005863 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5864 * from both DBError and KeyError, since the API only supports
5865 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005866 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005867 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5868 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005869 Py_file_input, d, d);
5870 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005871 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005872 PyDict_DelItemString(d, "KeyError");
5873
5874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875#if !INCOMPLETE_IS_WARNING
5876 MAKE_EX(DBIncompleteError);
5877#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005878 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 MAKE_EX(DBKeyEmptyError);
5880 MAKE_EX(DBKeyExistError);
5881 MAKE_EX(DBLockDeadlockError);
5882 MAKE_EX(DBLockNotGrantedError);
5883 MAKE_EX(DBOldVersionError);
5884 MAKE_EX(DBRunRecoveryError);
5885 MAKE_EX(DBVerifyBadError);
5886 MAKE_EX(DBNoServerError);
5887 MAKE_EX(DBNoServerHomeError);
5888 MAKE_EX(DBNoServerIDError);
5889#if (DBVER >= 33)
5890 MAKE_EX(DBPageNotFoundError);
5891 MAKE_EX(DBSecondaryBadError);
5892#endif
5893
5894 MAKE_EX(DBInvalidArgError);
5895 MAKE_EX(DBAccessError);
5896 MAKE_EX(DBNoSpaceError);
5897 MAKE_EX(DBNoMemoryError);
5898 MAKE_EX(DBAgainError);
5899 MAKE_EX(DBBusyError);
5900 MAKE_EX(DBFileExistsError);
5901 MAKE_EX(DBNoSuchFileError);
5902 MAKE_EX(DBPermissionsError);
5903
5904#undef MAKE_EX
5905
Gregory P. Smith39250532007-10-09 06:02:21 +00005906 /* Initiliase the C API structure and add it to the module */
5907 bsddb_api.db_type = &DB_Type;
5908 bsddb_api.dbcursor_type = &DBCursor_Type;
5909 bsddb_api.dbenv_type = &DBEnv_Type;
5910 bsddb_api.dbtxn_type = &DBTxn_Type;
5911 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005912#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00005913 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005914#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00005915 bsddb_api.makeDBError = makeDBError;
5916
5917 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5918 PyDict_SetItemString(d, "api", py_api);
5919 Py_DECREF(py_api);
5920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005921 /* Check for errors */
5922 if (PyErr_Occurred()) {
5923 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005924 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005925 }
5926}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005927
5928/* allow this module to be named _pybsddb so that it can be installed
5929 * and imported on top of python >= 2.3 that includes its own older
5930 * copy of the library named _bsddb without importing the old version. */
5931DL_EXPORT(void) init_pybsddb(void)
5932{
5933 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5934 init_bsddb();
5935}