blob: 11e02016142abac578811cef0319e5de2f0952a2 [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 */
338 key->data = strdup(PyString_AS_STRING(keyobj));
339 if (key->data == NULL) {
340 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
341 return 0;
342 }
343 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000344 key->size = PyString_GET_SIZE(keyobj);
345 }
346
347 else if (PyInt_Check(keyobj)) {
348 /* verify access method type */
349 type = _DB_get_type(self);
350 if (type == -1)
351 return 0;
352 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000353 /* if BTREE then an Integer key is allowed with the
354 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000355 *pflags |= DB_SET_RECNO;
356 }
357 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000358 PyErr_SetString(
359 PyExc_TypeError,
360 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000361 return 0;
362 }
363
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000364 /* Make a key out of the requested recno, use allocated space so DB
365 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000366 recno = PyInt_AS_LONG(keyobj);
367 key->data = malloc(sizeof(db_recno_t));
368 if (key->data == NULL) {
369 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
370 return 0;
371 }
372 key->ulen = key->size = sizeof(db_recno_t);
373 memcpy(key->data, &recno, sizeof(db_recno_t));
374 key->flags = DB_DBT_REALLOC;
375 }
376 else {
377 PyErr_Format(PyExc_TypeError,
378 "String or Integer object expected for key, %s found",
Martin v. Löwis68192102007-07-21 06:55:02 +0000379 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000380 return 0;
381 }
382
383 return 1;
384}
385
386
387/* Add partial record access to an existing DBT data struct.
388 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
389 and the data storage/retrieval will be done using dlen and doff. */
390static int add_partial_dbt(DBT* d, int dlen, int doff) {
391 /* if neither were set we do nothing (-1 is the default value) */
392 if ((dlen == -1) && (doff == -1)) {
393 return 1;
394 }
395
396 if ((dlen < 0) || (doff < 0)) {
397 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
398 return 0;
399 }
400
401 d->flags = d->flags | DB_DBT_PARTIAL;
402 d->dlen = (unsigned int) dlen;
403 d->doff = (unsigned int) doff;
404 return 1;
405}
406
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000407/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
408/* TODO: make this use the native libc strlcpy() when available (BSD) */
409unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
410{
411 unsigned int srclen, copylen;
412
413 srclen = strlen(src);
414 if (n <= 0)
415 return srclen;
416 copylen = (srclen > n-1) ? n-1 : srclen;
417 /* populate dest[0] thru dest[copylen-1] */
418 memcpy(dest, src, copylen);
419 /* guarantee null termination */
420 dest[copylen] = 0;
421
422 return srclen;
423}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000424
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000425/* Callback used to save away more information about errors from the DB
426 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000427static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000428#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000429static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000430#else
431static void _db_errorCallback(const DB_ENV *db_env,
432 const char* prefix, const char* msg)
433#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000434{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000435 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000436}
437
438
439/* make a nice exception object to raise for errors. */
440static int makeDBError(int err)
441{
442 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyObject *errObj = NULL;
444 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000445 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000446 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447
448 switch (err) {
449 case 0: /* successful, no error */ break;
450
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000451#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000452 case DB_INCOMPLETE:
453#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000454 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
455 /* Ensure that bytes_left never goes negative */
456 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
457 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
458 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000459 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000460 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000462 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000463 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000464
465#else /* do an exception instead */
466 errObj = DBIncompleteError;
467#endif
468 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000469#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000470
471 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
472 case DB_KEYEXIST: errObj = DBKeyExistError; break;
473 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
474 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
475 case DB_NOTFOUND: errObj = DBNotFoundError; break;
476 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
477 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
478 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
479 case DB_NOSERVER: errObj = DBNoServerError; break;
480 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
481 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
482#if (DBVER >= 33)
483 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
484 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
485#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000486 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000487
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000488#if (DBVER >= 43)
489 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
490 case ENOMEM: errObj = PyExc_MemoryError; break;
491#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000492 case EINVAL: errObj = DBInvalidArgError; break;
493 case EACCES: errObj = DBAccessError; break;
494 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000495 case EAGAIN: errObj = DBAgainError; break;
496 case EBUSY : errObj = DBBusyError; break;
497 case EEXIST: errObj = DBFileExistsError; break;
498 case ENOENT: errObj = DBNoSuchFileError; break;
499 case EPERM : errObj = DBPermissionsError; break;
500
501 default: errObj = DBError; break;
502 }
503
504 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000505 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
506 /* Ensure that bytes_left never goes negative */
507 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
508 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
509 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000510 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000511 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000513 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000514
515 errTuple = Py_BuildValue("(is)", err, errTxt);
516 PyErr_SetObject(errObj, errTuple);
517 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518 }
519
520 return ((errObj != NULL) || exceptionRaised);
521}
522
523
524
525/* set a type exception */
526static void makeTypeError(char* expected, PyObject* found)
527{
528 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis68192102007-07-21 06:55:02 +0000529 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530}
531
532
533/* verify that an obj is either None or a DBTxn, and set the txn pointer */
534static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
535{
536 if (txnobj == Py_None || txnobj == NULL) {
537 *txn = NULL;
538 return 1;
539 }
540 if (DBTxnObject_Check(txnobj)) {
541 *txn = ((DBTxnObject*)txnobj)->txn;
542 return 1;
543 }
544 else
545 makeTypeError("DBTxn", txnobj);
546 return 0;
547}
548
549
550/* Delete a key from a database
551 Returns 0 on success, -1 on an error. */
552static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
553{
554 int err;
555
556 MYDB_BEGIN_ALLOW_THREADS;
557 err = self->db->del(self->db, txn, key, 0);
558 MYDB_END_ALLOW_THREADS;
559 if (makeDBError(err)) {
560 return -1;
561 }
562 self->haveStat = 0;
563 return 0;
564}
565
566
567/* Store a key into a database
568 Returns 0 on success, -1 on an error. */
569static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
570{
571 int err;
572
573 MYDB_BEGIN_ALLOW_THREADS;
574 err = self->db->put(self->db, txn, key, data, flags);
575 MYDB_END_ALLOW_THREADS;
576 if (makeDBError(err)) {
577 return -1;
578 }
579 self->haveStat = 0;
580 return 0;
581}
582
583/* Get a key/data pair from a cursor */
584static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
585 PyObject *args, PyObject *kwargs, char *format)
586{
587 int err;
588 PyObject* retval = NULL;
589 DBT key, data;
590 int dlen = -1;
591 int doff = -1;
592 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000593 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000594
595 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
596 &flags, &dlen, &doff))
597 return NULL;
598
599 CHECK_CURSOR_NOT_CLOSED(self);
600
601 flags |= extra_flags;
602 CLEAR_DBT(key);
603 CLEAR_DBT(data);
604 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
605 /* Tell BerkeleyDB to malloc the return value (thread safe) */
606 data.flags = DB_DBT_MALLOC;
607 key.flags = DB_DBT_MALLOC;
608 }
609 if (!add_partial_dbt(&data, dlen, doff))
610 return NULL;
611
612 MYDB_BEGIN_ALLOW_THREADS;
613 err = self->dbc->c_get(self->dbc, &key, &data, flags);
614 MYDB_END_ALLOW_THREADS;
615
Gregory P. Smithe9477062005-06-04 06:46:59 +0000616 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
617 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000618 Py_INCREF(Py_None);
619 retval = Py_None;
620 }
621 else if (makeDBError(err)) {
622 retval = NULL;
623 }
624 else { /* otherwise, success! */
625
626 /* if Recno or Queue, return the key as an Int */
627 switch (_DB_get_type(self->mydb)) {
628 case -1:
629 retval = NULL;
630 break;
631
632 case DB_RECNO:
633 case DB_QUEUE:
634 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
635 data.data, data.size);
636 break;
637 case DB_HASH:
638 case DB_BTREE:
639 default:
640 retval = Py_BuildValue("s#s#", key.data, key.size,
641 data.data, data.size);
642 break;
643 }
644 }
645 if (!err) {
646 FREE_DBT(key);
647 FREE_DBT(data);
648 }
649 return retval;
650}
651
652
653/* add an integer to a dictionary using the given name as a key */
654static void _addIntToDict(PyObject* dict, char *name, int value)
655{
656 PyObject* v = PyInt_FromLong((long) value);
657 if (!v || PyDict_SetItemString(dict, name, v))
658 PyErr_Clear();
659
660 Py_XDECREF(v);
661}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000662
663/* The same, when the value is a time_t */
664static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
665{
666 PyObject* v;
667 /* if the value fits in regular int, use that. */
668#ifdef HAVE_LONG_LONG
669 if (sizeof(time_t) > sizeof(long))
670 v = PyLong_FromLongLong((PY_LONG_LONG) value);
671 else
672#endif
673 v = PyInt_FromLong((long) value);
674 if (!v || PyDict_SetItemString(dict, name, v))
675 PyErr_Clear();
676
677 Py_XDECREF(v);
678}
679
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000680#if (DBVER >= 43)
681/* add an db_seq_t to a dictionary using the given name as a key */
682static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
683{
684 PyObject* v = PyLong_FromLongLong(value);
685 if (!v || PyDict_SetItemString(dict, name, v))
686 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000687
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000688 Py_XDECREF(v);
689}
690#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691
692
693
694/* --------------------------------------------------------------------- */
695/* Allocators and deallocators */
696
697static DBObject*
698newDBObject(DBEnvObject* arg, int flags)
699{
700 DBObject* self;
701 DB_ENV* db_env = NULL;
702 int err;
703
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000704 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000705 if (self == NULL)
706 return NULL;
707
708 self->haveStat = 0;
709 self->flags = 0;
710 self->setflags = 0;
711 self->myenvobj = NULL;
712#if (DBVER >= 33)
713 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000714 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000715 self->primaryDBType = 0;
716#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000717 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000718
719 /* keep a reference to our python DBEnv object */
720 if (arg) {
721 Py_INCREF(arg);
722 self->myenvobj = arg;
723 db_env = arg->db_env;
724 }
725
726 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000727 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000728 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000729 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
730 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000731
732 MYDB_BEGIN_ALLOW_THREADS;
733 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000734 if (self->db != NULL) {
735 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000736#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000737 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000739 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000740 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000741 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
742 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000743 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000744 if (makeDBError(err)) {
745 if (self->myenvobj) {
746 Py_DECREF(self->myenvobj);
747 self->myenvobj = NULL;
748 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000749 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000750 self = NULL;
751 }
752 return self;
753}
754
755
756static void
757DB_dealloc(DBObject* self)
758{
759 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000760 /* avoid closing a DB when its DBEnv has been closed out from under
761 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000763 (self->myenvobj && self->myenvobj->db_env))
764 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765 MYDB_BEGIN_ALLOW_THREADS;
766 self->db->close(self->db, 0);
767 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000768 } else {
769 PyErr_Warn(PyExc_RuntimeWarning,
770 "DB could not be closed in destructor: DBEnv already closed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000771 }
772 self->db = NULL;
773 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000774 if (self->in_weakreflist != NULL) {
775 PyObject_ClearWeakRefs((PyObject *) self);
776 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000777 if (self->myenvobj) {
778 Py_DECREF(self->myenvobj);
779 self->myenvobj = NULL;
780 }
781#if (DBVER >= 33)
782 if (self->associateCallback != NULL) {
783 Py_DECREF(self->associateCallback);
784 self->associateCallback = NULL;
785 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000786 if (self->btCompareCallback != NULL) {
787 Py_DECREF(self->btCompareCallback);
788 self->btCompareCallback = NULL;
789 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000791 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792}
793
794
795static DBCursorObject*
796newDBCursorObject(DBC* dbc, DBObject* db)
797{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000798 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 if (self == NULL)
800 return NULL;
801
802 self->dbc = dbc;
803 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000804 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000805 Py_INCREF(self->mydb);
806 return self;
807}
808
809
810static void
811DBCursor_dealloc(DBCursorObject* self)
812{
813 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000814
Gregory P. Smitha703a212003-11-03 01:04:41 +0000815 if (self->in_weakreflist != NULL) {
816 PyObject_ClearWeakRefs((PyObject *) self);
817 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000818
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000819 if (self->dbc != NULL) {
820 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000821 /* If the underlying database has been closed, we don't
822 need to do anything. If the environment has been closed
823 we need to leak, as BerkeleyDB will crash trying to access
824 the environment. There was an exception when the
825 user closed the environment even though there still was
826 a database open. */
827 if (self->mydb->db && self->mydb->myenvobj &&
828 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000829 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830 self->dbc = NULL;
831 MYDB_END_ALLOW_THREADS;
832 }
833 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835}
836
837
838static DBEnvObject*
839newDBEnvObject(int flags)
840{
841 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000842 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 if (self == NULL)
844 return NULL;
845
846 self->closed = 1;
847 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000848 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
849 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000850 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851
852 MYDB_BEGIN_ALLOW_THREADS;
853 err = db_env_create(&self->db_env, flags);
854 MYDB_END_ALLOW_THREADS;
855 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000856 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 self = NULL;
858 }
859 else {
860 self->db_env->set_errcall(self->db_env, _db_errorCallback);
861 }
862 return self;
863}
864
865
866static void
867DBEnv_dealloc(DBEnvObject* self)
868{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000869 if (self->in_weakreflist != NULL) {
870 PyObject_ClearWeakRefs((PyObject *) self);
871 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000872
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000873 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000874 MYDB_BEGIN_ALLOW_THREADS;
875 self->db_env->close(self->db_env, 0);
876 MYDB_END_ALLOW_THREADS;
877 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879}
880
881
882static DBTxnObject*
883newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
884{
885 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000886 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000887 if (self == NULL)
888 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000889 Py_INCREF(myenv);
890 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000891 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892
893 MYDB_BEGIN_ALLOW_THREADS;
894#if (DBVER >= 40)
895 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
896#else
897 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
898#endif
899 MYDB_END_ALLOW_THREADS;
900 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000901 Py_DECREF(self->env);
902 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 self = NULL;
904 }
905 return self;
906}
907
908
909static void
910DBTxn_dealloc(DBTxnObject* self)
911{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000912 if (self->in_weakreflist != NULL) {
913 PyObject_ClearWeakRefs((PyObject *) self);
914 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915
Gregory P. Smith31c50652004-06-28 01:20:40 +0000916 if (self->txn) {
917 /* it hasn't been finalized, abort it! */
918 MYDB_BEGIN_ALLOW_THREADS;
919#if (DBVER >= 40)
920 self->txn->abort(self->txn);
921#else
922 txn_abort(self->txn);
923#endif
924 MYDB_END_ALLOW_THREADS;
925 PyErr_Warn(PyExc_RuntimeWarning,
926 "DBTxn aborted in destructor. No prior commit() or abort().");
927 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928
Neal Norwitz62a21122006-01-25 05:21:55 +0000929 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931}
932
933
934static DBLockObject*
935newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
936 db_lockmode_t lock_mode, int flags)
937{
938 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000939 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000940 if (self == NULL)
941 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000942 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943
944 MYDB_BEGIN_ALLOW_THREADS;
945#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000946 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
947 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948#else
949 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
950#endif
951 MYDB_END_ALLOW_THREADS;
952 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000953 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954 self = NULL;
955 }
956
957 return self;
958}
959
960
961static void
962DBLock_dealloc(DBLockObject* self)
963{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000964 if (self->in_weakreflist != NULL) {
965 PyObject_ClearWeakRefs((PyObject *) self);
966 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000967 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970}
971
972
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000973#if (DBVER >= 43)
974static DBSequenceObject*
975newDBSequenceObject(DBObject* mydb, int flags)
976{
977 int err;
978 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
979 if (self == NULL)
980 return NULL;
981 Py_INCREF(mydb);
982 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000983 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000984
985
986 MYDB_BEGIN_ALLOW_THREADS;
987 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
988 MYDB_END_ALLOW_THREADS;
989 if (makeDBError(err)) {
990 Py_DECREF(self->mydb);
991 PyObject_Del(self);
992 self = NULL;
993 }
994
995 return self;
996}
997
998
999static void
1000DBSequence_dealloc(DBSequenceObject* self)
1001{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001002 if (self->in_weakreflist != NULL) {
1003 PyObject_ClearWeakRefs((PyObject *) self);
1004 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001005
1006 Py_DECREF(self->mydb);
1007 PyObject_Del(self);
1008}
1009#endif
1010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011/* --------------------------------------------------------------------- */
1012/* DB methods */
1013
1014static PyObject*
1015DB_append(DBObject* self, PyObject* args)
1016{
1017 PyObject* txnobj = NULL;
1018 PyObject* dataobj;
1019 db_recno_t recno;
1020 DBT key, data;
1021 DB_TXN *txn = NULL;
1022
Georg Brandl96a8c392006-05-29 21:04:52 +00001023 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024 return NULL;
1025
1026 CHECK_DB_NOT_CLOSED(self);
1027
1028 /* make a dummy key out of a recno */
1029 recno = 0;
1030 CLEAR_DBT(key);
1031 key.data = &recno;
1032 key.size = sizeof(recno);
1033 key.ulen = key.size;
1034 key.flags = DB_DBT_USERMEM;
1035
1036 if (!make_dbt(dataobj, &data)) return NULL;
1037 if (!checkTxnObj(txnobj, &txn)) return NULL;
1038
1039 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1040 return NULL;
1041
1042 return PyInt_FromLong(recno);
1043}
1044
1045
1046#if (DBVER >= 33)
1047
1048static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001049_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1050 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001051{
1052 int retval = DB_DONOTINDEX;
1053 DBObject* secondaryDB = (DBObject*)db->app_private;
1054 PyObject* callback = secondaryDB->associateCallback;
1055 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001057 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058
1059
1060 if (callback != NULL) {
1061 MYDB_BEGIN_BLOCK_THREADS;
1062
Thomas Woutersb3153832006-03-08 01:47:19 +00001063 if (type == DB_RECNO || type == DB_QUEUE)
1064 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1065 priData->data, priData->size);
1066 else
1067 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1068 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001069 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001070 result = PyEval_CallObject(callback, args);
1071 }
1072 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001073 PyErr_Print();
1074 }
1075 else if (result == Py_None) {
1076 retval = DB_DONOTINDEX;
1077 }
1078 else if (PyInt_Check(result)) {
1079 retval = PyInt_AsLong(result);
1080 }
1081 else if (PyString_Check(result)) {
1082 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001083 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001084
1085 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001087 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1088 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001089 if (secKey->data) {
1090 memcpy(secKey->data, data, size);
1091 secKey->size = size;
1092 retval = 0;
1093 }
1094 else {
1095 PyErr_SetString(PyExc_MemoryError,
1096 "malloc failed in _db_associateCallback");
1097 PyErr_Print();
1098 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001099 }
1100 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001101 PyErr_SetString(
1102 PyExc_TypeError,
1103 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001104 PyErr_Print();
1105 }
1106
Thomas Woutersb3153832006-03-08 01:47:19 +00001107 Py_XDECREF(args);
1108 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001109
1110 MYDB_END_BLOCK_THREADS;
1111 }
1112 return retval;
1113}
1114
1115
1116static PyObject*
1117DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1118{
1119 int err, flags=0;
1120 DBObject* secondaryDB;
1121 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001122#if (DBVER >= 41)
1123 PyObject *txnobj = NULL;
1124 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001125 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001126 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001127#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001128 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001129#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001131#if (DBVER >= 41)
1132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1133 &secondaryDB, &callback, &flags,
1134 &txnobj)) {
1135#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001137 &secondaryDB, &callback, &flags)) {
1138#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001139 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001140 }
1141
1142#if (DBVER >= 41)
1143 if (!checkTxnObj(txnobj, &txn)) return NULL;
1144#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001145
1146 CHECK_DB_NOT_CLOSED(self);
1147 if (!DBObject_Check(secondaryDB)) {
1148 makeTypeError("DB", (PyObject*)secondaryDB);
1149 return NULL;
1150 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001151 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152 if (callback == Py_None) {
1153 callback = NULL;
1154 }
1155 else if (!PyCallable_Check(callback)) {
1156 makeTypeError("Callable", callback);
1157 return NULL;
1158 }
1159
1160 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001161 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001162 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163 secondaryDB->associateCallback = callback;
1164 secondaryDB->primaryDBType = _DB_get_type(self);
1165
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001166 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1167 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1168 * The global interepreter lock is not initialized until the first
1169 * thread is created using thread.start_new_thread() or fork() is
1170 * called. that would cause the ALLOW_THREADS here to segfault due
1171 * to a null pointer reference if no threads or child processes
1172 * have been created. This works around that and is a no-op if
1173 * threads have already been initialized.
1174 * (see pybsddb-users mailing list post on 2002-08-07)
1175 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001176#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001177 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001178#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001179 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001180#if (DBVER >= 41)
1181 err = self->db->associate(self->db,
1182 txn,
1183 secondaryDB->db,
1184 _db_associateCallback,
1185 flags);
1186#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001187 err = self->db->associate(self->db,
1188 secondaryDB->db,
1189 _db_associateCallback,
1190 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001191#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001192 MYDB_END_ALLOW_THREADS;
1193
1194 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001195 Py_XDECREF(secondaryDB->associateCallback);
1196 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001197 secondaryDB->primaryDBType = 0;
1198 }
1199
1200 RETURN_IF_ERR();
1201 RETURN_NONE();
1202}
1203
1204
1205#endif
1206
1207
1208static PyObject*
1209DB_close(DBObject* self, PyObject* args)
1210{
1211 int err, flags=0;
1212 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1213 return NULL;
1214 if (self->db != NULL) {
1215 if (self->myenvobj)
1216 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001217 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001218 self->db = NULL;
1219 RETURN_IF_ERR();
1220 }
1221 RETURN_NONE();
1222}
1223
1224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225static PyObject*
1226_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1227{
1228 int err, flags=0, type;
1229 PyObject* txnobj = NULL;
1230 PyObject* retval = NULL;
1231 DBT key, data;
1232 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001233 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001234
1235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1236 &txnobj, &flags))
1237 return NULL;
1238
1239 CHECK_DB_NOT_CLOSED(self);
1240 type = _DB_get_type(self);
1241 if (type == -1)
1242 return NULL;
1243 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001244 PyErr_SetString(PyExc_TypeError,
1245 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001246 return NULL;
1247 }
1248 if (!checkTxnObj(txnobj, &txn))
1249 return NULL;
1250
1251 CLEAR_DBT(key);
1252 CLEAR_DBT(data);
1253 if (CHECK_DBFLAG(self, DB_THREAD)) {
1254 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1255 data.flags = DB_DBT_MALLOC;
1256 key.flags = DB_DBT_MALLOC;
1257 }
1258
1259 MYDB_BEGIN_ALLOW_THREADS;
1260 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1261 MYDB_END_ALLOW_THREADS;
1262
Gregory P. Smithe9477062005-06-04 06:46:59 +00001263 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1264 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265 err = 0;
1266 Py_INCREF(Py_None);
1267 retval = Py_None;
1268 }
1269 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001270 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1271 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 FREE_DBT(key);
1273 FREE_DBT(data);
1274 }
1275
1276 RETURN_IF_ERR();
1277 return retval;
1278}
1279
1280static PyObject*
1281DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1282{
1283 return _DB_consume(self, args, kwargs, DB_CONSUME);
1284}
1285
1286static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001287DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1288 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289{
1290 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1291}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001292
1293
1294static PyObject*
1295DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1296{
1297 int err, flags=0;
1298 DBC* dbc;
1299 PyObject* txnobj = NULL;
1300 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001301 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001302
1303 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1304 &txnobj, &flags))
1305 return NULL;
1306 CHECK_DB_NOT_CLOSED(self);
1307 if (!checkTxnObj(txnobj, &txn))
1308 return NULL;
1309
1310 MYDB_BEGIN_ALLOW_THREADS;
1311 err = self->db->cursor(self->db, txn, &dbc, flags);
1312 MYDB_END_ALLOW_THREADS;
1313 RETURN_IF_ERR();
1314 return (PyObject*) newDBCursorObject(dbc, self);
1315}
1316
1317
1318static PyObject*
1319DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1320{
1321 PyObject* txnobj = NULL;
1322 int flags = 0;
1323 PyObject* keyobj;
1324 DBT key;
1325 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001326 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001327
1328 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1329 &keyobj, &txnobj, &flags))
1330 return NULL;
1331 CHECK_DB_NOT_CLOSED(self);
1332 if (!make_key_dbt(self, keyobj, &key, NULL))
1333 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001334 if (!checkTxnObj(txnobj, &txn)) {
1335 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001336 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001337 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001339 if (-1 == _DB_delete(self, txn, &key, 0)) {
1340 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001342 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343
1344 FREE_DBT(key);
1345 RETURN_NONE();
1346}
1347
1348
1349static PyObject*
1350DB_fd(DBObject* self, PyObject* args)
1351{
1352 int err, the_fd;
1353
1354 if (!PyArg_ParseTuple(args,":fd"))
1355 return NULL;
1356 CHECK_DB_NOT_CLOSED(self);
1357
1358 MYDB_BEGIN_ALLOW_THREADS;
1359 err = self->db->fd(self->db, &the_fd);
1360 MYDB_END_ALLOW_THREADS;
1361 RETURN_IF_ERR();
1362 return PyInt_FromLong(the_fd);
1363}
1364
1365
1366static PyObject*
1367DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1368{
1369 int err, flags=0;
1370 PyObject* txnobj = NULL;
1371 PyObject* keyobj;
1372 PyObject* dfltobj = NULL;
1373 PyObject* retval = NULL;
1374 int dlen = -1;
1375 int doff = -1;
1376 DBT key, data;
1377 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001378 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001379 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001380
1381 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001382 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1383 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001384 return NULL;
1385
1386 CHECK_DB_NOT_CLOSED(self);
1387 if (!make_key_dbt(self, keyobj, &key, &flags))
1388 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001389 if (!checkTxnObj(txnobj, &txn)) {
1390 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001392 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393
1394 CLEAR_DBT(data);
1395 if (CHECK_DBFLAG(self, DB_THREAD)) {
1396 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1397 data.flags = DB_DBT_MALLOC;
1398 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001399 if (!add_partial_dbt(&data, dlen, doff)) {
1400 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001401 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001402 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403
1404 MYDB_BEGIN_ALLOW_THREADS;
1405 err = self->db->get(self->db, txn, &key, &data, flags);
1406 MYDB_END_ALLOW_THREADS;
1407
Gregory P. Smithe9477062005-06-04 06:46:59 +00001408 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001409 err = 0;
1410 Py_INCREF(dfltobj);
1411 retval = dfltobj;
1412 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001413 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1414 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001415 err = 0;
1416 Py_INCREF(Py_None);
1417 retval = Py_None;
1418 }
1419 else if (!err) {
1420 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001421 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1422 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423 else /* return just the data */
1424 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425 FREE_DBT(data);
1426 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001427 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428
1429 RETURN_IF_ERR();
1430 return retval;
1431}
1432
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001433#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001434static PyObject*
1435DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1436{
1437 int err, flags=0;
1438 PyObject* txnobj = NULL;
1439 PyObject* keyobj;
1440 PyObject* dfltobj = NULL;
1441 PyObject* retval = NULL;
1442 int dlen = -1;
1443 int doff = -1;
1444 DBT key, pkey, data;
1445 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001446 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001447 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001448
1449 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1450 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1451 &doff))
1452 return NULL;
1453
1454 CHECK_DB_NOT_CLOSED(self);
1455 if (!make_key_dbt(self, keyobj, &key, &flags))
1456 return NULL;
1457 if (!checkTxnObj(txnobj, &txn)) {
1458 FREE_DBT(key);
1459 return NULL;
1460 }
1461
1462 CLEAR_DBT(data);
1463 if (CHECK_DBFLAG(self, DB_THREAD)) {
1464 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1465 data.flags = DB_DBT_MALLOC;
1466 }
1467 if (!add_partial_dbt(&data, dlen, doff)) {
1468 FREE_DBT(key);
1469 return NULL;
1470 }
1471
1472 CLEAR_DBT(pkey);
1473 pkey.flags = DB_DBT_MALLOC;
1474
1475 MYDB_BEGIN_ALLOW_THREADS;
1476 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1477 MYDB_END_ALLOW_THREADS;
1478
Gregory P. Smithe9477062005-06-04 06:46:59 +00001479 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001480 err = 0;
1481 Py_INCREF(dfltobj);
1482 retval = dfltobj;
1483 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001484 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1485 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001486 err = 0;
1487 Py_INCREF(Py_None);
1488 retval = Py_None;
1489 }
1490 else if (!err) {
1491 PyObject *pkeyObj;
1492 PyObject *dataObj;
1493 dataObj = PyString_FromStringAndSize(data.data, data.size);
1494
1495 if (self->primaryDBType == DB_RECNO ||
1496 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001497 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001498 else
1499 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1500
1501 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1502 {
1503 PyObject *keyObj;
1504 int type = _DB_get_type(self);
1505 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001506 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001507 else
1508 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001509#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001510 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001511#else
1512 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1513#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001514 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001515 }
1516 else /* return just the pkey and data */
1517 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001518#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001519 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001520#else
1521 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1522#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001523 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001524 Py_DECREF(dataObj);
1525 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001526 FREE_DBT(pkey);
1527 FREE_DBT(data);
1528 }
1529 FREE_DBT(key);
1530
1531 RETURN_IF_ERR();
1532 return retval;
1533}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001534#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001535
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536
1537/* Return size of entry */
1538static PyObject*
1539DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1540{
1541 int err, flags=0;
1542 PyObject* txnobj = NULL;
1543 PyObject* keyobj;
1544 PyObject* retval = NULL;
1545 DBT key, data;
1546 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001547 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001548
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1550 &keyobj, &txnobj))
1551 return NULL;
1552 CHECK_DB_NOT_CLOSED(self);
1553 if (!make_key_dbt(self, keyobj, &key, &flags))
1554 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001555 if (!checkTxnObj(txnobj, &txn)) {
1556 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001557 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001558 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001559 CLEAR_DBT(data);
1560
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001561 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1562 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001563 data.flags = DB_DBT_USERMEM;
1564 data.ulen = 0;
1565 MYDB_BEGIN_ALLOW_THREADS;
1566 err = self->db->get(self->db, txn, &key, &data, flags);
1567 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001568 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001569 retval = PyInt_FromLong((long)data.size);
1570 err = 0;
1571 }
1572
1573 FREE_DBT(key);
1574 FREE_DBT(data);
1575 RETURN_IF_ERR();
1576 return retval;
1577}
1578
1579
1580static PyObject*
1581DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1582{
1583 int err, flags=0;
1584 PyObject* txnobj = NULL;
1585 PyObject* keyobj;
1586 PyObject* dataobj;
1587 PyObject* retval = NULL;
1588 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001589 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001590 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001591 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001592
1593
1594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1595 &keyobj, &dataobj, &txnobj, &flags))
1596 return NULL;
1597
1598 CHECK_DB_NOT_CLOSED(self);
1599 if (!make_key_dbt(self, keyobj, &key, NULL))
1600 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001601 if ( !make_dbt(dataobj, &data) ||
1602 !checkTxnObj(txnobj, &txn) )
1603 {
1604 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001605 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001606 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001607
1608 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001609 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001610
1611 if (CHECK_DBFLAG(self, DB_THREAD)) {
1612 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001613 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001614 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001615 }
1616
1617 MYDB_BEGIN_ALLOW_THREADS;
1618 err = self->db->get(self->db, txn, &key, &data, flags);
1619 MYDB_END_ALLOW_THREADS;
1620
Gregory P. Smithe9477062005-06-04 06:46:59 +00001621 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1622 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001623 err = 0;
1624 Py_INCREF(Py_None);
1625 retval = Py_None;
1626 }
1627 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001628 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001629 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001630
1631 /* Even though the flags require DB_DBT_MALLOC, data is not always
1632 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1633 if (data.data != orig_data)
1634 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001635 }
1636
1637 FREE_DBT(key);
1638 RETURN_IF_ERR();
1639 return retval;
1640}
1641
1642
1643static PyObject*
1644DB_get_byteswapped(DBObject* self, PyObject* args)
1645{
1646#if (DBVER >= 33)
1647 int err = 0;
1648#endif
1649 int retval = -1;
1650
1651 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1652 return NULL;
1653 CHECK_DB_NOT_CLOSED(self);
1654
1655#if (DBVER >= 33)
1656 MYDB_BEGIN_ALLOW_THREADS;
1657 err = self->db->get_byteswapped(self->db, &retval);
1658 MYDB_END_ALLOW_THREADS;
1659 RETURN_IF_ERR();
1660#else
1661 MYDB_BEGIN_ALLOW_THREADS;
1662 retval = self->db->get_byteswapped(self->db);
1663 MYDB_END_ALLOW_THREADS;
1664#endif
1665 return PyInt_FromLong(retval);
1666}
1667
1668
1669static PyObject*
1670DB_get_type(DBObject* self, PyObject* args)
1671{
1672 int type;
1673
1674 if (!PyArg_ParseTuple(args,":get_type"))
1675 return NULL;
1676 CHECK_DB_NOT_CLOSED(self);
1677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001679 if (type == -1)
1680 return NULL;
1681 return PyInt_FromLong(type);
1682}
1683
1684
1685static PyObject*
1686DB_join(DBObject* self, PyObject* args)
1687{
1688 int err, flags=0;
1689 int length, x;
1690 PyObject* cursorsObj;
1691 DBC** cursors;
1692 DBC* dbc;
1693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001694 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1695 return NULL;
1696
1697 CHECK_DB_NOT_CLOSED(self);
1698
1699 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001700 PyErr_SetString(PyExc_TypeError,
1701 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001702 return NULL;
1703 }
1704
1705 length = PyObject_Length(cursorsObj);
1706 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001707 if (!cursors) {
1708 PyErr_NoMemory();
1709 return NULL;
1710 }
1711
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001712 cursors[length] = NULL;
1713 for (x=0; x<length; x++) {
1714 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001715 if (item == NULL) {
1716 free(cursors);
1717 return NULL;
1718 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001720 PyErr_SetString(PyExc_TypeError,
1721 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001722 free(cursors);
1723 return NULL;
1724 }
1725 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001726 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 }
1728
1729 MYDB_BEGIN_ALLOW_THREADS;
1730 err = self->db->join(self->db, cursors, &dbc, flags);
1731 MYDB_END_ALLOW_THREADS;
1732 free(cursors);
1733 RETURN_IF_ERR();
1734
Gregory P. Smith7441e652003-11-03 21:35:31 +00001735 /* FIXME: this is a buggy interface. The returned cursor
1736 contains internal references to the passed in cursors
1737 but does not hold python references to them or prevent
1738 them from being closed prematurely. This can cause
1739 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001740 return (PyObject*) newDBCursorObject(dbc, self);
1741}
1742
1743
1744static PyObject*
1745DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1746{
1747 int err, flags=0;
1748 PyObject* txnobj = NULL;
1749 PyObject* keyobj;
1750 DBT key;
1751 DB_TXN *txn = NULL;
1752 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001753 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001754
1755 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1756 &keyobj, &txnobj, &flags))
1757 return NULL;
1758 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001759 if (!make_dbt(keyobj, &key))
1760 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001761 return NULL;
1762 if (!checkTxnObj(txnobj, &txn))
1763 return NULL;
1764
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 err = self->db->key_range(self->db, txn, &key, &range, flags);
1767 MYDB_END_ALLOW_THREADS;
1768
1769 RETURN_IF_ERR();
1770 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1771}
1772
1773
1774static PyObject*
1775DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1776{
1777 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1778 char* filename = NULL;
1779 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001780#if (DBVER >= 41)
1781 PyObject *txnobj = NULL;
1782 DB_TXN *txn = NULL;
1783 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001784 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001785 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1786 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001787 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001788 "filename", "dbtype", "flags", "mode", "txn", NULL};
1789#else
1790 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001791 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001792 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1793 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001794 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001795 "filename", "dbtype", "flags", "mode", NULL};
1796#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001797
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001798#if (DBVER >= 41)
1799 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1800 &filename, &dbname, &type, &flags, &mode,
1801 &txnobj))
1802#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001803 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001804 &filename, &dbname, &type, &flags,
1805 &mode))
1806#endif
1807 {
1808 PyErr_Clear();
1809 type = DB_UNKNOWN; flags = 0; mode = 0660;
1810 filename = NULL; dbname = NULL;
1811#if (DBVER >= 41)
1812 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1813 kwnames_basic,
1814 &filename, &type, &flags, &mode,
1815 &txnobj))
1816 return NULL;
1817#else
1818 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1819 kwnames_basic,
1820 &filename, &type, &flags, &mode))
1821 return NULL;
1822#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 }
1824
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001825#if (DBVER >= 41)
1826 if (!checkTxnObj(txnobj, &txn)) return NULL;
1827#endif
1828
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001830 PyObject *t = Py_BuildValue("(is)", 0,
1831 "Cannot call open() twice for DB object");
1832 PyErr_SetObject(DBError, t);
1833 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 return NULL;
1835 }
1836
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001837#if 0 && (DBVER >= 41)
1838 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1839 && (self->myenvobj->flags & DB_INIT_TXN))
1840 {
1841 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1842 * explicitly passed) but we are in a transaction ready environment:
1843 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1844 * to work on BerkeleyDB 4.1 without needing to modify their
1845 * DBEnv or DB open calls.
1846 * TODO make this behaviour of the library configurable.
1847 */
1848 flags |= DB_AUTO_COMMIT;
1849 }
1850#endif
1851
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001853#if (DBVER >= 41)
1854 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1855#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001857#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858 MYDB_END_ALLOW_THREADS;
1859 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001860 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 self->db = NULL;
1862 return NULL;
1863 }
1864
1865 self->flags = flags;
1866 RETURN_NONE();
1867}
1868
1869
1870static PyObject*
1871DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1872{
1873 int flags=0;
1874 PyObject* txnobj = NULL;
1875 int dlen = -1;
1876 int doff = -1;
1877 PyObject* keyobj, *dataobj, *retval;
1878 DBT key, data;
1879 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001880 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001881 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001882
1883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1884 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1885 return NULL;
1886
1887 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001888 if (!make_key_dbt(self, keyobj, &key, NULL))
1889 return NULL;
1890 if ( !make_dbt(dataobj, &data) ||
1891 !add_partial_dbt(&data, dlen, doff) ||
1892 !checkTxnObj(txnobj, &txn) )
1893 {
1894 FREE_DBT(key);
1895 return NULL;
1896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001897
1898 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1899 FREE_DBT(key);
1900 return NULL;
1901 }
1902
1903 if (flags & DB_APPEND)
1904 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1905 else {
1906 retval = Py_None;
1907 Py_INCREF(retval);
1908 }
1909 FREE_DBT(key);
1910 return retval;
1911}
1912
1913
1914
1915static PyObject*
1916DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1917{
1918 char* filename;
1919 char* database = NULL;
1920 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001921 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001922
1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1924 &filename, &database, &flags))
1925 return NULL;
1926 CHECK_DB_NOT_CLOSED(self);
1927
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001929 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 RETURN_IF_ERR();
1931 RETURN_NONE();
1932}
1933
1934
1935
1936static PyObject*
1937DB_rename(DBObject* self, PyObject* args)
1938{
1939 char* filename;
1940 char* database;
1941 char* newname;
1942 int err, flags=0;
1943
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001944 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1945 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1948
1949 MYDB_BEGIN_ALLOW_THREADS;
1950 err = self->db->rename(self->db, filename, database, newname, flags);
1951 MYDB_END_ALLOW_THREADS;
1952 RETURN_IF_ERR();
1953 RETURN_NONE();
1954}
1955
1956
1957static PyObject*
1958DB_set_bt_minkey(DBObject* self, PyObject* args)
1959{
1960 int err, minkey;
1961
1962 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1963 return NULL;
1964 CHECK_DB_NOT_CLOSED(self);
1965
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->set_bt_minkey(self->db, minkey);
1968 MYDB_END_ALLOW_THREADS;
1969 RETURN_IF_ERR();
1970 RETURN_NONE();
1971}
1972
Neal Norwitz84562352005-10-20 04:30:15 +00001973#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001974static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001975_default_cmp(const DBT *leftKey,
1976 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001977{
1978 int res;
1979 int lsize = leftKey->size, rsize = rightKey->size;
1980
Georg Brandlef1701f2006-03-07 14:57:48 +00001981 res = memcmp(leftKey->data, rightKey->data,
1982 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001983
1984 if (res == 0) {
1985 if (lsize < rsize) {
1986 res = -1;
1987 }
1988 else if (lsize > rsize) {
1989 res = 1;
1990 }
1991 }
1992 return res;
1993}
1994
1995static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001996_db_compareCallback(DB* db,
1997 const DBT *leftKey,
1998 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001999{
2000 int res = 0;
2001 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002002 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002003 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002004
2005 if (self == NULL || self->btCompareCallback == NULL) {
2006 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002007 PyErr_SetString(PyExc_TypeError,
2008 (self == 0
2009 ? "DB_bt_compare db is NULL."
2010 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002011 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002012 PyErr_Print();
2013 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002014 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002015 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002016 MYDB_BEGIN_BLOCK_THREADS;
2017
Thomas Woutersb3153832006-03-08 01:47:19 +00002018 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2019 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002020 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002021 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002022 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002023 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002024 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002025 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002026 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002027 PyErr_Print();
2028 res = _default_cmp(leftKey, rightKey);
2029 } else if (PyInt_Check(result)) {
2030 res = PyInt_AsLong(result);
2031 } else {
2032 PyErr_SetString(PyExc_TypeError,
2033 "DB_bt_compare callback MUST return an int.");
2034 /* we're in a callback within the DB code, we can't raise */
2035 PyErr_Print();
2036 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002037 }
2038
Thomas Woutersb3153832006-03-08 01:47:19 +00002039 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002040 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002041
2042 MYDB_END_BLOCK_THREADS;
2043 }
2044 return res;
2045}
2046
2047static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002048DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002049{
2050 int err;
2051 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002052 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002053
Georg Brandlef1701f2006-03-07 14:57:48 +00002054 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002055 return NULL;
2056
Georg Brandlef1701f2006-03-07 14:57:48 +00002057 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002058
Georg Brandlef1701f2006-03-07 14:57:48 +00002059 if (!PyCallable_Check(comparator)) {
2060 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002061 return NULL;
2062 }
2063
2064 /*
2065 * Perform a test call of the comparator function with two empty
2066 * string objects here. verify that it returns an int (0).
2067 * err if not.
2068 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002069 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002070 result = PyEval_CallObject(comparator, tuple);
2071 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002072 if (result == NULL)
2073 return NULL;
2074 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002075 PyErr_SetString(PyExc_TypeError,
2076 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002078 } else if (PyInt_AsLong(result) != 0) {
2079 PyErr_SetString(PyExc_TypeError,
2080 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081 return NULL;
2082 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002083 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002084
2085 /* We don't accept multiple set_bt_compare operations, in order to
2086 * simplify the code. This would have no real use, as one cannot
2087 * change the function once the db is opened anyway */
2088 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002089 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002090 return NULL;
2091 }
2092
Georg Brandlef1701f2006-03-07 14:57:48 +00002093 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002094 self->btCompareCallback = comparator;
2095
2096 /* This is to workaround a problem with un-initialized threads (see
2097 comment in DB_associate) */
2098#ifdef WITH_THREAD
2099 PyEval_InitThreads();
2100#endif
2101
Thomas Woutersb3153832006-03-08 01:47:19 +00002102 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103
2104 if (err) {
2105 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002106 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107 self->btCompareCallback = NULL;
2108 }
2109
Georg Brandlef1701f2006-03-07 14:57:48 +00002110 RETURN_IF_ERR();
2111 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002112}
Neal Norwitz84562352005-10-20 04:30:15 +00002113#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002115
2116static PyObject*
2117DB_set_cachesize(DBObject* self, PyObject* args)
2118{
2119 int err;
2120 int gbytes = 0, bytes = 0, ncache = 0;
2121
2122 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2123 &gbytes,&bytes,&ncache))
2124 return NULL;
2125 CHECK_DB_NOT_CLOSED(self);
2126
2127 MYDB_BEGIN_ALLOW_THREADS;
2128 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2129 MYDB_END_ALLOW_THREADS;
2130 RETURN_IF_ERR();
2131 RETURN_NONE();
2132}
2133
2134
2135static PyObject*
2136DB_set_flags(DBObject* self, PyObject* args)
2137{
2138 int err, flags;
2139
2140 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2141 return NULL;
2142 CHECK_DB_NOT_CLOSED(self);
2143
2144 MYDB_BEGIN_ALLOW_THREADS;
2145 err = self->db->set_flags(self->db, flags);
2146 MYDB_END_ALLOW_THREADS;
2147 RETURN_IF_ERR();
2148
2149 self->setflags |= flags;
2150 RETURN_NONE();
2151}
2152
2153
2154static PyObject*
2155DB_set_h_ffactor(DBObject* self, PyObject* args)
2156{
2157 int err, ffactor;
2158
2159 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2160 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2162
2163 MYDB_BEGIN_ALLOW_THREADS;
2164 err = self->db->set_h_ffactor(self->db, ffactor);
2165 MYDB_END_ALLOW_THREADS;
2166 RETURN_IF_ERR();
2167 RETURN_NONE();
2168}
2169
2170
2171static PyObject*
2172DB_set_h_nelem(DBObject* self, PyObject* args)
2173{
2174 int err, nelem;
2175
2176 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2177 return NULL;
2178 CHECK_DB_NOT_CLOSED(self);
2179
2180 MYDB_BEGIN_ALLOW_THREADS;
2181 err = self->db->set_h_nelem(self->db, nelem);
2182 MYDB_END_ALLOW_THREADS;
2183 RETURN_IF_ERR();
2184 RETURN_NONE();
2185}
2186
2187
2188static PyObject*
2189DB_set_lorder(DBObject* self, PyObject* args)
2190{
2191 int err, lorder;
2192
2193 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2194 return NULL;
2195 CHECK_DB_NOT_CLOSED(self);
2196
2197 MYDB_BEGIN_ALLOW_THREADS;
2198 err = self->db->set_lorder(self->db, lorder);
2199 MYDB_END_ALLOW_THREADS;
2200 RETURN_IF_ERR();
2201 RETURN_NONE();
2202}
2203
2204
2205static PyObject*
2206DB_set_pagesize(DBObject* self, PyObject* args)
2207{
2208 int err, pagesize;
2209
2210 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2211 return NULL;
2212 CHECK_DB_NOT_CLOSED(self);
2213
2214 MYDB_BEGIN_ALLOW_THREADS;
2215 err = self->db->set_pagesize(self->db, pagesize);
2216 MYDB_END_ALLOW_THREADS;
2217 RETURN_IF_ERR();
2218 RETURN_NONE();
2219}
2220
2221
2222static PyObject*
2223DB_set_re_delim(DBObject* self, PyObject* args)
2224{
2225 int err;
2226 char delim;
2227
2228 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2229 PyErr_Clear();
2230 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2231 return NULL;
2232 }
2233
2234 CHECK_DB_NOT_CLOSED(self);
2235
2236 MYDB_BEGIN_ALLOW_THREADS;
2237 err = self->db->set_re_delim(self->db, delim);
2238 MYDB_END_ALLOW_THREADS;
2239 RETURN_IF_ERR();
2240 RETURN_NONE();
2241}
2242
2243static PyObject*
2244DB_set_re_len(DBObject* self, PyObject* args)
2245{
2246 int err, len;
2247
2248 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2249 return NULL;
2250 CHECK_DB_NOT_CLOSED(self);
2251
2252 MYDB_BEGIN_ALLOW_THREADS;
2253 err = self->db->set_re_len(self->db, len);
2254 MYDB_END_ALLOW_THREADS;
2255 RETURN_IF_ERR();
2256 RETURN_NONE();
2257}
2258
2259
2260static PyObject*
2261DB_set_re_pad(DBObject* self, PyObject* args)
2262{
2263 int err;
2264 char pad;
2265
2266 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2267 PyErr_Clear();
2268 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2269 return NULL;
2270 }
2271 CHECK_DB_NOT_CLOSED(self);
2272
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_re_pad(self->db, pad);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2278}
2279
2280
2281static PyObject*
2282DB_set_re_source(DBObject* self, PyObject* args)
2283{
2284 int err;
2285 char *re_source;
2286
2287 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2288 return NULL;
2289 CHECK_DB_NOT_CLOSED(self);
2290
2291 MYDB_BEGIN_ALLOW_THREADS;
2292 err = self->db->set_re_source(self->db, re_source);
2293 MYDB_END_ALLOW_THREADS;
2294 RETURN_IF_ERR();
2295 RETURN_NONE();
2296}
2297
2298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002299static PyObject*
2300DB_set_q_extentsize(DBObject* self, PyObject* args)
2301{
2302 int err;
2303 int extentsize;
2304
2305 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2306 return NULL;
2307 CHECK_DB_NOT_CLOSED(self);
2308
2309 MYDB_BEGIN_ALLOW_THREADS;
2310 err = self->db->set_q_extentsize(self->db, extentsize);
2311 MYDB_END_ALLOW_THREADS;
2312 RETURN_IF_ERR();
2313 RETURN_NONE();
2314}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002315
2316static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002317DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002318{
2319 int err, flags = 0, type;
2320 void* sp;
2321 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002322#if (DBVER >= 43)
2323 PyObject* txnobj = NULL;
2324 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002325 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002326#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002327 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002328#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002329
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002330#if (DBVER >= 43)
2331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2332 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002333 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002334 if (!checkTxnObj(txnobj, &txn))
2335 return NULL;
2336#else
2337 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2338 return NULL;
2339#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002340 CHECK_DB_NOT_CLOSED(self);
2341
2342 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002343#if (DBVER >= 43)
2344 err = self->db->stat(self->db, txn, &sp, flags);
2345#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002346 err = self->db->stat(self->db, &sp, flags);
2347#else
2348 err = self->db->stat(self->db, &sp, NULL, flags);
2349#endif
2350 MYDB_END_ALLOW_THREADS;
2351 RETURN_IF_ERR();
2352
2353 self->haveStat = 1;
2354
2355 /* Turn the stat structure into a dictionary */
2356 type = _DB_get_type(self);
2357 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2358 free(sp);
2359 return NULL;
2360 }
2361
2362#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2363#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2364#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2365
2366 switch (type) {
2367 case DB_HASH:
2368 MAKE_HASH_ENTRY(magic);
2369 MAKE_HASH_ENTRY(version);
2370 MAKE_HASH_ENTRY(nkeys);
2371 MAKE_HASH_ENTRY(ndata);
2372 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002373#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002374 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002375#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002376 MAKE_HASH_ENTRY(ffactor);
2377 MAKE_HASH_ENTRY(buckets);
2378 MAKE_HASH_ENTRY(free);
2379 MAKE_HASH_ENTRY(bfree);
2380 MAKE_HASH_ENTRY(bigpages);
2381 MAKE_HASH_ENTRY(big_bfree);
2382 MAKE_HASH_ENTRY(overflows);
2383 MAKE_HASH_ENTRY(ovfl_free);
2384 MAKE_HASH_ENTRY(dup);
2385 MAKE_HASH_ENTRY(dup_free);
2386 break;
2387
2388 case DB_BTREE:
2389 case DB_RECNO:
2390 MAKE_BT_ENTRY(magic);
2391 MAKE_BT_ENTRY(version);
2392 MAKE_BT_ENTRY(nkeys);
2393 MAKE_BT_ENTRY(ndata);
2394 MAKE_BT_ENTRY(pagesize);
2395 MAKE_BT_ENTRY(minkey);
2396 MAKE_BT_ENTRY(re_len);
2397 MAKE_BT_ENTRY(re_pad);
2398 MAKE_BT_ENTRY(levels);
2399 MAKE_BT_ENTRY(int_pg);
2400 MAKE_BT_ENTRY(leaf_pg);
2401 MAKE_BT_ENTRY(dup_pg);
2402 MAKE_BT_ENTRY(over_pg);
2403 MAKE_BT_ENTRY(free);
2404 MAKE_BT_ENTRY(int_pgfree);
2405 MAKE_BT_ENTRY(leaf_pgfree);
2406 MAKE_BT_ENTRY(dup_pgfree);
2407 MAKE_BT_ENTRY(over_pgfree);
2408 break;
2409
2410 case DB_QUEUE:
2411 MAKE_QUEUE_ENTRY(magic);
2412 MAKE_QUEUE_ENTRY(version);
2413 MAKE_QUEUE_ENTRY(nkeys);
2414 MAKE_QUEUE_ENTRY(ndata);
2415 MAKE_QUEUE_ENTRY(pagesize);
2416 MAKE_QUEUE_ENTRY(pages);
2417 MAKE_QUEUE_ENTRY(re_len);
2418 MAKE_QUEUE_ENTRY(re_pad);
2419 MAKE_QUEUE_ENTRY(pgfree);
2420#if (DBVER == 31)
2421 MAKE_QUEUE_ENTRY(start);
2422#endif
2423 MAKE_QUEUE_ENTRY(first_recno);
2424 MAKE_QUEUE_ENTRY(cur_recno);
2425 break;
2426
2427 default:
2428 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2429 Py_DECREF(d);
2430 d = NULL;
2431 }
2432
2433#undef MAKE_HASH_ENTRY
2434#undef MAKE_BT_ENTRY
2435#undef MAKE_QUEUE_ENTRY
2436
2437 free(sp);
2438 return d;
2439}
2440
2441static PyObject*
2442DB_sync(DBObject* self, PyObject* args)
2443{
2444 int err;
2445 int flags = 0;
2446
2447 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2448 return NULL;
2449 CHECK_DB_NOT_CLOSED(self);
2450
2451 MYDB_BEGIN_ALLOW_THREADS;
2452 err = self->db->sync(self->db, flags);
2453 MYDB_END_ALLOW_THREADS;
2454 RETURN_IF_ERR();
2455 RETURN_NONE();
2456}
2457
2458
2459#if (DBVER >= 33)
2460static PyObject*
2461DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2462{
2463 int err, flags=0;
2464 u_int32_t count=0;
2465 PyObject* txnobj = NULL;
2466 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002467 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002468
2469 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2470 &txnobj, &flags))
2471 return NULL;
2472 CHECK_DB_NOT_CLOSED(self);
2473 if (!checkTxnObj(txnobj, &txn))
2474 return NULL;
2475
2476 MYDB_BEGIN_ALLOW_THREADS;
2477 err = self->db->truncate(self->db, txn, &count, flags);
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480 return PyInt_FromLong(count);
2481}
2482#endif
2483
2484
2485static PyObject*
2486DB_upgrade(DBObject* self, PyObject* args)
2487{
2488 int err, flags=0;
2489 char *filename;
2490
2491 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2492 return NULL;
2493 CHECK_DB_NOT_CLOSED(self);
2494
2495 MYDB_BEGIN_ALLOW_THREADS;
2496 err = self->db->upgrade(self->db, filename, flags);
2497 MYDB_END_ALLOW_THREADS;
2498 RETURN_IF_ERR();
2499 RETURN_NONE();
2500}
2501
2502
2503static PyObject*
2504DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2505{
2506 int err, flags=0;
2507 char* fileName;
2508 char* dbName=NULL;
2509 char* outFileName=NULL;
2510 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002511 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002512 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002513
2514 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2515 &fileName, &dbName, &outFileName, &flags))
2516 return NULL;
2517
2518 CHECK_DB_NOT_CLOSED(self);
2519 if (outFileName)
2520 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002521 /* XXX(nnorwitz): it should probably be an exception if outFile
2522 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002523
2524 MYDB_BEGIN_ALLOW_THREADS;
2525 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2526 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002527 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002528 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002529
2530 /* DB.verify acts as a DB handle destructor (like close); this was
2531 * documented in BerkeleyDB 4.2 but had the undocumented effect
2532 * of not being safe in prior versions while still requiring an explicit
2533 * DB.close call afterwards. Lets call close for the user to emulate
2534 * the safe 4.2 behaviour. */
2535#if (DBVER <= 41)
2536 self->db->close(self->db, 0);
2537#endif
2538 self->db = NULL;
2539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002540 RETURN_IF_ERR();
2541 RETURN_NONE();
2542}
2543
2544
2545static PyObject*
2546DB_set_get_returns_none(DBObject* self, PyObject* args)
2547{
2548 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002549 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002550
2551 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2552 return NULL;
2553 CHECK_DB_NOT_CLOSED(self);
2554
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002555 if (self->moduleFlags.getReturnsNone)
2556 ++oldValue;
2557 if (self->moduleFlags.cursorSetReturnsNone)
2558 ++oldValue;
2559 self->moduleFlags.getReturnsNone = (flags >= 1);
2560 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002561 return PyInt_FromLong(oldValue);
2562}
2563
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002564#if (DBVER >= 41)
2565static PyObject*
2566DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2567{
2568 int err;
2569 u_int32_t flags=0;
2570 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002571 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002572
2573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2574 &passwd, &flags)) {
2575 return NULL;
2576 }
2577
2578 MYDB_BEGIN_ALLOW_THREADS;
2579 err = self->db->set_encrypt(self->db, passwd, flags);
2580 MYDB_END_ALLOW_THREADS;
2581
2582 RETURN_IF_ERR();
2583 RETURN_NONE();
2584}
2585#endif /* DBVER >= 41 */
2586
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587
2588/*-------------------------------------------------------------- */
2589/* Mapping and Dictionary-like access routines */
2590
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002591Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002592{
2593 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002594 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002595 int flags = 0;
2596 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002597 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002598
2599 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002600 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2601 PyErr_SetObject(DBError, t);
2602 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002603 return -1;
2604 }
2605
2606 if (self->haveStat) { /* Has the stat function been called recently? If
2607 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002608 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002609 }
2610
2611 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002612redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002613#if (DBVER >= 43)
2614 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2615#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 err = self->db->stat(self->db, &sp, flags);
2617#else
2618 err = self->db->stat(self->db, &sp, NULL, flags);
2619#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002620
2621 /* All the stat structures have matching fields upto the ndata field,
2622 so we can use any of them for the type cast */
2623 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2624
2625 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2626 * redo a full stat to make sure.
2627 * Fixes SF python bug 1493322, pybsddb bug 1184012
2628 */
2629 if (size == 0 && (flags & DB_FAST_STAT)) {
2630 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002631 if (!err)
2632 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002633 goto redo_stat_for_length;
2634 }
2635
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636 MYDB_END_ALLOW_THREADS;
2637
2638 if (err)
2639 return -1;
2640
2641 self->haveStat = 1;
2642
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002643 free(sp);
2644 return size;
2645}
2646
2647
2648PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2649{
2650 int err;
2651 PyObject* retval;
2652 DBT key;
2653 DBT data;
2654
2655 CHECK_DB_NOT_CLOSED(self);
2656 if (!make_key_dbt(self, keyobj, &key, NULL))
2657 return NULL;
2658
2659 CLEAR_DBT(data);
2660 if (CHECK_DBFLAG(self, DB_THREAD)) {
2661 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2662 data.flags = DB_DBT_MALLOC;
2663 }
2664 MYDB_BEGIN_ALLOW_THREADS;
2665 err = self->db->get(self->db, NULL, &key, &data, 0);
2666 MYDB_END_ALLOW_THREADS;
2667 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2668 PyErr_SetObject(PyExc_KeyError, keyobj);
2669 retval = NULL;
2670 }
2671 else if (makeDBError(err)) {
2672 retval = NULL;
2673 }
2674 else {
2675 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2676 FREE_DBT(data);
2677 }
2678
2679 FREE_DBT(key);
2680 return retval;
2681}
2682
2683
2684static int
2685DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2686{
2687 DBT key, data;
2688 int retval;
2689 int flags = 0;
2690
2691 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002692 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError, t);
2694 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695 return -1;
2696 }
2697
2698 if (!make_key_dbt(self, keyobj, &key, NULL))
2699 return -1;
2700
2701 if (dataobj != NULL) {
2702 if (!make_dbt(dataobj, &data))
2703 retval = -1;
2704 else {
2705 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002706 /* dictionaries shouldn't have duplicate keys */
2707 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002708 retval = _DB_put(self, NULL, &key, &data, flags);
2709
2710 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002711 /* try deleting any old record that matches and then PUT it
2712 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002713 _DB_delete(self, NULL, &key, 0);
2714 PyErr_Clear();
2715 retval = _DB_put(self, NULL, &key, &data, flags);
2716 }
2717 }
2718 }
2719 else {
2720 /* dataobj == NULL, so delete the key */
2721 retval = _DB_delete(self, NULL, &key, 0);
2722 }
2723 FREE_DBT(key);
2724 return retval;
2725}
2726
2727
2728static PyObject*
2729DB_has_key(DBObject* self, PyObject* args)
2730{
2731 int err;
2732 PyObject* keyobj;
2733 DBT key, data;
2734 PyObject* txnobj = NULL;
2735 DB_TXN *txn = NULL;
2736
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002737 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002738 return NULL;
2739 CHECK_DB_NOT_CLOSED(self);
2740 if (!make_key_dbt(self, keyobj, &key, NULL))
2741 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002742 if (!checkTxnObj(txnobj, &txn)) {
2743 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002745 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002747 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002748 it has a record but can't allocate a buffer for the data. This saves
2749 having to deal with data we won't be using.
2750 */
2751 CLEAR_DBT(data);
2752 data.flags = DB_DBT_USERMEM;
2753
2754 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002755 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002756 MYDB_END_ALLOW_THREADS;
2757 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002758
2759 if (err == DB_BUFFER_SMALL || err == 0) {
2760 return PyInt_FromLong(1);
2761 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2762 return PyInt_FromLong(0);
2763 }
2764
2765 makeDBError(err);
2766 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002767}
2768
2769
2770#define _KEYS_LIST 1
2771#define _VALUES_LIST 2
2772#define _ITEMS_LIST 3
2773
2774static PyObject*
2775_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2776{
2777 int err, dbtype;
2778 DBT key;
2779 DBT data;
2780 DBC *cursor;
2781 PyObject* list;
2782 PyObject* item = NULL;
2783
2784 CHECK_DB_NOT_CLOSED(self);
2785 CLEAR_DBT(key);
2786 CLEAR_DBT(data);
2787
2788 dbtype = _DB_get_type(self);
2789 if (dbtype == -1)
2790 return NULL;
2791
2792 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002793 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002794 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002795
2796 /* get a cursor */
2797 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002798 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002800 if (makeDBError(err)) {
2801 Py_DECREF(list);
2802 return NULL;
2803 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804
2805 if (CHECK_DBFLAG(self, DB_THREAD)) {
2806 key.flags = DB_DBT_REALLOC;
2807 data.flags = DB_DBT_REALLOC;
2808 }
2809
2810 while (1) { /* use the cursor to traverse the DB, collecting items */
2811 MYDB_BEGIN_ALLOW_THREADS;
2812 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2813 MYDB_END_ALLOW_THREADS;
2814
2815 if (err) {
2816 /* for any error, break out of the loop */
2817 break;
2818 }
2819
2820 switch (type) {
2821 case _KEYS_LIST:
2822 switch(dbtype) {
2823 case DB_BTREE:
2824 case DB_HASH:
2825 default:
2826 item = PyString_FromStringAndSize((char*)key.data, key.size);
2827 break;
2828 case DB_RECNO:
2829 case DB_QUEUE:
2830 item = PyInt_FromLong(*((db_recno_t*)key.data));
2831 break;
2832 }
2833 break;
2834
2835 case _VALUES_LIST:
2836 item = PyString_FromStringAndSize((char*)data.data, data.size);
2837 break;
2838
2839 case _ITEMS_LIST:
2840 switch(dbtype) {
2841 case DB_BTREE:
2842 case DB_HASH:
2843 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002844 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2845 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 break;
2847 case DB_RECNO:
2848 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002849 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2850 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 break;
2852 }
2853 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002854 default:
2855 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2856 item = NULL;
2857 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 }
2859 if (item == NULL) {
2860 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 list = NULL;
2862 goto done;
2863 }
2864 PyList_Append(list, item);
2865 Py_DECREF(item);
2866 }
2867
Gregory P. Smithe9477062005-06-04 06:46:59 +00002868 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2869 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002870 Py_DECREF(list);
2871 list = NULL;
2872 }
2873
2874 done:
2875 FREE_DBT(key);
2876 FREE_DBT(data);
2877 MYDB_BEGIN_ALLOW_THREADS;
2878 cursor->c_close(cursor);
2879 MYDB_END_ALLOW_THREADS;
2880 return list;
2881}
2882
2883
2884static PyObject*
2885DB_keys(DBObject* self, PyObject* args)
2886{
2887 PyObject* txnobj = NULL;
2888 DB_TXN *txn = NULL;
2889
Georg Brandl96a8c392006-05-29 21:04:52 +00002890 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002891 return NULL;
2892 if (!checkTxnObj(txnobj, &txn))
2893 return NULL;
2894 return _DB_make_list(self, txn, _KEYS_LIST);
2895}
2896
2897
2898static PyObject*
2899DB_items(DBObject* self, PyObject* args)
2900{
2901 PyObject* txnobj = NULL;
2902 DB_TXN *txn = NULL;
2903
Georg Brandl96a8c392006-05-29 21:04:52 +00002904 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 return NULL;
2906 if (!checkTxnObj(txnobj, &txn))
2907 return NULL;
2908 return _DB_make_list(self, txn, _ITEMS_LIST);
2909}
2910
2911
2912static PyObject*
2913DB_values(DBObject* self, PyObject* args)
2914{
2915 PyObject* txnobj = NULL;
2916 DB_TXN *txn = NULL;
2917
Georg Brandl96a8c392006-05-29 21:04:52 +00002918 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919 return NULL;
2920 if (!checkTxnObj(txnobj, &txn))
2921 return NULL;
2922 return _DB_make_list(self, txn, _VALUES_LIST);
2923}
2924
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925/* --------------------------------------------------------------------- */
2926/* DBCursor methods */
2927
2928
2929static PyObject*
2930DBC_close(DBCursorObject* self, PyObject* args)
2931{
2932 int err = 0;
2933
2934 if (!PyArg_ParseTuple(args, ":close"))
2935 return NULL;
2936
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 if (self->dbc != NULL) {
2938 MYDB_BEGIN_ALLOW_THREADS;
2939 err = self->dbc->c_close(self->dbc);
2940 self->dbc = NULL;
2941 MYDB_END_ALLOW_THREADS;
2942 }
2943 RETURN_IF_ERR();
2944 RETURN_NONE();
2945}
2946
2947
2948static PyObject*
2949DBC_count(DBCursorObject* self, PyObject* args)
2950{
2951 int err = 0;
2952 db_recno_t count;
2953 int flags = 0;
2954
2955 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2956 return NULL;
2957
2958 CHECK_CURSOR_NOT_CLOSED(self);
2959
2960 MYDB_BEGIN_ALLOW_THREADS;
2961 err = self->dbc->c_count(self->dbc, &count, flags);
2962 MYDB_END_ALLOW_THREADS;
2963 RETURN_IF_ERR();
2964
2965 return PyInt_FromLong(count);
2966}
2967
2968
2969static PyObject*
2970DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2971{
2972 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2973}
2974
2975
2976static PyObject*
2977DBC_delete(DBCursorObject* self, PyObject* args)
2978{
2979 int err, flags=0;
2980
2981 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2982 return NULL;
2983
2984 CHECK_CURSOR_NOT_CLOSED(self);
2985
2986 MYDB_BEGIN_ALLOW_THREADS;
2987 err = self->dbc->c_del(self->dbc, flags);
2988 MYDB_END_ALLOW_THREADS;
2989 RETURN_IF_ERR();
2990
2991 self->mydb->haveStat = 0;
2992 RETURN_NONE();
2993}
2994
2995
2996static PyObject*
2997DBC_dup(DBCursorObject* self, PyObject* args)
2998{
2999 int err, flags =0;
3000 DBC* dbc = NULL;
3001
3002 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3003 return NULL;
3004
3005 CHECK_CURSOR_NOT_CLOSED(self);
3006
3007 MYDB_BEGIN_ALLOW_THREADS;
3008 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3009 MYDB_END_ALLOW_THREADS;
3010 RETURN_IF_ERR();
3011
3012 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3013}
3014
3015static PyObject*
3016DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3017{
3018 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3019}
3020
3021
3022static PyObject*
3023DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3024{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003025 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003026 PyObject* keyobj = NULL;
3027 PyObject* dataobj = NULL;
3028 PyObject* retval = NULL;
3029 int dlen = -1;
3030 int doff = -1;
3031 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003032 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003033 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034
3035 CLEAR_DBT(key);
3036 CLEAR_DBT(data);
3037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003038 &flags, &dlen, &doff))
3039 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003040 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3042 &kwnames[1],
3043 &keyobj, &flags, &dlen, &doff))
3044 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3047 kwnames, &keyobj, &dataobj,
3048 &flags, &dlen, &doff))
3049 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 return NULL;
3051 }
3052 }
3053 }
3054
3055 CHECK_CURSOR_NOT_CLOSED(self);
3056
3057 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3058 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003059 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3060 (!add_partial_dbt(&data, dlen, doff)) )
3061 {
3062 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003063 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003064 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065
3066 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3067 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003068 if (!(key.flags & DB_DBT_REALLOC)) {
3069 key.flags |= DB_DBT_MALLOC;
3070 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 }
3072
3073 MYDB_BEGIN_ALLOW_THREADS;
3074 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3075 MYDB_END_ALLOW_THREADS;
3076
Gregory P. Smithe9477062005-06-04 06:46:59 +00003077 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3078 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 Py_INCREF(Py_None);
3080 retval = Py_None;
3081 }
3082 else if (makeDBError(err)) {
3083 retval = NULL;
3084 }
3085 else {
3086 switch (_DB_get_type(self->mydb)) {
3087 case -1:
3088 retval = NULL;
3089 break;
3090 case DB_BTREE:
3091 case DB_HASH:
3092 default:
3093 retval = Py_BuildValue("s#s#", key.data, key.size,
3094 data.data, data.size);
3095 break;
3096 case DB_RECNO:
3097 case DB_QUEUE:
3098 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3099 data.data, data.size);
3100 break;
3101 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 FREE_DBT(data);
3103 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003104 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003105 return retval;
3106}
3107
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003108#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003109static PyObject*
3110DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3111{
3112 int err, flags=0;
3113 PyObject* keyobj = NULL;
3114 PyObject* dataobj = NULL;
3115 PyObject* retval = NULL;
3116 int dlen = -1;
3117 int doff = -1;
3118 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003119 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3120 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003121
3122 CLEAR_DBT(key);
3123 CLEAR_DBT(data);
3124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3125 &flags, &dlen, &doff))
3126 {
3127 PyErr_Clear();
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003129 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003130 &keyobj, &flags, &dlen, &doff))
3131 {
3132 PyErr_Clear();
3133 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3134 kwnames, &keyobj, &dataobj,
3135 &flags, &dlen, &doff))
3136 {
3137 return NULL;
3138 }
3139 }
3140 }
3141
3142 CHECK_CURSOR_NOT_CLOSED(self);
3143
3144 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3145 return NULL;
3146 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3147 (!add_partial_dbt(&data, dlen, doff)) ) {
3148 FREE_DBT(key);
3149 return NULL;
3150 }
3151
3152 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3153 data.flags = DB_DBT_MALLOC;
3154 if (!(key.flags & DB_DBT_REALLOC)) {
3155 key.flags |= DB_DBT_MALLOC;
3156 }
3157 }
3158
3159 CLEAR_DBT(pkey);
3160 pkey.flags = DB_DBT_MALLOC;
3161
3162 MYDB_BEGIN_ALLOW_THREADS;
3163 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3164 MYDB_END_ALLOW_THREADS;
3165
Gregory P. Smithe9477062005-06-04 06:46:59 +00003166 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3167 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003168 Py_INCREF(Py_None);
3169 retval = Py_None;
3170 }
3171 else if (makeDBError(err)) {
3172 retval = NULL;
3173 }
3174 else {
3175 PyObject *pkeyObj;
3176 PyObject *dataObj;
3177 dataObj = PyString_FromStringAndSize(data.data, data.size);
3178
3179 if (self->mydb->primaryDBType == DB_RECNO ||
3180 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003181 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003182 else
3183 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3184
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003185 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003186 {
3187 PyObject *keyObj;
3188 int type = _DB_get_type(self->mydb);
3189 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003190 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003191 else
3192 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003193#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003194 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003195#else
3196 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3197#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003198 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199 FREE_DBT(key);
3200 }
3201 else /* return just the pkey and data */
3202 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003203#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003204 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003205#else
3206 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3207#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003208 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003209 Py_DECREF(dataObj);
3210 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003211 FREE_DBT(pkey);
3212 FREE_DBT(data);
3213 }
3214 /* the only time REALLOC should be set is if we used an integer
3215 * key that make_key_dbt malloc'd for us. always free these. */
3216 if (key.flags & DB_DBT_REALLOC) {
3217 FREE_DBT(key);
3218 }
3219 return retval;
3220}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003221#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003222
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003223
3224static PyObject*
3225DBC_get_recno(DBCursorObject* self, PyObject* args)
3226{
3227 int err;
3228 db_recno_t recno;
3229 DBT key;
3230 DBT data;
3231
3232 if (!PyArg_ParseTuple(args, ":get_recno"))
3233 return NULL;
3234
3235 CHECK_CURSOR_NOT_CLOSED(self);
3236
3237 CLEAR_DBT(key);
3238 CLEAR_DBT(data);
3239 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3240 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3241 data.flags = DB_DBT_MALLOC;
3242 key.flags = DB_DBT_MALLOC;
3243 }
3244
3245 MYDB_BEGIN_ALLOW_THREADS;
3246 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3247 MYDB_END_ALLOW_THREADS;
3248 RETURN_IF_ERR();
3249
3250 recno = *((db_recno_t*)data.data);
3251 FREE_DBT(key);
3252 FREE_DBT(data);
3253 return PyInt_FromLong(recno);
3254}
3255
3256
3257static PyObject*
3258DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3259{
3260 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3261}
3262
3263
3264static PyObject*
3265DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3266{
3267 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3268}
3269
3270
3271static PyObject*
3272DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3273{
3274 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3275}
3276
3277
3278static PyObject*
3279DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3280{
3281 int err, flags = 0;
3282 PyObject* keyobj, *dataobj;
3283 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003284 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003285 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003286 int dlen = -1;
3287 int doff = -1;
3288
3289 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3290 &keyobj, &dataobj, &flags, &dlen, &doff))
3291 return NULL;
3292
3293 CHECK_CURSOR_NOT_CLOSED(self);
3294
3295 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3296 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003297 if (!make_dbt(dataobj, &data) ||
3298 !add_partial_dbt(&data, dlen, doff) )
3299 {
3300 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003301 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003302 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303
3304 MYDB_BEGIN_ALLOW_THREADS;
3305 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3306 MYDB_END_ALLOW_THREADS;
3307 FREE_DBT(key);
3308 RETURN_IF_ERR();
3309 self->mydb->haveStat = 0;
3310 RETURN_NONE();
3311}
3312
3313
3314static PyObject*
3315DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3316{
3317 int err, flags = 0;
3318 DBT key, data;
3319 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003320 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003321 int dlen = -1;
3322 int doff = -1;
3323
3324 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3325 &keyobj, &flags, &dlen, &doff))
3326 return NULL;
3327
3328 CHECK_CURSOR_NOT_CLOSED(self);
3329
3330 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3331 return NULL;
3332
3333 CLEAR_DBT(data);
3334 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3335 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3336 data.flags = DB_DBT_MALLOC;
3337 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003338 if (!add_partial_dbt(&data, dlen, doff)) {
3339 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003340 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003341 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342
3343 MYDB_BEGIN_ALLOW_THREADS;
3344 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3345 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003346 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3347 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003348 Py_INCREF(Py_None);
3349 retval = Py_None;
3350 }
3351 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003352 retval = NULL;
3353 }
3354 else {
3355 switch (_DB_get_type(self->mydb)) {
3356 case -1:
3357 retval = NULL;
3358 break;
3359 case DB_BTREE:
3360 case DB_HASH:
3361 default:
3362 retval = Py_BuildValue("s#s#", key.data, key.size,
3363 data.data, data.size);
3364 break;
3365 case DB_RECNO:
3366 case DB_QUEUE:
3367 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3368 data.data, data.size);
3369 break;
3370 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003371 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003372 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003374 /* the only time REALLOC should be set is if we used an integer
3375 * key that make_key_dbt malloc'd for us. always free these. */
3376 if (key.flags & DB_DBT_REALLOC) {
3377 FREE_DBT(key);
3378 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379
3380 return retval;
3381}
3382
3383
3384static PyObject*
3385DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3386{
3387 int err, flags = 0;
3388 DBT key, data;
3389 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003390 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 int dlen = -1;
3392 int doff = -1;
3393
3394 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3395 &keyobj, &flags, &dlen, &doff))
3396 return NULL;
3397
3398 CHECK_CURSOR_NOT_CLOSED(self);
3399
3400 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3401 return NULL;
3402
3403 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003404 if (!add_partial_dbt(&data, dlen, doff)) {
3405 FREE_DBT(key);
3406 return NULL;
3407 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3409 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003410 data.flags |= DB_DBT_MALLOC;
3411 /* only BTREE databases will return anything in the key */
3412 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3413 key.flags |= DB_DBT_MALLOC;
3414 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003416 MYDB_BEGIN_ALLOW_THREADS;
3417 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3418 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003419 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3420 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003421 Py_INCREF(Py_None);
3422 retval = Py_None;
3423 }
3424 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003425 retval = NULL;
3426 }
3427 else {
3428 switch (_DB_get_type(self->mydb)) {
3429 case -1:
3430 retval = NULL;
3431 break;
3432 case DB_BTREE:
3433 case DB_HASH:
3434 default:
3435 retval = Py_BuildValue("s#s#", key.data, key.size,
3436 data.data, data.size);
3437 break;
3438 case DB_RECNO:
3439 case DB_QUEUE:
3440 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3441 data.data, data.size);
3442 break;
3443 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003444 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 FREE_DBT(data);
3446 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003447 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003448 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 if (key.flags & DB_DBT_REALLOC) {
3450 FREE_DBT(key);
3451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452
3453 return retval;
3454}
3455
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003456static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003457_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3458 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003460 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003462 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463
Gregory P. Smith7441e652003-11-03 21:35:31 +00003464 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3466 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003467 if (!make_dbt(dataobj, &data)) {
3468 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003470 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471
3472 MYDB_BEGIN_ALLOW_THREADS;
3473 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3474 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003475 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003476 Py_INCREF(Py_None);
3477 retval = Py_None;
3478 }
3479 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 retval = NULL;
3481 }
3482 else {
3483 switch (_DB_get_type(self->mydb)) {
3484 case -1:
3485 retval = NULL;
3486 break;
3487 case DB_BTREE:
3488 case DB_HASH:
3489 default:
3490 retval = Py_BuildValue("s#s#", key.data, key.size,
3491 data.data, data.size);
3492 break;
3493 case DB_RECNO:
3494 case DB_QUEUE:
3495 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3496 data.data, data.size);
3497 break;
3498 }
3499 }
3500
3501 FREE_DBT(key);
3502 return retval;
3503}
3504
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003505static PyObject*
3506DBC_get_both(DBCursorObject* self, PyObject* args)
3507{
3508 int flags=0;
3509 PyObject *keyobj, *dataobj;
3510
3511 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3512 return NULL;
3513
Gregory P. Smith7441e652003-11-03 21:35:31 +00003514 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003515 CHECK_CURSOR_NOT_CLOSED(self);
3516
3517 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3518 self->mydb->moduleFlags.getReturnsNone);
3519}
3520
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003521/* Return size of entry */
3522static PyObject*
3523DBC_get_current_size(DBCursorObject* self, PyObject* args)
3524{
3525 int err, flags=DB_CURRENT;
3526 PyObject* retval = NULL;
3527 DBT key, data;
3528
3529 if (!PyArg_ParseTuple(args, ":get_current_size"))
3530 return NULL;
3531 CHECK_CURSOR_NOT_CLOSED(self);
3532 CLEAR_DBT(key);
3533 CLEAR_DBT(data);
3534
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003535 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003536 getting the record size. */
3537 data.flags = DB_DBT_USERMEM;
3538 data.ulen = 0;
3539 MYDB_BEGIN_ALLOW_THREADS;
3540 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3541 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003542 if (err == DB_BUFFER_SMALL || !err) {
3543 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003544 retval = PyInt_FromLong((long)data.size);
3545 err = 0;
3546 }
3547
3548 FREE_DBT(key);
3549 FREE_DBT(data);
3550 RETURN_IF_ERR();
3551 return retval;
3552}
3553
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003554static PyObject*
3555DBC_set_both(DBCursorObject* self, PyObject* args)
3556{
3557 int flags=0;
3558 PyObject *keyobj, *dataobj;
3559
3560 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3561 return NULL;
3562
Gregory P. Smith7441e652003-11-03 21:35:31 +00003563 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003564 CHECK_CURSOR_NOT_CLOSED(self);
3565
3566 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3567 self->mydb->moduleFlags.cursorSetReturnsNone);
3568}
3569
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570
3571static PyObject*
3572DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3573{
3574 int err, irecno, flags=0;
3575 db_recno_t recno;
3576 DBT key, data;
3577 PyObject* retval;
3578 int dlen = -1;
3579 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003580 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581
3582 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3583 &irecno, &flags, &dlen, &doff))
3584 return NULL;
3585
3586 CHECK_CURSOR_NOT_CLOSED(self);
3587
3588 CLEAR_DBT(key);
3589 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003590 /* use allocated space so DB will be able to realloc room for the real
3591 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 key.data = malloc(sizeof(db_recno_t));
3593 if (key.data == NULL) {
3594 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3595 return NULL;
3596 }
3597 key.size = sizeof(db_recno_t);
3598 key.ulen = key.size;
3599 memcpy(key.data, &recno, sizeof(db_recno_t));
3600 key.flags = DB_DBT_REALLOC;
3601
3602 CLEAR_DBT(data);
3603 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3604 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3605 data.flags = DB_DBT_MALLOC;
3606 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003607 if (!add_partial_dbt(&data, dlen, doff)) {
3608 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003609 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611
3612 MYDB_BEGIN_ALLOW_THREADS;
3613 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3614 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003615 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3616 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003617 Py_INCREF(Py_None);
3618 retval = Py_None;
3619 }
3620 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003621 retval = NULL;
3622 }
3623 else { /* Can only be used for BTrees, so no need to return int key */
3624 retval = Py_BuildValue("s#s#", key.data, key.size,
3625 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003626 FREE_DBT(data);
3627 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003628 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003629
3630 return retval;
3631}
3632
3633
3634static PyObject*
3635DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3636{
3637 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3638}
3639
3640
3641static PyObject*
3642DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3643{
3644 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3645}
3646
3647
3648static PyObject*
3649DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3650{
3651 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3652}
3653
3654
3655static PyObject*
3656DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3657{
3658 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3659}
3660
3661
3662static PyObject*
3663DBC_join_item(DBCursorObject* self, PyObject* args)
3664{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003666 DBT key, data;
3667 PyObject* retval;
3668
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670 return NULL;
3671
3672 CHECK_CURSOR_NOT_CLOSED(self);
3673
3674 CLEAR_DBT(key);
3675 CLEAR_DBT(data);
3676 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3677 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3678 key.flags = DB_DBT_MALLOC;
3679 }
3680
3681 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003682 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003684 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3685 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003686 Py_INCREF(Py_None);
3687 retval = Py_None;
3688 }
3689 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 retval = NULL;
3691 }
3692 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003693 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694 FREE_DBT(key);
3695 }
3696
3697 return retval;
3698}
3699
3700
3701
3702/* --------------------------------------------------------------------- */
3703/* DBEnv methods */
3704
3705
3706static PyObject*
3707DBEnv_close(DBEnvObject* self, PyObject* args)
3708{
3709 int err, flags = 0;
3710
3711 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3712 return NULL;
3713 if (!self->closed) { /* Don't close more than once */
3714 MYDB_BEGIN_ALLOW_THREADS;
3715 err = self->db_env->close(self->db_env, flags);
3716 MYDB_END_ALLOW_THREADS;
3717 /* after calling DBEnv->close, regardless of error, this DBEnv
3718 * may not be accessed again (BerkeleyDB docs). */
3719 self->closed = 1;
3720 self->db_env = NULL;
3721 RETURN_IF_ERR();
3722 }
3723 RETURN_NONE();
3724}
3725
3726
3727static PyObject*
3728DBEnv_open(DBEnvObject* self, PyObject* args)
3729{
3730 int err, flags=0, mode=0660;
3731 char *db_home;
3732
3733 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3734 return NULL;
3735
3736 CHECK_ENV_NOT_CLOSED(self);
3737
3738 MYDB_BEGIN_ALLOW_THREADS;
3739 err = self->db_env->open(self->db_env, db_home, flags, mode);
3740 MYDB_END_ALLOW_THREADS;
3741 RETURN_IF_ERR();
3742 self->closed = 0;
3743 self->flags = flags;
3744 RETURN_NONE();
3745}
3746
3747
3748static PyObject*
3749DBEnv_remove(DBEnvObject* self, PyObject* args)
3750{
3751 int err, flags=0;
3752 char *db_home;
3753
3754 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3755 return NULL;
3756 CHECK_ENV_NOT_CLOSED(self);
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 err = self->db_env->remove(self->db_env, db_home, flags);
3759 MYDB_END_ALLOW_THREADS;
3760 RETURN_IF_ERR();
3761 RETURN_NONE();
3762}
3763
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003764#if (DBVER >= 41)
3765static PyObject*
3766DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3767{
3768 int err;
3769 u_int32_t flags=0;
3770 char *file = NULL;
3771 char *database = NULL;
3772 PyObject *txnobj = NULL;
3773 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003774 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003775 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003776
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003777 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003778 &file, &database, &txnobj, &flags)) {
3779 return NULL;
3780 }
3781 if (!checkTxnObj(txnobj, &txn)) {
3782 return NULL;
3783 }
3784 CHECK_ENV_NOT_CLOSED(self);
3785 MYDB_BEGIN_ALLOW_THREADS;
3786 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3790}
3791
3792static PyObject*
3793DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3794{
3795 int err;
3796 u_int32_t flags=0;
3797 char *file = NULL;
3798 char *database = NULL;
3799 char *newname = NULL;
3800 PyObject *txnobj = NULL;
3801 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003802 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003803 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003804
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003806 &file, &database, &newname, &txnobj, &flags)) {
3807 return NULL;
3808 }
3809 if (!checkTxnObj(txnobj, &txn)) {
3810 return NULL;
3811 }
3812 CHECK_ENV_NOT_CLOSED(self);
3813 MYDB_BEGIN_ALLOW_THREADS;
3814 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3815 flags);
3816 MYDB_END_ALLOW_THREADS;
3817 RETURN_IF_ERR();
3818 RETURN_NONE();
3819}
3820
3821static PyObject*
3822DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3823{
3824 int err;
3825 u_int32_t flags=0;
3826 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003827 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003828
3829 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3830 &passwd, &flags)) {
3831 return NULL;
3832 }
3833
3834 MYDB_BEGIN_ALLOW_THREADS;
3835 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3836 MYDB_END_ALLOW_THREADS;
3837
3838 RETURN_IF_ERR();
3839 RETURN_NONE();
3840}
3841#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003842
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003843#if (DBVER >= 40)
3844static PyObject*
3845DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3846{
3847 int err;
3848 u_int32_t flags=0;
3849 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003850 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003851
3852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3853 &timeout, &flags)) {
3854 return NULL;
3855 }
3856
3857 MYDB_BEGIN_ALLOW_THREADS;
3858 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3859 MYDB_END_ALLOW_THREADS;
3860
3861 RETURN_IF_ERR();
3862 RETURN_NONE();
3863}
3864#endif /* DBVER >= 40 */
3865
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003866static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003867DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3868{
3869 int err;
3870 long shm_key = 0;
3871
3872 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3873 return NULL;
3874 CHECK_ENV_NOT_CLOSED(self);
3875
3876 err = self->db_env->set_shm_key(self->db_env, shm_key);
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3879}
3880
3881static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003882DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3883{
3884 int err, gbytes=0, bytes=0, ncache=0;
3885
3886 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3887 &gbytes, &bytes, &ncache))
3888 return NULL;
3889 CHECK_ENV_NOT_CLOSED(self);
3890
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3896}
3897
3898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003899static PyObject*
3900DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3901{
3902 int err, flags=0, onoff=0;
3903
3904 if (!PyArg_ParseTuple(args, "ii:set_flags",
3905 &flags, &onoff))
3906 return NULL;
3907 CHECK_ENV_NOT_CLOSED(self);
3908
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->set_flags(self->db_env, flags, onoff);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3914}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003915
3916
3917static PyObject*
3918DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3919{
3920 int err;
3921 char *dir;
3922
3923 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3924 return NULL;
3925 CHECK_ENV_NOT_CLOSED(self);
3926
3927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = self->db_env->set_data_dir(self->db_env, dir);
3929 MYDB_END_ALLOW_THREADS;
3930 RETURN_IF_ERR();
3931 RETURN_NONE();
3932}
3933
3934
3935static PyObject*
3936DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3937{
3938 int err, lg_bsize;
3939
3940 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3941 return NULL;
3942 CHECK_ENV_NOT_CLOSED(self);
3943
3944 MYDB_BEGIN_ALLOW_THREADS;
3945 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3946 MYDB_END_ALLOW_THREADS;
3947 RETURN_IF_ERR();
3948 RETURN_NONE();
3949}
3950
3951
3952static PyObject*
3953DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3954{
3955 int err;
3956 char *dir;
3957
3958 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3959 return NULL;
3960 CHECK_ENV_NOT_CLOSED(self);
3961
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = self->db_env->set_lg_dir(self->db_env, dir);
3964 MYDB_END_ALLOW_THREADS;
3965 RETURN_IF_ERR();
3966 RETURN_NONE();
3967}
3968
3969static PyObject*
3970DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3971{
3972 int err, lg_max;
3973
3974 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3975 return NULL;
3976 CHECK_ENV_NOT_CLOSED(self);
3977
3978 MYDB_BEGIN_ALLOW_THREADS;
3979 err = self->db_env->set_lg_max(self->db_env, lg_max);
3980 MYDB_END_ALLOW_THREADS;
3981 RETURN_IF_ERR();
3982 RETURN_NONE();
3983}
3984
3985
Neal Norwitz84562352005-10-20 04:30:15 +00003986#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003987static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003988DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3989{
3990 int err, lg_max;
3991
3992 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3993 return NULL;
3994 CHECK_ENV_NOT_CLOSED(self);
3995
3996 MYDB_BEGIN_ALLOW_THREADS;
3997 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3998 MYDB_END_ALLOW_THREADS;
3999 RETURN_IF_ERR();
4000 RETURN_NONE();
4001}
Neal Norwitz84562352005-10-20 04:30:15 +00004002#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004003
4004
4005static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004006DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4007{
4008 int err, lk_detect;
4009
4010 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4011 return NULL;
4012 CHECK_ENV_NOT_CLOSED(self);
4013
4014 MYDB_BEGIN_ALLOW_THREADS;
4015 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4016 MYDB_END_ALLOW_THREADS;
4017 RETURN_IF_ERR();
4018 RETURN_NONE();
4019}
4020
4021
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004022#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004023static PyObject*
4024DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4025{
4026 int err, max;
4027
4028 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4029 return NULL;
4030 CHECK_ENV_NOT_CLOSED(self);
4031
4032 MYDB_BEGIN_ALLOW_THREADS;
4033 err = self->db_env->set_lk_max(self->db_env, max);
4034 MYDB_END_ALLOW_THREADS;
4035 RETURN_IF_ERR();
4036 RETURN_NONE();
4037}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004038#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004039
4040
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004041
4042static PyObject*
4043DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4044{
4045 int err, max;
4046
4047 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4048 return NULL;
4049 CHECK_ENV_NOT_CLOSED(self);
4050
4051 MYDB_BEGIN_ALLOW_THREADS;
4052 err = self->db_env->set_lk_max_locks(self->db_env, max);
4053 MYDB_END_ALLOW_THREADS;
4054 RETURN_IF_ERR();
4055 RETURN_NONE();
4056}
4057
4058
4059static PyObject*
4060DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4061{
4062 int err, max;
4063
4064 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4065 return NULL;
4066 CHECK_ENV_NOT_CLOSED(self);
4067
4068 MYDB_BEGIN_ALLOW_THREADS;
4069 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4070 MYDB_END_ALLOW_THREADS;
4071 RETURN_IF_ERR();
4072 RETURN_NONE();
4073}
4074
4075
4076static PyObject*
4077DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4078{
4079 int err, max;
4080
4081 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4082 return NULL;
4083 CHECK_ENV_NOT_CLOSED(self);
4084
4085 MYDB_BEGIN_ALLOW_THREADS;
4086 err = self->db_env->set_lk_max_objects(self->db_env, max);
4087 MYDB_END_ALLOW_THREADS;
4088 RETURN_IF_ERR();
4089 RETURN_NONE();
4090}
4091
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004092
4093static PyObject*
4094DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4095{
4096 int err, mp_mmapsize;
4097
4098 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4101
4102 MYDB_BEGIN_ALLOW_THREADS;
4103 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4104 MYDB_END_ALLOW_THREADS;
4105 RETURN_IF_ERR();
4106 RETURN_NONE();
4107}
4108
4109
4110static PyObject*
4111DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4112{
4113 int err;
4114 char *dir;
4115
4116 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4117 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4119
4120 MYDB_BEGIN_ALLOW_THREADS;
4121 err = self->db_env->set_tmp_dir(self->db_env, dir);
4122 MYDB_END_ALLOW_THREADS;
4123 RETURN_IF_ERR();
4124 RETURN_NONE();
4125}
4126
4127
4128static PyObject*
4129DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4130{
4131 int flags = 0;
4132 PyObject* txnobj = NULL;
4133 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004134 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004135
4136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4137 &txnobj, &flags))
4138 return NULL;
4139
4140 if (!checkTxnObj(txnobj, &txn))
4141 return NULL;
4142 CHECK_ENV_NOT_CLOSED(self);
4143
4144 return (PyObject*)newDBTxnObject(self, txn, flags);
4145}
4146
4147
4148static PyObject*
4149DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4150{
4151 int err, kbyte=0, min=0, flags=0;
4152
4153 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4154 return NULL;
4155 CHECK_ENV_NOT_CLOSED(self);
4156
4157 MYDB_BEGIN_ALLOW_THREADS;
4158#if (DBVER >= 40)
4159 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4160#else
4161 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4162#endif
4163 MYDB_END_ALLOW_THREADS;
4164 RETURN_IF_ERR();
4165 RETURN_NONE();
4166}
4167
4168
4169static PyObject*
4170DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4171{
4172 int err, max;
4173
4174 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004178 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004179 RETURN_IF_ERR();
4180 RETURN_NONE();
4181}
4182
4183
4184static PyObject*
4185DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4186{
4187 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004188 long stamp;
4189 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004190
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004191 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004194 timestamp = (time_t)stamp;
4195 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004196 RETURN_IF_ERR();
4197 RETURN_NONE();
4198}
4199
4200
4201static PyObject*
4202DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4203{
4204 int err, atype, flags=0;
4205 int aborted = 0;
4206
4207 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4210
4211 MYDB_BEGIN_ALLOW_THREADS;
4212#if (DBVER >= 40)
4213 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4214#else
4215 err = lock_detect(self->db_env, flags, atype, &aborted);
4216#endif
4217 MYDB_END_ALLOW_THREADS;
4218 RETURN_IF_ERR();
4219 return PyInt_FromLong(aborted);
4220}
4221
4222
4223static PyObject*
4224DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4225{
4226 int flags=0;
4227 int locker, lock_mode;
4228 DBT obj;
4229 PyObject* objobj;
4230
4231 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4232 return NULL;
4233
4234
4235 if (!make_dbt(objobj, &obj))
4236 return NULL;
4237
4238 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4239}
4240
4241
4242static PyObject*
4243DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4244{
4245 int err;
4246 u_int32_t theID;
4247
4248 if (!PyArg_ParseTuple(args, ":lock_id"))
4249 return NULL;
4250
4251 CHECK_ENV_NOT_CLOSED(self);
4252 MYDB_BEGIN_ALLOW_THREADS;
4253#if (DBVER >= 40)
4254 err = self->db_env->lock_id(self->db_env, &theID);
4255#else
4256 err = lock_id(self->db_env, &theID);
4257#endif
4258 MYDB_END_ALLOW_THREADS;
4259 RETURN_IF_ERR();
4260
4261 return PyInt_FromLong((long)theID);
4262}
4263
4264
4265static PyObject*
4266DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4267{
4268 int err;
4269 DBLockObject* dblockobj;
4270
4271 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4272 return NULL;
4273
4274 CHECK_ENV_NOT_CLOSED(self);
4275 MYDB_BEGIN_ALLOW_THREADS;
4276#if (DBVER >= 40)
4277 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4278#else
4279 err = lock_put(self->db_env, &dblockobj->lock);
4280#endif
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4284}
4285
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004286#if (DBVER >= 44)
4287static PyObject*
4288DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4289{
4290 int err;
4291 char *file;
4292 u_int32_t flags = 0;
4293 static char* kwnames[] = { "file", "flags", NULL};
4294
4295 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4296 &file, &flags))
4297 return NULL;
4298 CHECK_ENV_NOT_CLOSED(self);
4299
4300 MYDB_BEGIN_ALLOW_THREADS;
4301 err = self->db_env->lsn_reset(self->db_env, file, flags);
4302 MYDB_END_ALLOW_THREADS;
4303 RETURN_IF_ERR();
4304 RETURN_NONE();
4305}
4306#endif /* DBVER >= 4.4 */
4307
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004308#if (DBVER >= 40)
4309static PyObject*
4310DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4311{
4312 int err;
4313 DB_LOG_STAT* statp = NULL;
4314 PyObject* d = NULL;
4315 u_int32_t flags = 0;
4316
4317 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4318 return NULL;
4319 CHECK_ENV_NOT_CLOSED(self);
4320
4321 MYDB_BEGIN_ALLOW_THREADS;
4322 err = self->db_env->log_stat(self->db_env, &statp, flags);
4323 MYDB_END_ALLOW_THREADS;
4324 RETURN_IF_ERR();
4325
4326 /* Turn the stat structure into a dictionary */
4327 d = PyDict_New();
4328 if (d == NULL) {
4329 if (statp)
4330 free(statp);
4331 return NULL;
4332 }
4333
4334#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4335
4336 MAKE_ENTRY(magic);
4337 MAKE_ENTRY(version);
4338 MAKE_ENTRY(mode);
4339 MAKE_ENTRY(lg_bsize);
4340#if (DBVER >= 44)
4341 MAKE_ENTRY(lg_size);
4342 MAKE_ENTRY(record);
4343#endif
4344#if (DBVER <= 40)
4345 MAKE_ENTRY(lg_max);
4346#endif
4347 MAKE_ENTRY(w_mbytes);
4348 MAKE_ENTRY(w_bytes);
4349 MAKE_ENTRY(wc_mbytes);
4350 MAKE_ENTRY(wc_bytes);
4351 MAKE_ENTRY(wcount);
4352 MAKE_ENTRY(wcount_fill);
4353#if (DBVER >= 44)
4354 MAKE_ENTRY(rcount);
4355#endif
4356 MAKE_ENTRY(scount);
4357 MAKE_ENTRY(cur_file);
4358 MAKE_ENTRY(cur_offset);
4359 MAKE_ENTRY(disk_file);
4360 MAKE_ENTRY(disk_offset);
4361 MAKE_ENTRY(maxcommitperflush);
4362 MAKE_ENTRY(mincommitperflush);
4363 MAKE_ENTRY(regsize);
4364 MAKE_ENTRY(region_wait);
4365 MAKE_ENTRY(region_nowait);
4366
4367#undef MAKE_ENTRY
4368 free(statp);
4369 return d;
4370} /* DBEnv_log_stat */
4371#endif /* DBVER >= 4.0 for log_stat method */
4372
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004373
4374static PyObject*
4375DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4376{
4377 int err;
4378 DB_LOCK_STAT* sp;
4379 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004380 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004381
4382 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4383 return NULL;
4384 CHECK_ENV_NOT_CLOSED(self);
4385
4386 MYDB_BEGIN_ALLOW_THREADS;
4387#if (DBVER >= 40)
4388 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4389#else
4390#if (DBVER >= 33)
4391 err = lock_stat(self->db_env, &sp);
4392#else
4393 err = lock_stat(self->db_env, &sp, NULL);
4394#endif
4395#endif
4396 MYDB_END_ALLOW_THREADS;
4397 RETURN_IF_ERR();
4398
4399 /* Turn the stat structure into a dictionary */
4400 d = PyDict_New();
4401 if (d == NULL) {
4402 free(sp);
4403 return NULL;
4404 }
4405
4406#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4407
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004408#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004409 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004410#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004411 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004412 MAKE_ENTRY(maxlocks);
4413 MAKE_ENTRY(maxlockers);
4414 MAKE_ENTRY(maxobjects);
4415 MAKE_ENTRY(nlocks);
4416 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004417 MAKE_ENTRY(nlockers);
4418 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004419 MAKE_ENTRY(nobjects);
4420 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004421 MAKE_ENTRY(nrequests);
4422 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004423#if (DBVER < 44)
4424 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004425 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004426#else
4427 MAKE_ENTRY(lock_nowait);
4428 MAKE_ENTRY(lock_wait);
4429#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004430 MAKE_ENTRY(ndeadlocks);
4431 MAKE_ENTRY(regsize);
4432 MAKE_ENTRY(region_wait);
4433 MAKE_ENTRY(region_nowait);
4434
4435#undef MAKE_ENTRY
4436 free(sp);
4437 return d;
4438}
4439
4440
4441static PyObject*
4442DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4443{
4444 int flags=0;
4445 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004446 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004447 PyObject* list;
4448 PyObject* item = NULL;
4449
4450 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4451 return NULL;
4452
4453 CHECK_ENV_NOT_CLOSED(self);
4454 MYDB_BEGIN_ALLOW_THREADS;
4455#if (DBVER >= 40)
4456 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4457#elif (DBVER == 33)
4458 err = log_archive(self->db_env, &log_list, flags);
4459#else
4460 err = log_archive(self->db_env, &log_list, flags, NULL);
4461#endif
4462 MYDB_END_ALLOW_THREADS;
4463 RETURN_IF_ERR();
4464
Gregory P. Smithbad47452006-06-05 00:33:35 +00004465 list = PyList_New(0);
4466 if (list == NULL) {
4467 if (log_list)
4468 free(log_list);
4469 return NULL;
4470 }
4471
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004472 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004473 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004474 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4475 item = PyString_FromString (*log_list);
4476 if (item == NULL) {
4477 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004478 list = NULL;
4479 break;
4480 }
4481 PyList_Append(list, item);
4482 Py_DECREF(item);
4483 }
4484 free(log_list_start);
4485 }
4486 return list;
4487}
4488
4489
4490static PyObject*
4491DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4492{
4493 int err;
4494 DB_TXN_STAT* sp;
4495 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004496 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004497
4498 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4499 return NULL;
4500 CHECK_ENV_NOT_CLOSED(self);
4501
4502 MYDB_BEGIN_ALLOW_THREADS;
4503#if (DBVER >= 40)
4504 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4505#elif (DBVER == 33)
4506 err = txn_stat(self->db_env, &sp);
4507#else
4508 err = txn_stat(self->db_env, &sp, NULL);
4509#endif
4510 MYDB_END_ALLOW_THREADS;
4511 RETURN_IF_ERR();
4512
4513 /* Turn the stat structure into a dictionary */
4514 d = PyDict_New();
4515 if (d == NULL) {
4516 free(sp);
4517 return NULL;
4518 }
4519
4520#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004521#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004523 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004524 MAKE_ENTRY(last_txnid);
4525 MAKE_ENTRY(maxtxns);
4526 MAKE_ENTRY(nactive);
4527 MAKE_ENTRY(maxnactive);
4528 MAKE_ENTRY(nbegins);
4529 MAKE_ENTRY(naborts);
4530 MAKE_ENTRY(ncommits);
4531 MAKE_ENTRY(regsize);
4532 MAKE_ENTRY(region_wait);
4533 MAKE_ENTRY(region_nowait);
4534
4535#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004536#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004537 free(sp);
4538 return d;
4539}
4540
4541
4542static PyObject*
4543DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4544{
4545 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004546 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547
4548 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4549 return NULL;
4550 CHECK_ENV_NOT_CLOSED(self);
4551
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004552 if (self->moduleFlags.getReturnsNone)
4553 ++oldValue;
4554 if (self->moduleFlags.cursorSetReturnsNone)
4555 ++oldValue;
4556 self->moduleFlags.getReturnsNone = (flags >= 1);
4557 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004558 return PyInt_FromLong(oldValue);
4559}
4560
4561
4562/* --------------------------------------------------------------------- */
4563/* DBTxn methods */
4564
4565
4566static PyObject*
4567DBTxn_commit(DBTxnObject* self, PyObject* args)
4568{
4569 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004570 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004571
4572 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4573 return NULL;
4574
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004575 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004576 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4577 "after txn_commit or txn_abort");
4578 PyErr_SetObject(DBError, t);
4579 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004580 return NULL;
4581 }
4582 txn = self->txn;
4583 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584 MYDB_BEGIN_ALLOW_THREADS;
4585#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004586 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004588 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589#endif
4590 MYDB_END_ALLOW_THREADS;
4591 RETURN_IF_ERR();
4592 RETURN_NONE();
4593}
4594
4595static PyObject*
4596DBTxn_prepare(DBTxnObject* self, PyObject* args)
4597{
4598#if (DBVER >= 33)
4599 int err;
4600 char* gid=NULL;
4601 int gid_size=0;
4602
4603 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4604 return NULL;
4605
4606 if (gid_size != DB_XIDDATASIZE) {
4607 PyErr_SetString(PyExc_TypeError,
4608 "gid must be DB_XIDDATASIZE bytes long");
4609 return NULL;
4610 }
4611
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004612 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004613 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4614 "after txn_commit or txn_abort");
4615 PyErr_SetObject(DBError, t);
4616 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004617 return NULL;
4618 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004619 MYDB_BEGIN_ALLOW_THREADS;
4620#if (DBVER >= 40)
4621 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4622#else
4623 err = txn_prepare(self->txn, (u_int8_t*)gid);
4624#endif
4625 MYDB_END_ALLOW_THREADS;
4626 RETURN_IF_ERR();
4627 RETURN_NONE();
4628#else
4629 int err;
4630
4631 if (!PyArg_ParseTuple(args, ":prepare"))
4632 return NULL;
4633
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004634 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004635 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4636 "after txn_commit or txn_abort");
4637 PyErr_SetObject(DBError, t);
4638 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004639 return NULL;
4640 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004641 MYDB_BEGIN_ALLOW_THREADS;
4642 err = txn_prepare(self->txn);
4643 MYDB_END_ALLOW_THREADS;
4644 RETURN_IF_ERR();
4645 RETURN_NONE();
4646#endif
4647}
4648
4649
4650static PyObject*
4651DBTxn_abort(DBTxnObject* self, PyObject* args)
4652{
4653 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004654 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004655
4656 if (!PyArg_ParseTuple(args, ":abort"))
4657 return NULL;
4658
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004659 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004660 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4661 "after txn_commit or txn_abort");
4662 PyErr_SetObject(DBError, t);
4663 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004664 return NULL;
4665 }
4666 txn = self->txn;
4667 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004668 MYDB_BEGIN_ALLOW_THREADS;
4669#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004670 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004671#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004672 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004673#endif
4674 MYDB_END_ALLOW_THREADS;
4675 RETURN_IF_ERR();
4676 RETURN_NONE();
4677}
4678
4679
4680static PyObject*
4681DBTxn_id(DBTxnObject* self, PyObject* args)
4682{
4683 int id;
4684
4685 if (!PyArg_ParseTuple(args, ":id"))
4686 return NULL;
4687
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004688 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004689 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4690 "after txn_commit or txn_abort");
4691 PyErr_SetObject(DBError, t);
4692 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004693 return NULL;
4694 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004695 MYDB_BEGIN_ALLOW_THREADS;
4696#if (DBVER >= 40)
4697 id = self->txn->id(self->txn);
4698#else
4699 id = txn_id(self->txn);
4700#endif
4701 MYDB_END_ALLOW_THREADS;
4702 return PyInt_FromLong(id);
4703}
4704
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004705#if (DBVER >= 43)
4706/* --------------------------------------------------------------------- */
4707/* DBSequence methods */
4708
4709
4710static PyObject*
4711DBSequence_close(DBSequenceObject* self, PyObject* args)
4712{
4713 int err, flags=0;
4714 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4715 return NULL;
4716 CHECK_SEQUENCE_NOT_CLOSED(self)
4717
4718 MYDB_BEGIN_ALLOW_THREADS
4719 err = self->sequence->close(self->sequence, flags);
4720 self->sequence = NULL;
4721 MYDB_END_ALLOW_THREADS
4722
4723 RETURN_IF_ERR();
4724
4725 RETURN_NONE();
4726}
4727
4728static PyObject*
4729DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4730{
4731 int err, flags = 0;
4732 int delta = 1;
4733 db_seq_t value;
4734 PyObject *txnobj = NULL;
4735 DB_TXN *txn = NULL;
4736 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4737 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4738 return NULL;
4739 CHECK_SEQUENCE_NOT_CLOSED(self)
4740
4741 if (!checkTxnObj(txnobj, &txn))
4742 return NULL;
4743
4744 MYDB_BEGIN_ALLOW_THREADS
4745 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4746 MYDB_END_ALLOW_THREADS
4747
4748 RETURN_IF_ERR();
4749 return PyLong_FromLongLong(value);
4750
4751}
4752
4753static PyObject*
4754DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4755{
4756 if (!PyArg_ParseTuple(args,":get_dbp"))
4757 return NULL;
4758 CHECK_SEQUENCE_NOT_CLOSED(self)
4759 Py_INCREF(self->mydb);
4760 return (PyObject* )self->mydb;
4761}
4762
4763static PyObject*
4764DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4765{
4766 int err;
4767 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00004768 PyObject *retval = NULL;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004769 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004770 CHECK_SEQUENCE_NOT_CLOSED(self)
4771 MYDB_BEGIN_ALLOW_THREADS
4772 err = self->sequence->get_key(self->sequence, &key);
4773 MYDB_END_ALLOW_THREADS
4774
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004775 if (!err)
4776 retval = PyString_FromStringAndSize(key.data, key.size);
4777
4778 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004779 RETURN_IF_ERR();
4780
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004781 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004782}
4783
4784static PyObject*
4785DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4786{
4787 int err;
4788 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004789 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004790 return NULL;
4791 CHECK_SEQUENCE_NOT_CLOSED(self)
4792
4793 MYDB_BEGIN_ALLOW_THREADS
4794 err = self->sequence->initial_value(self->sequence, value);
4795 MYDB_END_ALLOW_THREADS
4796
4797 RETURN_IF_ERR();
4798
4799 RETURN_NONE();
4800}
4801
4802static PyObject*
4803DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4804{
4805 int err, flags = 0;
4806 PyObject* keyobj;
4807 PyObject *txnobj = NULL;
4808 DB_TXN *txn = NULL;
4809 DBT key;
4810
4811 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004812 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004813 return NULL;
4814
4815 if (!checkTxnObj(txnobj, &txn))
4816 return NULL;
4817
4818 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4819 return NULL;
4820
4821 MYDB_BEGIN_ALLOW_THREADS
4822 err = self->sequence->open(self->sequence, txn, &key, flags);
4823 MYDB_END_ALLOW_THREADS
4824
4825 CLEAR_DBT(key);
4826 RETURN_IF_ERR();
4827
4828 RETURN_NONE();
4829}
4830
4831static PyObject*
4832DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4833{
4834 int err, flags = 0;
4835 PyObject *txnobj = NULL;
4836 DB_TXN *txn = NULL;
4837
4838 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004839 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004840 return NULL;
4841
4842 if (!checkTxnObj(txnobj, &txn))
4843 return NULL;
4844
4845 CHECK_SEQUENCE_NOT_CLOSED(self)
4846
4847 MYDB_BEGIN_ALLOW_THREADS
4848 err = self->sequence->remove(self->sequence, txn, flags);
4849 MYDB_END_ALLOW_THREADS
4850
4851 RETURN_IF_ERR();
4852 RETURN_NONE();
4853}
4854
4855static PyObject*
4856DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4857{
4858 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004859 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004860 return NULL;
4861 CHECK_SEQUENCE_NOT_CLOSED(self)
4862
4863 MYDB_BEGIN_ALLOW_THREADS
4864 err = self->sequence->set_cachesize(self->sequence, size);
4865 MYDB_END_ALLOW_THREADS
4866
4867 RETURN_IF_ERR();
4868 RETURN_NONE();
4869}
4870
4871static PyObject*
4872DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4873{
4874 int err, size;
4875 if (!PyArg_ParseTuple(args,":get_cachesize"))
4876 return NULL;
4877 CHECK_SEQUENCE_NOT_CLOSED(self)
4878
4879 MYDB_BEGIN_ALLOW_THREADS
4880 err = self->sequence->get_cachesize(self->sequence, &size);
4881 MYDB_END_ALLOW_THREADS
4882
4883 RETURN_IF_ERR();
4884 return PyInt_FromLong(size);
4885}
4886
4887static PyObject*
4888DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4889{
4890 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004891 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004892 return NULL;
4893 CHECK_SEQUENCE_NOT_CLOSED(self)
4894
4895 MYDB_BEGIN_ALLOW_THREADS
4896 err = self->sequence->set_flags(self->sequence, flags);
4897 MYDB_END_ALLOW_THREADS
4898
4899 RETURN_IF_ERR();
4900 RETURN_NONE();
4901
4902}
4903
4904static PyObject*
4905DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4906{
4907 unsigned int flags;
4908 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004909 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004910 return NULL;
4911 CHECK_SEQUENCE_NOT_CLOSED(self)
4912
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err = self->sequence->get_flags(self->sequence, &flags);
4915 MYDB_END_ALLOW_THREADS
4916
4917 RETURN_IF_ERR();
4918 return PyInt_FromLong((int)flags);
4919}
4920
4921static PyObject*
4922DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4923{
4924 int err;
4925 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004926 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004927 return NULL;
4928 CHECK_SEQUENCE_NOT_CLOSED(self)
4929
4930 MYDB_BEGIN_ALLOW_THREADS
4931 err = self->sequence->set_range(self->sequence, min, max);
4932 MYDB_END_ALLOW_THREADS
4933
4934 RETURN_IF_ERR();
4935 RETURN_NONE();
4936}
4937
4938static PyObject*
4939DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4940{
4941 int err;
4942 db_seq_t min, max;
4943 if (!PyArg_ParseTuple(args,":get_range"))
4944 return NULL;
4945 CHECK_SEQUENCE_NOT_CLOSED(self)
4946
4947 MYDB_BEGIN_ALLOW_THREADS
4948 err = self->sequence->get_range(self->sequence, &min, &max);
4949 MYDB_END_ALLOW_THREADS
4950
4951 RETURN_IF_ERR();
4952 return Py_BuildValue("(LL)", min, max);
4953}
4954
4955static PyObject*
4956DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4957{
4958 int err, flags = 0;
4959 DB_SEQUENCE_STAT* sp = NULL;
4960 PyObject* dict_stat;
4961 static char* kwnames[] = {"flags", NULL };
4962 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4963 return NULL;
4964 CHECK_SEQUENCE_NOT_CLOSED(self);
4965
4966 MYDB_BEGIN_ALLOW_THREADS;
4967 err = self->sequence->stat(self->sequence, &sp, flags);
4968 MYDB_END_ALLOW_THREADS;
4969 RETURN_IF_ERR();
4970
4971 if ((dict_stat = PyDict_New()) == NULL) {
4972 free(sp);
4973 return NULL;
4974 }
4975
4976
4977#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4978#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4979
4980 MAKE_INT_ENTRY(wait);
4981 MAKE_INT_ENTRY(nowait);
4982 MAKE_LONG_LONG_ENTRY(current);
4983 MAKE_LONG_LONG_ENTRY(value);
4984 MAKE_LONG_LONG_ENTRY(last_value);
4985 MAKE_LONG_LONG_ENTRY(min);
4986 MAKE_LONG_LONG_ENTRY(max);
4987 MAKE_INT_ENTRY(cache_size);
4988 MAKE_INT_ENTRY(flags);
4989
4990#undef MAKE_INT_ENTRY
4991#undef MAKE_LONG_LONG_ENTRY
4992
4993 free(sp);
4994 return dict_stat;
4995}
4996#endif
4997
4998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004999/* --------------------------------------------------------------------- */
5000/* Method definition tables and type objects */
5001
5002static PyMethodDef DB_methods[] = {
5003 {"append", (PyCFunction)DB_append, METH_VARARGS},
5004#if (DBVER >= 33)
5005 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5006#endif
5007 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005008 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5009 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005010 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5011 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5012 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5013 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005014#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005015 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005016#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005017 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5018 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5019 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5020 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5021 {"join", (PyCFunction)DB_join, METH_VARARGS},
5022 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5023 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5024 {"items", (PyCFunction)DB_items, METH_VARARGS},
5025 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5026 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5027 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5028 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5029 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5030 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005031#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005032 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005033#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005034 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005035#if (DBVER >= 41)
5036 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005038 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5039 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5040 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5041 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5042 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5043 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5044 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5045 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5046 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005047 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005048 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005049 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5050#if (DBVER >= 33)
5051 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5052#endif
5053 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5054 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5055 {"values", (PyCFunction)DB_values, METH_VARARGS},
5056 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5057 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5058 {NULL, NULL} /* sentinel */
5059};
5060
5061
5062static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005063 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005064 (binaryfunc)DB_subscript, /*mp_subscript*/
5065 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5066};
5067
5068
5069static PyMethodDef DBCursor_methods[] = {
5070 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5071 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5072 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5073 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5074 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5075 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5076 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005077#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005078 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005079#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005080 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5081 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5082 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5083 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5084 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5085 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5086 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5087 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005088 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005089 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005090 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5091 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5092 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5093 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5094 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5095 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5096 {NULL, NULL} /* sentinel */
5097};
5098
5099
5100static PyMethodDef DBEnv_methods[] = {
5101 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5102 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5103 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005104#if (DBVER >= 41)
5105 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5106 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5107 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5108#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005109#if (DBVER >= 40)
5110 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5111#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005112 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005113 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5114 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005115 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005116 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5117 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5118 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005119#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005120 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005121#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005122 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005123#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005124 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5127 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5128 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005129 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5130 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5131 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5132 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5133 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5134 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005135 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005136 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5137 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5138 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5139 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5140 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5141 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005142#if (DBVER >= 40)
5143 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5144#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005145#if (DBVER >= 44)
5146 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5147#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005148 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5149 {NULL, NULL} /* sentinel */
5150};
5151
5152
5153static PyMethodDef DBTxn_methods[] = {
5154 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5155 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5156 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5157 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5158 {NULL, NULL} /* sentinel */
5159};
5160
5161
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005162#if (DBVER >= 43)
5163static PyMethodDef DBSequence_methods[] = {
5164 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5165 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5166 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5167 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005168 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5169 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5170 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5171 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5172 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5173 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5174 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5175 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5176 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5177 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5178 {NULL, NULL} /* sentinel */
5179};
5180#endif
5181
5182
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005183static PyObject*
5184DB_getattr(DBObject* self, char *name)
5185{
5186 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5187}
5188
5189
5190static PyObject*
5191DBEnv_getattr(DBEnvObject* self, char *name)
5192{
5193 if (!strcmp(name, "db_home")) {
5194 CHECK_ENV_NOT_CLOSED(self);
5195 if (self->db_env->db_home == NULL) {
5196 RETURN_NONE();
5197 }
5198 return PyString_FromString(self->db_env->db_home);
5199 }
5200
5201 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5202}
5203
5204
5205static PyObject*
5206DBCursor_getattr(DBCursorObject* self, char *name)
5207{
5208 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5209}
5210
5211static PyObject*
5212DBTxn_getattr(DBTxnObject* self, char *name)
5213{
5214 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5215}
5216
5217static PyObject*
5218DBLock_getattr(DBLockObject* self, char *name)
5219{
5220 return NULL;
5221}
5222
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005223#if (DBVER >= 43)
5224static PyObject*
5225DBSequence_getattr(DBSequenceObject* self, char *name)
5226{
5227 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5228}
5229#endif
5230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005231statichere PyTypeObject DB_Type = {
5232 PyObject_HEAD_INIT(NULL)
5233 0, /*ob_size*/
5234 "DB", /*tp_name*/
5235 sizeof(DBObject), /*tp_basicsize*/
5236 0, /*tp_itemsize*/
5237 /* methods */
5238 (destructor)DB_dealloc, /*tp_dealloc*/
5239 0, /*tp_print*/
5240 (getattrfunc)DB_getattr, /*tp_getattr*/
5241 0, /*tp_setattr*/
5242 0, /*tp_compare*/
5243 0, /*tp_repr*/
5244 0, /*tp_as_number*/
5245 0, /*tp_as_sequence*/
5246 &DB_mapping,/*tp_as_mapping*/
5247 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005248 0, /* tp_call */
5249 0, /* tp_str */
5250 0, /* tp_getattro */
5251 0, /* tp_setattro */
5252 0, /* tp_as_buffer */
5253 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5254 0, /* tp_doc */
5255 0, /* tp_traverse */
5256 0, /* tp_clear */
5257 0, /* tp_richcompare */
5258 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259};
5260
5261
5262statichere PyTypeObject DBCursor_Type = {
5263 PyObject_HEAD_INIT(NULL)
5264 0, /*ob_size*/
5265 "DBCursor", /*tp_name*/
5266 sizeof(DBCursorObject), /*tp_basicsize*/
5267 0, /*tp_itemsize*/
5268 /* methods */
5269 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5270 0, /*tp_print*/
5271 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5272 0, /*tp_setattr*/
5273 0, /*tp_compare*/
5274 0, /*tp_repr*/
5275 0, /*tp_as_number*/
5276 0, /*tp_as_sequence*/
5277 0, /*tp_as_mapping*/
5278 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005279 0, /* tp_call */
5280 0, /* tp_str */
5281 0, /* tp_getattro */
5282 0, /* tp_setattro */
5283 0, /* tp_as_buffer */
5284 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5285 0, /* tp_doc */
5286 0, /* tp_traverse */
5287 0, /* tp_clear */
5288 0, /* tp_richcompare */
5289 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005290};
5291
5292
5293statichere PyTypeObject DBEnv_Type = {
5294 PyObject_HEAD_INIT(NULL)
5295 0, /*ob_size*/
5296 "DBEnv", /*tp_name*/
5297 sizeof(DBEnvObject), /*tp_basicsize*/
5298 0, /*tp_itemsize*/
5299 /* methods */
5300 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5301 0, /*tp_print*/
5302 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5303 0, /*tp_setattr*/
5304 0, /*tp_compare*/
5305 0, /*tp_repr*/
5306 0, /*tp_as_number*/
5307 0, /*tp_as_sequence*/
5308 0, /*tp_as_mapping*/
5309 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005310 0, /* tp_call */
5311 0, /* tp_str */
5312 0, /* tp_getattro */
5313 0, /* tp_setattro */
5314 0, /* tp_as_buffer */
5315 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5316 0, /* tp_doc */
5317 0, /* tp_traverse */
5318 0, /* tp_clear */
5319 0, /* tp_richcompare */
5320 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005321};
5322
5323statichere PyTypeObject DBTxn_Type = {
5324 PyObject_HEAD_INIT(NULL)
5325 0, /*ob_size*/
5326 "DBTxn", /*tp_name*/
5327 sizeof(DBTxnObject), /*tp_basicsize*/
5328 0, /*tp_itemsize*/
5329 /* methods */
5330 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5331 0, /*tp_print*/
5332 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5333 0, /*tp_setattr*/
5334 0, /*tp_compare*/
5335 0, /*tp_repr*/
5336 0, /*tp_as_number*/
5337 0, /*tp_as_sequence*/
5338 0, /*tp_as_mapping*/
5339 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005340 0, /* tp_call */
5341 0, /* tp_str */
5342 0, /* tp_getattro */
5343 0, /* tp_setattro */
5344 0, /* tp_as_buffer */
5345 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5346 0, /* tp_doc */
5347 0, /* tp_traverse */
5348 0, /* tp_clear */
5349 0, /* tp_richcompare */
5350 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005351};
5352
5353
5354statichere PyTypeObject DBLock_Type = {
5355 PyObject_HEAD_INIT(NULL)
5356 0, /*ob_size*/
5357 "DBLock", /*tp_name*/
5358 sizeof(DBLockObject), /*tp_basicsize*/
5359 0, /*tp_itemsize*/
5360 /* methods */
5361 (destructor)DBLock_dealloc, /*tp_dealloc*/
5362 0, /*tp_print*/
5363 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5364 0, /*tp_setattr*/
5365 0, /*tp_compare*/
5366 0, /*tp_repr*/
5367 0, /*tp_as_number*/
5368 0, /*tp_as_sequence*/
5369 0, /*tp_as_mapping*/
5370 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005371 0, /* tp_call */
5372 0, /* tp_str */
5373 0, /* tp_getattro */
5374 0, /* tp_setattro */
5375 0, /* tp_as_buffer */
5376 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5377 0, /* tp_doc */
5378 0, /* tp_traverse */
5379 0, /* tp_clear */
5380 0, /* tp_richcompare */
5381 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005382};
5383
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005384#if (DBVER >= 43)
5385statichere PyTypeObject DBSequence_Type = {
5386 PyObject_HEAD_INIT(NULL)
5387 0, /*ob_size*/
5388 "DBSequence", /*tp_name*/
5389 sizeof(DBSequenceObject), /*tp_basicsize*/
5390 0, /*tp_itemsize*/
5391 /* methods */
5392 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5393 0, /*tp_print*/
5394 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5395 0, /*tp_setattr*/
5396 0, /*tp_compare*/
5397 0, /*tp_repr*/
5398 0, /*tp_as_number*/
5399 0, /*tp_as_sequence*/
5400 0, /*tp_as_mapping*/
5401 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005402 0, /* tp_call */
5403 0, /* tp_str */
5404 0, /* tp_getattro */
5405 0, /* tp_setattro */
5406 0, /* tp_as_buffer */
5407 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5408 0, /* tp_doc */
5409 0, /* tp_traverse */
5410 0, /* tp_clear */
5411 0, /* tp_richcompare */
5412 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005413};
5414#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005415
5416/* --------------------------------------------------------------------- */
5417/* Module-level functions */
5418
5419static PyObject*
5420DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5421{
5422 PyObject* dbenvobj = NULL;
5423 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005424 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005425
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5427 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005428 return NULL;
5429 if (dbenvobj == Py_None)
5430 dbenvobj = NULL;
5431 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5432 makeTypeError("DBEnv", dbenvobj);
5433 return NULL;
5434 }
5435
5436 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5437}
5438
5439
5440static PyObject*
5441DBEnv_construct(PyObject* self, PyObject* args)
5442{
5443 int flags = 0;
5444 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5445 return (PyObject* )newDBEnvObject(flags);
5446}
5447
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005448#if (DBVER >= 43)
5449static PyObject*
5450DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5451{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005452 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005453 int flags = 0;
5454 static char* kwnames[] = { "db", "flags", NULL};
5455
5456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5457 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005458 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005459 makeTypeError("DB", dbobj);
5460 return NULL;
5461 }
5462 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5463}
5464#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005465
5466static char bsddb_version_doc[] =
5467"Returns a tuple of major, minor, and patch release numbers of the\n\
5468underlying DB library.";
5469
5470static PyObject*
5471bsddb_version(PyObject* self, PyObject* args)
5472{
5473 int major, minor, patch;
5474
5475 if (!PyArg_ParseTuple(args, ":version"))
5476 return NULL;
5477 db_version(&major, &minor, &patch);
5478 return Py_BuildValue("(iii)", major, minor, patch);
5479}
5480
5481
5482/* List of functions defined in the module */
5483
5484static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005485 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5486 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5487#if (DBVER >= 43)
5488 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5489#endif
5490 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005491 {NULL, NULL} /* sentinel */
5492};
5493
Gregory P. Smith39250532007-10-09 06:02:21 +00005494/* API structure */
5495static BSDDB_api bsddb_api;
5496
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005497
5498/* --------------------------------------------------------------------- */
5499/* Module initialization */
5500
5501
5502/* Convenience routine to export an integer value.
5503 * Errors are silently ignored, for better or for worse...
5504 */
5505#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5506
Gregory P. Smith41631e82003-09-21 00:08:14 +00005507#define MODULE_NAME_MAX_LEN 11
5508static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005509
5510DL_EXPORT(void) init_bsddb(void)
5511{
5512 PyObject* m;
5513 PyObject* d;
5514 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5515 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5516 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005517 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005518
5519 /* Initialize the type of the new type objects here; doing it here
5520 is required for portability to Windows without requiring C++. */
Martin v. Löwis68192102007-07-21 06:55:02 +00005521 Py_Type(&DB_Type) = &PyType_Type;
5522 Py_Type(&DBCursor_Type) = &PyType_Type;
5523 Py_Type(&DBEnv_Type) = &PyType_Type;
5524 Py_Type(&DBTxn_Type) = &PyType_Type;
5525 Py_Type(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005526#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +00005527 Py_Type(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005528#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005529
5530
Mark Hammonda69d4092003-04-22 23:13:27 +00005531#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005532 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005533 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005534#endif
5535
5536 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005537 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005538 if (m == NULL)
5539 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005540
5541 /* Add some symbolic constants to the module */
5542 d = PyModule_GetDict(m);
5543 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5544 PyDict_SetItemString(d, "cvsid", cvsid_s);
5545 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5546 Py_DECREF(pybsddb_version_s);
5547 pybsddb_version_s = NULL;
5548 Py_DECREF(cvsid_s);
5549 cvsid_s = NULL;
5550 Py_DECREF(db_version_s);
5551 db_version_s = NULL;
5552
5553 ADD_INT(d, DB_VERSION_MAJOR);
5554 ADD_INT(d, DB_VERSION_MINOR);
5555 ADD_INT(d, DB_VERSION_PATCH);
5556
5557 ADD_INT(d, DB_MAX_PAGES);
5558 ADD_INT(d, DB_MAX_RECORDS);
5559
Gregory P. Smith41631e82003-09-21 00:08:14 +00005560#if (DBVER >= 42)
5561 ADD_INT(d, DB_RPCCLIENT);
5562#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005564 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5565 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5566#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005567 ADD_INT(d, DB_XA_CREATE);
5568
5569 ADD_INT(d, DB_CREATE);
5570 ADD_INT(d, DB_NOMMAP);
5571 ADD_INT(d, DB_THREAD);
5572
5573 ADD_INT(d, DB_FORCE);
5574 ADD_INT(d, DB_INIT_CDB);
5575 ADD_INT(d, DB_INIT_LOCK);
5576 ADD_INT(d, DB_INIT_LOG);
5577 ADD_INT(d, DB_INIT_MPOOL);
5578 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005579 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005580
5581 ADD_INT(d, DB_RECOVER);
5582 ADD_INT(d, DB_RECOVER_FATAL);
5583 ADD_INT(d, DB_TXN_NOSYNC);
5584 ADD_INT(d, DB_USE_ENVIRON);
5585 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5586
5587 ADD_INT(d, DB_LOCKDOWN);
5588 ADD_INT(d, DB_PRIVATE);
5589 ADD_INT(d, DB_SYSTEM_MEM);
5590
5591 ADD_INT(d, DB_TXN_SYNC);
5592 ADD_INT(d, DB_TXN_NOWAIT);
5593
5594 ADD_INT(d, DB_EXCL);
5595 ADD_INT(d, DB_FCNTL_LOCKING);
5596 ADD_INT(d, DB_ODDFILESIZE);
5597 ADD_INT(d, DB_RDWRMASTER);
5598 ADD_INT(d, DB_RDONLY);
5599 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005600 ADD_INT(d, DB_EXTENT);
5601 ADD_INT(d, DB_CDB_ALLDB);
5602 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005603 ADD_INT(d, DB_UPGRADE);
5604
5605 ADD_INT(d, DB_AGGRESSIVE);
5606 ADD_INT(d, DB_NOORDERCHK);
5607 ADD_INT(d, DB_ORDERCHKONLY);
5608 ADD_INT(d, DB_PR_PAGE);
5609#if ! (DBVER >= 33)
5610 ADD_INT(d, DB_VRFY_FLAGMASK);
5611 ADD_INT(d, DB_PR_HEADERS);
5612#endif
5613 ADD_INT(d, DB_PR_RECOVERYTEST);
5614 ADD_INT(d, DB_SALVAGE);
5615
5616 ADD_INT(d, DB_LOCK_NORUN);
5617 ADD_INT(d, DB_LOCK_DEFAULT);
5618 ADD_INT(d, DB_LOCK_OLDEST);
5619 ADD_INT(d, DB_LOCK_RANDOM);
5620 ADD_INT(d, DB_LOCK_YOUNGEST);
5621#if (DBVER >= 33)
5622 ADD_INT(d, DB_LOCK_MAXLOCKS);
5623 ADD_INT(d, DB_LOCK_MINLOCKS);
5624 ADD_INT(d, DB_LOCK_MINWRITE);
5625#endif
5626
5627
5628#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005629 /* docs say to use zero instead */
5630 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005631#else
5632 ADD_INT(d, DB_LOCK_CONFLICT);
5633#endif
5634
5635 ADD_INT(d, DB_LOCK_DUMP);
5636 ADD_INT(d, DB_LOCK_GET);
5637 ADD_INT(d, DB_LOCK_INHERIT);
5638 ADD_INT(d, DB_LOCK_PUT);
5639 ADD_INT(d, DB_LOCK_PUT_ALL);
5640 ADD_INT(d, DB_LOCK_PUT_OBJ);
5641
5642 ADD_INT(d, DB_LOCK_NG);
5643 ADD_INT(d, DB_LOCK_READ);
5644 ADD_INT(d, DB_LOCK_WRITE);
5645 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005646 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647 ADD_INT(d, DB_LOCK_IWRITE);
5648 ADD_INT(d, DB_LOCK_IREAD);
5649 ADD_INT(d, DB_LOCK_IWR);
5650#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005651#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005652 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005653#else
5654 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5655#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656 ADD_INT(d, DB_LOCK_WWRITE);
5657#endif
5658
5659 ADD_INT(d, DB_LOCK_RECORD);
5660 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005661 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005662#if (DBVER >= 33)
5663 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5664#endif
5665
5666 ADD_INT(d, DB_LOCK_NOWAIT);
5667 ADD_INT(d, DB_LOCK_RECORD);
5668 ADD_INT(d, DB_LOCK_UPGRADE);
5669
5670#if (DBVER >= 33)
5671 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005672#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005674#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675 ADD_INT(d, DB_LSTAT_FREE);
5676 ADD_INT(d, DB_LSTAT_HELD);
5677#if (DBVER == 33)
5678 ADD_INT(d, DB_LSTAT_NOGRANT);
5679#endif
5680 ADD_INT(d, DB_LSTAT_PENDING);
5681 ADD_INT(d, DB_LSTAT_WAITING);
5682#endif
5683
5684 ADD_INT(d, DB_ARCH_ABS);
5685 ADD_INT(d, DB_ARCH_DATA);
5686 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005687#if (DBVER >= 42)
5688 ADD_INT(d, DB_ARCH_REMOVE);
5689#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005690
5691 ADD_INT(d, DB_BTREE);
5692 ADD_INT(d, DB_HASH);
5693 ADD_INT(d, DB_RECNO);
5694 ADD_INT(d, DB_QUEUE);
5695 ADD_INT(d, DB_UNKNOWN);
5696
5697 ADD_INT(d, DB_DUP);
5698 ADD_INT(d, DB_DUPSORT);
5699 ADD_INT(d, DB_RECNUM);
5700 ADD_INT(d, DB_RENUMBER);
5701 ADD_INT(d, DB_REVSPLITOFF);
5702 ADD_INT(d, DB_SNAPSHOT);
5703
5704 ADD_INT(d, DB_JOIN_NOSORT);
5705
5706 ADD_INT(d, DB_AFTER);
5707 ADD_INT(d, DB_APPEND);
5708 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005709#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005710 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005711#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005712#if (DBVER >= 41)
5713 _addIntToDict(d, "DB_CHECKPOINT", 0);
5714#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005715 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005716 ADD_INT(d, DB_CURLSN);
5717#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005718#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005719 ADD_INT(d, DB_COMMIT);
5720#endif
5721 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005722 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005723 ADD_INT(d, DB_CURRENT);
5724#if (DBVER >= 33)
5725 ADD_INT(d, DB_FAST_STAT);
5726#endif
5727 ADD_INT(d, DB_FIRST);
5728 ADD_INT(d, DB_FLUSH);
5729 ADD_INT(d, DB_GET_BOTH);
5730 ADD_INT(d, DB_GET_RECNO);
5731 ADD_INT(d, DB_JOIN_ITEM);
5732 ADD_INT(d, DB_KEYFIRST);
5733 ADD_INT(d, DB_KEYLAST);
5734 ADD_INT(d, DB_LAST);
5735 ADD_INT(d, DB_NEXT);
5736 ADD_INT(d, DB_NEXT_DUP);
5737 ADD_INT(d, DB_NEXT_NODUP);
5738 ADD_INT(d, DB_NODUPDATA);
5739 ADD_INT(d, DB_NOOVERWRITE);
5740 ADD_INT(d, DB_NOSYNC);
5741 ADD_INT(d, DB_POSITION);
5742 ADD_INT(d, DB_PREV);
5743 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005744#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005745 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005746#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005747 ADD_INT(d, DB_SET);
5748 ADD_INT(d, DB_SET_RANGE);
5749 ADD_INT(d, DB_SET_RECNO);
5750 ADD_INT(d, DB_WRITECURSOR);
5751
5752 ADD_INT(d, DB_OPFLAGS_MASK);
5753 ADD_INT(d, DB_RMW);
5754#if (DBVER >= 33)
5755 ADD_INT(d, DB_DIRTY_READ);
5756 ADD_INT(d, DB_MULTIPLE);
5757 ADD_INT(d, DB_MULTIPLE_KEY);
5758#endif
5759
Gregory P. Smith29602d22006-01-24 09:46:48 +00005760#if (DBVER >= 44)
5761 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5762 ADD_INT(d, DB_READ_COMMITTED);
5763#endif
5764
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005765#if (DBVER >= 33)
5766 ADD_INT(d, DB_DONOTINDEX);
5767#endif
5768
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005769#if (DBVER >= 41)
5770 _addIntToDict(d, "DB_INCOMPLETE", 0);
5771#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005772 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005773#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005774 ADD_INT(d, DB_KEYEMPTY);
5775 ADD_INT(d, DB_KEYEXIST);
5776 ADD_INT(d, DB_LOCK_DEADLOCK);
5777 ADD_INT(d, DB_LOCK_NOTGRANTED);
5778 ADD_INT(d, DB_NOSERVER);
5779 ADD_INT(d, DB_NOSERVER_HOME);
5780 ADD_INT(d, DB_NOSERVER_ID);
5781 ADD_INT(d, DB_NOTFOUND);
5782 ADD_INT(d, DB_OLD_VERSION);
5783 ADD_INT(d, DB_RUNRECOVERY);
5784 ADD_INT(d, DB_VERIFY_BAD);
5785#if (DBVER >= 33)
5786 ADD_INT(d, DB_PAGE_NOTFOUND);
5787 ADD_INT(d, DB_SECONDARY_BAD);
5788#endif
5789#if (DBVER >= 40)
5790 ADD_INT(d, DB_STAT_CLEAR);
5791 ADD_INT(d, DB_REGION_INIT);
5792 ADD_INT(d, DB_NOLOCKING);
5793 ADD_INT(d, DB_YIELDCPU);
5794 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5795 ADD_INT(d, DB_NOPANIC);
5796#endif
5797
Gregory P. Smith41631e82003-09-21 00:08:14 +00005798#if (DBVER >= 42)
5799 ADD_INT(d, DB_TIME_NOTGRANTED);
5800 ADD_INT(d, DB_TXN_NOT_DURABLE);
5801 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5802 ADD_INT(d, DB_LOG_AUTOREMOVE);
5803 ADD_INT(d, DB_DIRECT_LOG);
5804 ADD_INT(d, DB_DIRECT_DB);
5805 ADD_INT(d, DB_INIT_REP);
5806 ADD_INT(d, DB_ENCRYPT);
5807 ADD_INT(d, DB_CHKSUM);
5808#endif
5809
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005810#if (DBVER >= 43)
5811 ADD_INT(d, DB_LOG_INMEMORY);
5812 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005813 ADD_INT(d, DB_SEQ_DEC);
5814 ADD_INT(d, DB_SEQ_INC);
5815 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005816#endif
5817
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005818#if (DBVER >= 41)
5819 ADD_INT(d, DB_ENCRYPT_AES);
5820 ADD_INT(d, DB_AUTO_COMMIT);
5821#else
5822 /* allow berkeleydb 4.1 aware apps to run on older versions */
5823 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5824#endif
5825
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005826 ADD_INT(d, EINVAL);
5827 ADD_INT(d, EACCES);
5828 ADD_INT(d, ENOSPC);
5829 ADD_INT(d, ENOMEM);
5830 ADD_INT(d, EAGAIN);
5831 ADD_INT(d, EBUSY);
5832 ADD_INT(d, EEXIST);
5833 ADD_INT(d, ENOENT);
5834 ADD_INT(d, EPERM);
5835
Barry Warsaw1baa9822003-03-31 19:51:29 +00005836#if (DBVER >= 40)
5837 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5838 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5839#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005840
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005841 /* The exception name must be correct for pickled exception *
5842 * objects to unpickle properly. */
5843#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5844#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5845#else
5846#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5847#endif
5848
5849 /* All the rest of the exceptions derive only from DBError */
5850#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5851 PyDict_SetItemString(d, #name, name)
5852
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005853 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005854 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5855 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005856
Gregory P. Smithe9477062005-06-04 06:46:59 +00005857 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5858 * from both DBError and KeyError, since the API only supports
5859 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005860 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005861 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5862 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005863 Py_file_input, d, d);
5864 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005865 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005866 PyDict_DelItemString(d, "KeyError");
5867
5868
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005869#if !INCOMPLETE_IS_WARNING
5870 MAKE_EX(DBIncompleteError);
5871#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005872 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005873 MAKE_EX(DBKeyEmptyError);
5874 MAKE_EX(DBKeyExistError);
5875 MAKE_EX(DBLockDeadlockError);
5876 MAKE_EX(DBLockNotGrantedError);
5877 MAKE_EX(DBOldVersionError);
5878 MAKE_EX(DBRunRecoveryError);
5879 MAKE_EX(DBVerifyBadError);
5880 MAKE_EX(DBNoServerError);
5881 MAKE_EX(DBNoServerHomeError);
5882 MAKE_EX(DBNoServerIDError);
5883#if (DBVER >= 33)
5884 MAKE_EX(DBPageNotFoundError);
5885 MAKE_EX(DBSecondaryBadError);
5886#endif
5887
5888 MAKE_EX(DBInvalidArgError);
5889 MAKE_EX(DBAccessError);
5890 MAKE_EX(DBNoSpaceError);
5891 MAKE_EX(DBNoMemoryError);
5892 MAKE_EX(DBAgainError);
5893 MAKE_EX(DBBusyError);
5894 MAKE_EX(DBFileExistsError);
5895 MAKE_EX(DBNoSuchFileError);
5896 MAKE_EX(DBPermissionsError);
5897
5898#undef MAKE_EX
5899
Gregory P. Smith39250532007-10-09 06:02:21 +00005900 /* Initiliase the C API structure and add it to the module */
5901 bsddb_api.db_type = &DB_Type;
5902 bsddb_api.dbcursor_type = &DBCursor_Type;
5903 bsddb_api.dbenv_type = &DBEnv_Type;
5904 bsddb_api.dbtxn_type = &DBTxn_Type;
5905 bsddb_api.dblock_type = &DBLock_Type;
5906 bsddb_api.dbsequence_type = &DBSequence_Type;
5907 bsddb_api.makeDBError = makeDBError;
5908
5909 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5910 PyDict_SetItemString(d, "api", py_api);
5911 Py_DECREF(py_api);
5912
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005913 /* Check for errors */
5914 if (PyErr_Occurred()) {
5915 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005916 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005917 }
5918}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005919
5920/* allow this module to be named _pybsddb so that it can be installed
5921 * and imported on top of python >= 2.3 that includes its own older
5922 * copy of the library named _bsddb without importing the old version. */
5923DL_EXPORT(void) init_pybsddb(void)
5924{
5925 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5926 init_bsddb();
5927}