blob: 95ccb438dd6ecc462b8eab10623ee8db4bdca1a7 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Gregory P. Smithf8057852007-09-09 20:25:00 +000051 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000052 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000100#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000101typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000102#endif
103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Gregory P. Smith39250532007-10-09 06:02:21 +0000194#if PYTHON_API_VERSION < 1010
195#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000196#endif
197
Gregory P. Smith31c50652004-06-28 01:20:40 +0000198
Gregory P. Smith39250532007-10-09 06:02:21 +0000199/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000200#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000201#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000202
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203
204staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
205
Martin v. Löwis68192102007-07-21 06:55:02 +0000206#define DBObject_Check(v) (Py_Type(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_Type(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_Type(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_Type(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_Type(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000211#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +0000212#define DBSequenceObject_Check(v) (Py_Type(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
254#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000255 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000256
257
258static int makeDBError(int err);
259
260
261/* Return the access method type of the DBObject */
262static int _DB_get_type(DBObject* self)
263{
264#if (DBVER >= 33)
265 DBTYPE type;
266 int err;
267 err = self->db->get_type(self->db, &type);
268 if (makeDBError(err)) {
269 return -1;
270 }
271 return type;
272#else
273 return self->db->get_type(self->db);
274#endif
275}
276
277
278/* Create a DBT structure (containing key and data values) from Python
279 strings. Returns 1 on success, 0 on an error. */
280static int make_dbt(PyObject* obj, DBT* dbt)
281{
282 CLEAR_DBT(*dbt);
283 if (obj == Py_None) {
284 /* no need to do anything, the structure has already been zeroed */
285 }
286 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
287 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000288 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000289 return 0;
290 }
291 return 1;
292}
293
294
295/* Recno and Queue DBs can have integer keys. This function figures out
296 what's been given, verifies that it's allowed, and then makes the DBT.
297
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000298 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000299static int
300make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301{
302 db_recno_t recno;
303 int type;
304
305 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000306 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000307 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000308 if (type == -1)
309 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000310 if (type == DB_RECNO || type == DB_QUEUE) {
311 PyErr_SetString(
312 PyExc_TypeError,
313 "None keys not allowed for Recno and Queue DB's");
314 return 0;
315 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000316 /* no need to do anything, the structure has already been zeroed */
317 }
318
319 else if (PyString_Check(keyobj)) {
320 /* verify access method type */
321 type = _DB_get_type(self);
322 if (type == -1)
323 return 0;
324 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000325 PyErr_SetString(
326 PyExc_TypeError,
327 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000328 return 0;
329 }
330
Gregory P. Smith10bed542007-10-09 06:50:43 +0000331 /*
332 * NOTE(gps): I don't like doing a data copy here, it seems
333 * wasteful. But without a clean way to tell FREE_DBT if it
334 * should free key->data or not we have to. Other places in
335 * the code check for DB_THREAD and forceably set DBT_MALLOC
336 * when we otherwise would leave flags 0 to indicate that.
337 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000338 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000339 if (key->data == NULL) {
340 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
341 return 0;
342 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000343 memcpy(key->data, PyString_AS_STRING(keyobj),
344 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000345 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346 key->size = PyString_GET_SIZE(keyobj);
347 }
348
349 else if (PyInt_Check(keyobj)) {
350 /* verify access method type */
351 type = _DB_get_type(self);
352 if (type == -1)
353 return 0;
354 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000355 /* if BTREE then an Integer key is allowed with the
356 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000357 *pflags |= DB_SET_RECNO;
358 }
359 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000360 PyErr_SetString(
361 PyExc_TypeError,
362 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000363 return 0;
364 }
365
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000366 /* Make a key out of the requested recno, use allocated space so DB
367 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000368 recno = PyInt_AS_LONG(keyobj);
369 key->data = malloc(sizeof(db_recno_t));
370 if (key->data == NULL) {
371 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
372 return 0;
373 }
374 key->ulen = key->size = sizeof(db_recno_t);
375 memcpy(key->data, &recno, sizeof(db_recno_t));
376 key->flags = DB_DBT_REALLOC;
377 }
378 else {
379 PyErr_Format(PyExc_TypeError,
380 "String or Integer object expected for key, %s found",
Martin v. Löwis68192102007-07-21 06:55:02 +0000381 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382 return 0;
383 }
384
385 return 1;
386}
387
388
389/* Add partial record access to an existing DBT data struct.
390 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
391 and the data storage/retrieval will be done using dlen and doff. */
392static int add_partial_dbt(DBT* d, int dlen, int doff) {
393 /* if neither were set we do nothing (-1 is the default value) */
394 if ((dlen == -1) && (doff == -1)) {
395 return 1;
396 }
397
398 if ((dlen < 0) || (doff < 0)) {
399 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
400 return 0;
401 }
402
403 d->flags = d->flags | DB_DBT_PARTIAL;
404 d->dlen = (unsigned int) dlen;
405 d->doff = (unsigned int) doff;
406 return 1;
407}
408
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000409/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
410/* TODO: make this use the native libc strlcpy() when available (BSD) */
411unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
412{
413 unsigned int srclen, copylen;
414
415 srclen = strlen(src);
416 if (n <= 0)
417 return srclen;
418 copylen = (srclen > n-1) ? n-1 : srclen;
419 /* populate dest[0] thru dest[copylen-1] */
420 memcpy(dest, src, copylen);
421 /* guarantee null termination */
422 dest[copylen] = 0;
423
424 return srclen;
425}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000426
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000427/* Callback used to save away more information about errors from the DB
428 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000429static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000430#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000432#else
433static void _db_errorCallback(const DB_ENV *db_env,
434 const char* prefix, const char* msg)
435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000436{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000437 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000438}
439
440
441/* make a nice exception object to raise for errors. */
442static int makeDBError(int err)
443{
444 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000445 PyObject *errObj = NULL;
446 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000448 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000449
450 switch (err) {
451 case 0: /* successful, no error */ break;
452
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000453#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 case DB_INCOMPLETE:
455#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000456 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
457 /* Ensure that bytes_left never goes negative */
458 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
459 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
460 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000462 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000463 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000464 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000466
467#else /* do an exception instead */
468 errObj = DBIncompleteError;
469#endif
470 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000471#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000472
473 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
474 case DB_KEYEXIST: errObj = DBKeyExistError; break;
475 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
476 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
477 case DB_NOTFOUND: errObj = DBNotFoundError; break;
478 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
479 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
480 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
481 case DB_NOSERVER: errObj = DBNoServerError; break;
482 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
483 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
484#if (DBVER >= 33)
485 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
486 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
487#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000488 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000489
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000490#if (DBVER >= 43)
491 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
492 case ENOMEM: errObj = PyExc_MemoryError; break;
493#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000494 case EINVAL: errObj = DBInvalidArgError; break;
495 case EACCES: errObj = DBAccessError; break;
496 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000497 case EAGAIN: errObj = DBAgainError; break;
498 case EBUSY : errObj = DBBusyError; break;
499 case EEXIST: errObj = DBFileExistsError; break;
500 case ENOENT: errObj = DBNoSuchFileError; break;
501 case EPERM : errObj = DBPermissionsError; break;
502
503 default: errObj = DBError; break;
504 }
505
506 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000507 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
508 /* Ensure that bytes_left never goes negative */
509 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
510 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
511 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000513 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000515 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000516
517 errTuple = Py_BuildValue("(is)", err, errTxt);
518 PyErr_SetObject(errObj, errTuple);
519 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520 }
521
522 return ((errObj != NULL) || exceptionRaised);
523}
524
525
526
527/* set a type exception */
528static void makeTypeError(char* expected, PyObject* found)
529{
530 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis68192102007-07-21 06:55:02 +0000531 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532}
533
534
535/* verify that an obj is either None or a DBTxn, and set the txn pointer */
536static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
537{
538 if (txnobj == Py_None || txnobj == NULL) {
539 *txn = NULL;
540 return 1;
541 }
542 if (DBTxnObject_Check(txnobj)) {
543 *txn = ((DBTxnObject*)txnobj)->txn;
544 return 1;
545 }
546 else
547 makeTypeError("DBTxn", txnobj);
548 return 0;
549}
550
551
552/* Delete a key from a database
553 Returns 0 on success, -1 on an error. */
554static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
555{
556 int err;
557
558 MYDB_BEGIN_ALLOW_THREADS;
559 err = self->db->del(self->db, txn, key, 0);
560 MYDB_END_ALLOW_THREADS;
561 if (makeDBError(err)) {
562 return -1;
563 }
564 self->haveStat = 0;
565 return 0;
566}
567
568
569/* Store a key into a database
570 Returns 0 on success, -1 on an error. */
571static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
572{
573 int err;
574
575 MYDB_BEGIN_ALLOW_THREADS;
576 err = self->db->put(self->db, txn, key, data, flags);
577 MYDB_END_ALLOW_THREADS;
578 if (makeDBError(err)) {
579 return -1;
580 }
581 self->haveStat = 0;
582 return 0;
583}
584
585/* Get a key/data pair from a cursor */
586static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
587 PyObject *args, PyObject *kwargs, char *format)
588{
589 int err;
590 PyObject* retval = NULL;
591 DBT key, data;
592 int dlen = -1;
593 int doff = -1;
594 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000595 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596
597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
598 &flags, &dlen, &doff))
599 return NULL;
600
601 CHECK_CURSOR_NOT_CLOSED(self);
602
603 flags |= extra_flags;
604 CLEAR_DBT(key);
605 CLEAR_DBT(data);
606 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
607 /* Tell BerkeleyDB to malloc the return value (thread safe) */
608 data.flags = DB_DBT_MALLOC;
609 key.flags = DB_DBT_MALLOC;
610 }
611 if (!add_partial_dbt(&data, dlen, doff))
612 return NULL;
613
614 MYDB_BEGIN_ALLOW_THREADS;
615 err = self->dbc->c_get(self->dbc, &key, &data, flags);
616 MYDB_END_ALLOW_THREADS;
617
Gregory P. Smithe9477062005-06-04 06:46:59 +0000618 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
619 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620 Py_INCREF(Py_None);
621 retval = Py_None;
622 }
623 else if (makeDBError(err)) {
624 retval = NULL;
625 }
626 else { /* otherwise, success! */
627
628 /* if Recno or Queue, return the key as an Int */
629 switch (_DB_get_type(self->mydb)) {
630 case -1:
631 retval = NULL;
632 break;
633
634 case DB_RECNO:
635 case DB_QUEUE:
636 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
637 data.data, data.size);
638 break;
639 case DB_HASH:
640 case DB_BTREE:
641 default:
642 retval = Py_BuildValue("s#s#", key.data, key.size,
643 data.data, data.size);
644 break;
645 }
646 }
647 if (!err) {
648 FREE_DBT(key);
649 FREE_DBT(data);
650 }
651 return retval;
652}
653
654
655/* add an integer to a dictionary using the given name as a key */
656static void _addIntToDict(PyObject* dict, char *name, int value)
657{
658 PyObject* v = PyInt_FromLong((long) value);
659 if (!v || PyDict_SetItemString(dict, name, v))
660 PyErr_Clear();
661
662 Py_XDECREF(v);
663}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000664
665/* The same, when the value is a time_t */
666static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
667{
668 PyObject* v;
669 /* if the value fits in regular int, use that. */
670#ifdef HAVE_LONG_LONG
671 if (sizeof(time_t) > sizeof(long))
672 v = PyLong_FromLongLong((PY_LONG_LONG) value);
673 else
674#endif
675 v = PyInt_FromLong((long) value);
676 if (!v || PyDict_SetItemString(dict, name, v))
677 PyErr_Clear();
678
679 Py_XDECREF(v);
680}
681
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000682#if (DBVER >= 43)
683/* add an db_seq_t to a dictionary using the given name as a key */
684static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
685{
686 PyObject* v = PyLong_FromLongLong(value);
687 if (!v || PyDict_SetItemString(dict, name, v))
688 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000690 Py_XDECREF(v);
691}
692#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000693
694
695
696/* --------------------------------------------------------------------- */
697/* Allocators and deallocators */
698
699static DBObject*
700newDBObject(DBEnvObject* arg, int flags)
701{
702 DBObject* self;
703 DB_ENV* db_env = NULL;
704 int err;
705
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000707 if (self == NULL)
708 return NULL;
709
710 self->haveStat = 0;
711 self->flags = 0;
712 self->setflags = 0;
713 self->myenvobj = NULL;
714#if (DBVER >= 33)
715 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000716 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000717 self->primaryDBType = 0;
718#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000719 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720
721 /* keep a reference to our python DBEnv object */
722 if (arg) {
723 Py_INCREF(arg);
724 self->myenvobj = arg;
725 db_env = arg->db_env;
726 }
727
728 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000729 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000730 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000731 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
732 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000733
734 MYDB_BEGIN_ALLOW_THREADS;
735 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000736 if (self->db != NULL) {
737 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000739 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000740#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000741 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000743 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
744 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000745 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000746 if (makeDBError(err)) {
747 if (self->myenvobj) {
748 Py_DECREF(self->myenvobj);
749 self->myenvobj = NULL;
750 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000751 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 self = NULL;
753 }
754 return self;
755}
756
757
758static void
759DB_dealloc(DBObject* self)
760{
761 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000762 /* avoid closing a DB when its DBEnv has been closed out from under
763 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000764 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000765 (self->myenvobj && self->myenvobj->db_env))
766 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000767 MYDB_BEGIN_ALLOW_THREADS;
768 self->db->close(self->db, 0);
769 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770 } else {
771 PyErr_Warn(PyExc_RuntimeWarning,
772 "DB could not be closed in destructor: DBEnv already closed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773 }
774 self->db = NULL;
775 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000776 if (self->in_weakreflist != NULL) {
777 PyObject_ClearWeakRefs((PyObject *) self);
778 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000779 if (self->myenvobj) {
780 Py_DECREF(self->myenvobj);
781 self->myenvobj = NULL;
782 }
783#if (DBVER >= 33)
784 if (self->associateCallback != NULL) {
785 Py_DECREF(self->associateCallback);
786 self->associateCallback = NULL;
787 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000788 if (self->btCompareCallback != NULL) {
789 Py_DECREF(self->btCompareCallback);
790 self->btCompareCallback = NULL;
791 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794}
795
796
797static DBCursorObject*
798newDBCursorObject(DBC* dbc, DBObject* db)
799{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000800 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000801 if (self == NULL)
802 return NULL;
803
804 self->dbc = dbc;
805 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000806 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000807 Py_INCREF(self->mydb);
808 return self;
809}
810
811
812static void
813DBCursor_dealloc(DBCursorObject* self)
814{
815 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000816
Gregory P. Smitha703a212003-11-03 01:04:41 +0000817 if (self->in_weakreflist != NULL) {
818 PyObject_ClearWeakRefs((PyObject *) self);
819 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000820
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821 if (self->dbc != NULL) {
822 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000823 /* If the underlying database has been closed, we don't
824 need to do anything. If the environment has been closed
825 we need to leak, as BerkeleyDB will crash trying to access
826 the environment. There was an exception when the
827 user closed the environment even though there still was
828 a database open. */
829 if (self->mydb->db && self->mydb->myenvobj &&
830 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000831 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 self->dbc = NULL;
833 MYDB_END_ALLOW_THREADS;
834 }
835 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000837}
838
839
840static DBEnvObject*
841newDBEnvObject(int flags)
842{
843 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000844 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000845 if (self == NULL)
846 return NULL;
847
848 self->closed = 1;
849 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000850 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
851 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000852 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853
854 MYDB_BEGIN_ALLOW_THREADS;
855 err = db_env_create(&self->db_env, flags);
856 MYDB_END_ALLOW_THREADS;
857 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000858 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 self = NULL;
860 }
861 else {
862 self->db_env->set_errcall(self->db_env, _db_errorCallback);
863 }
864 return self;
865}
866
867
868static void
869DBEnv_dealloc(DBEnvObject* self)
870{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000871 if (self->in_weakreflist != NULL) {
872 PyObject_ClearWeakRefs((PyObject *) self);
873 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000874
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000875 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876 MYDB_BEGIN_ALLOW_THREADS;
877 self->db_env->close(self->db_env, 0);
878 MYDB_END_ALLOW_THREADS;
879 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000880 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881}
882
883
884static DBTxnObject*
885newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
886{
887 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000888 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 if (self == NULL)
890 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000891 Py_INCREF(myenv);
892 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000893 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894
895 MYDB_BEGIN_ALLOW_THREADS;
896#if (DBVER >= 40)
897 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
898#else
899 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
900#endif
901 MYDB_END_ALLOW_THREADS;
902 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000903 Py_DECREF(self->env);
904 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905 self = NULL;
906 }
907 return self;
908}
909
910
911static void
912DBTxn_dealloc(DBTxnObject* self)
913{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000914 if (self->in_weakreflist != NULL) {
915 PyObject_ClearWeakRefs((PyObject *) self);
916 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917
Gregory P. Smith31c50652004-06-28 01:20:40 +0000918 if (self->txn) {
919 /* it hasn't been finalized, abort it! */
920 MYDB_BEGIN_ALLOW_THREADS;
921#if (DBVER >= 40)
922 self->txn->abort(self->txn);
923#else
924 txn_abort(self->txn);
925#endif
926 MYDB_END_ALLOW_THREADS;
927 PyErr_Warn(PyExc_RuntimeWarning,
928 "DBTxn aborted in destructor. No prior commit() or abort().");
929 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930
Neal Norwitz62a21122006-01-25 05:21:55 +0000931 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000933}
934
935
936static DBLockObject*
937newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
938 db_lockmode_t lock_mode, int flags)
939{
940 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000941 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 if (self == NULL)
943 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000944 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945
946 MYDB_BEGIN_ALLOW_THREADS;
947#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000948 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
949 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000950#else
951 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
952#endif
953 MYDB_END_ALLOW_THREADS;
954 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000955 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956 self = NULL;
957 }
958
959 return self;
960}
961
962
963static void
964DBLock_dealloc(DBLockObject* self)
965{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000966 if (self->in_weakreflist != NULL) {
967 PyObject_ClearWeakRefs((PyObject *) self);
968 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000969 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972}
973
974
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000975#if (DBVER >= 43)
976static DBSequenceObject*
977newDBSequenceObject(DBObject* mydb, int flags)
978{
979 int err;
980 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
981 if (self == NULL)
982 return NULL;
983 Py_INCREF(mydb);
984 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000985 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000986
987
988 MYDB_BEGIN_ALLOW_THREADS;
989 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
990 MYDB_END_ALLOW_THREADS;
991 if (makeDBError(err)) {
992 Py_DECREF(self->mydb);
993 PyObject_Del(self);
994 self = NULL;
995 }
996
997 return self;
998}
999
1000
1001static void
1002DBSequence_dealloc(DBSequenceObject* self)
1003{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001004 if (self->in_weakreflist != NULL) {
1005 PyObject_ClearWeakRefs((PyObject *) self);
1006 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001007
1008 Py_DECREF(self->mydb);
1009 PyObject_Del(self);
1010}
1011#endif
1012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013/* --------------------------------------------------------------------- */
1014/* DB methods */
1015
1016static PyObject*
1017DB_append(DBObject* self, PyObject* args)
1018{
1019 PyObject* txnobj = NULL;
1020 PyObject* dataobj;
1021 db_recno_t recno;
1022 DBT key, data;
1023 DB_TXN *txn = NULL;
1024
Georg Brandl96a8c392006-05-29 21:04:52 +00001025 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 return NULL;
1027
1028 CHECK_DB_NOT_CLOSED(self);
1029
1030 /* make a dummy key out of a recno */
1031 recno = 0;
1032 CLEAR_DBT(key);
1033 key.data = &recno;
1034 key.size = sizeof(recno);
1035 key.ulen = key.size;
1036 key.flags = DB_DBT_USERMEM;
1037
1038 if (!make_dbt(dataobj, &data)) return NULL;
1039 if (!checkTxnObj(txnobj, &txn)) return NULL;
1040
1041 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1042 return NULL;
1043
1044 return PyInt_FromLong(recno);
1045}
1046
1047
1048#if (DBVER >= 33)
1049
1050static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001051_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1052 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001053{
1054 int retval = DB_DONOTINDEX;
1055 DBObject* secondaryDB = (DBObject*)db->app_private;
1056 PyObject* callback = secondaryDB->associateCallback;
1057 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001059 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060
1061
1062 if (callback != NULL) {
1063 MYDB_BEGIN_BLOCK_THREADS;
1064
Thomas Woutersb3153832006-03-08 01:47:19 +00001065 if (type == DB_RECNO || type == DB_QUEUE)
1066 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1067 priData->data, priData->size);
1068 else
1069 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1070 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001071 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001072 result = PyEval_CallObject(callback, args);
1073 }
1074 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001075 PyErr_Print();
1076 }
1077 else if (result == Py_None) {
1078 retval = DB_DONOTINDEX;
1079 }
1080 else if (PyInt_Check(result)) {
1081 retval = PyInt_AsLong(result);
1082 }
1083 else if (PyString_Check(result)) {
1084 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001085 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086
1087 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001088 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001089 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1090 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001091 if (secKey->data) {
1092 memcpy(secKey->data, data, size);
1093 secKey->size = size;
1094 retval = 0;
1095 }
1096 else {
1097 PyErr_SetString(PyExc_MemoryError,
1098 "malloc failed in _db_associateCallback");
1099 PyErr_Print();
1100 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001101 }
1102 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001103 PyErr_SetString(
1104 PyExc_TypeError,
1105 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106 PyErr_Print();
1107 }
1108
Thomas Woutersb3153832006-03-08 01:47:19 +00001109 Py_XDECREF(args);
1110 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111
1112 MYDB_END_BLOCK_THREADS;
1113 }
1114 return retval;
1115}
1116
1117
1118static PyObject*
1119DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1120{
1121 int err, flags=0;
1122 DBObject* secondaryDB;
1123 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001124#if (DBVER >= 41)
1125 PyObject *txnobj = NULL;
1126 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001127 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001128 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001129#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001130 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001131#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001133#if (DBVER >= 41)
1134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1135 &secondaryDB, &callback, &flags,
1136 &txnobj)) {
1137#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001138 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001139 &secondaryDB, &callback, &flags)) {
1140#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001141 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001142 }
1143
1144#if (DBVER >= 41)
1145 if (!checkTxnObj(txnobj, &txn)) return NULL;
1146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147
1148 CHECK_DB_NOT_CLOSED(self);
1149 if (!DBObject_Check(secondaryDB)) {
1150 makeTypeError("DB", (PyObject*)secondaryDB);
1151 return NULL;
1152 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001153 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154 if (callback == Py_None) {
1155 callback = NULL;
1156 }
1157 else if (!PyCallable_Check(callback)) {
1158 makeTypeError("Callable", callback);
1159 return NULL;
1160 }
1161
1162 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001163 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001164 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001165 secondaryDB->associateCallback = callback;
1166 secondaryDB->primaryDBType = _DB_get_type(self);
1167
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001168 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1169 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1170 * The global interepreter lock is not initialized until the first
1171 * thread is created using thread.start_new_thread() or fork() is
1172 * called. that would cause the ALLOW_THREADS here to segfault due
1173 * to a null pointer reference if no threads or child processes
1174 * have been created. This works around that and is a no-op if
1175 * threads have already been initialized.
1176 * (see pybsddb-users mailing list post on 2002-08-07)
1177 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001178#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001179 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001180#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001182#if (DBVER >= 41)
1183 err = self->db->associate(self->db,
1184 txn,
1185 secondaryDB->db,
1186 _db_associateCallback,
1187 flags);
1188#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001189 err = self->db->associate(self->db,
1190 secondaryDB->db,
1191 _db_associateCallback,
1192 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001194 MYDB_END_ALLOW_THREADS;
1195
1196 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001197 Py_XDECREF(secondaryDB->associateCallback);
1198 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001199 secondaryDB->primaryDBType = 0;
1200 }
1201
1202 RETURN_IF_ERR();
1203 RETURN_NONE();
1204}
1205
1206
1207#endif
1208
1209
1210static PyObject*
1211DB_close(DBObject* self, PyObject* args)
1212{
1213 int err, flags=0;
1214 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1215 return NULL;
1216 if (self->db != NULL) {
1217 if (self->myenvobj)
1218 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001220 self->db = NULL;
1221 RETURN_IF_ERR();
1222 }
1223 RETURN_NONE();
1224}
1225
1226
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227static PyObject*
1228_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1229{
1230 int err, flags=0, type;
1231 PyObject* txnobj = NULL;
1232 PyObject* retval = NULL;
1233 DBT key, data;
1234 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001235 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236
1237 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1238 &txnobj, &flags))
1239 return NULL;
1240
1241 CHECK_DB_NOT_CLOSED(self);
1242 type = _DB_get_type(self);
1243 if (type == -1)
1244 return NULL;
1245 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001246 PyErr_SetString(PyExc_TypeError,
1247 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001248 return NULL;
1249 }
1250 if (!checkTxnObj(txnobj, &txn))
1251 return NULL;
1252
1253 CLEAR_DBT(key);
1254 CLEAR_DBT(data);
1255 if (CHECK_DBFLAG(self, DB_THREAD)) {
1256 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1257 data.flags = DB_DBT_MALLOC;
1258 key.flags = DB_DBT_MALLOC;
1259 }
1260
1261 MYDB_BEGIN_ALLOW_THREADS;
1262 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1263 MYDB_END_ALLOW_THREADS;
1264
Gregory P. Smithe9477062005-06-04 06:46:59 +00001265 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1266 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001267 err = 0;
1268 Py_INCREF(Py_None);
1269 retval = Py_None;
1270 }
1271 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001272 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1273 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001274 FREE_DBT(key);
1275 FREE_DBT(data);
1276 }
1277
1278 RETURN_IF_ERR();
1279 return retval;
1280}
1281
1282static PyObject*
1283DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1284{
1285 return _DB_consume(self, args, kwargs, DB_CONSUME);
1286}
1287
1288static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001289DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1290 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291{
1292 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1293}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294
1295
1296static PyObject*
1297DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1298{
1299 int err, flags=0;
1300 DBC* dbc;
1301 PyObject* txnobj = NULL;
1302 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001303 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001304
1305 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1306 &txnobj, &flags))
1307 return NULL;
1308 CHECK_DB_NOT_CLOSED(self);
1309 if (!checkTxnObj(txnobj, &txn))
1310 return NULL;
1311
1312 MYDB_BEGIN_ALLOW_THREADS;
1313 err = self->db->cursor(self->db, txn, &dbc, flags);
1314 MYDB_END_ALLOW_THREADS;
1315 RETURN_IF_ERR();
1316 return (PyObject*) newDBCursorObject(dbc, self);
1317}
1318
1319
1320static PyObject*
1321DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1322{
1323 PyObject* txnobj = NULL;
1324 int flags = 0;
1325 PyObject* keyobj;
1326 DBT key;
1327 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001328 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001329
1330 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1331 &keyobj, &txnobj, &flags))
1332 return NULL;
1333 CHECK_DB_NOT_CLOSED(self);
1334 if (!make_key_dbt(self, keyobj, &key, NULL))
1335 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001336 if (!checkTxnObj(txnobj, &txn)) {
1337 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001339 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001341 if (-1 == _DB_delete(self, txn, &key, 0)) {
1342 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001344 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345
1346 FREE_DBT(key);
1347 RETURN_NONE();
1348}
1349
1350
1351static PyObject*
1352DB_fd(DBObject* self, PyObject* args)
1353{
1354 int err, the_fd;
1355
1356 if (!PyArg_ParseTuple(args,":fd"))
1357 return NULL;
1358 CHECK_DB_NOT_CLOSED(self);
1359
1360 MYDB_BEGIN_ALLOW_THREADS;
1361 err = self->db->fd(self->db, &the_fd);
1362 MYDB_END_ALLOW_THREADS;
1363 RETURN_IF_ERR();
1364 return PyInt_FromLong(the_fd);
1365}
1366
1367
1368static PyObject*
1369DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1370{
1371 int err, flags=0;
1372 PyObject* txnobj = NULL;
1373 PyObject* keyobj;
1374 PyObject* dfltobj = NULL;
1375 PyObject* retval = NULL;
1376 int dlen = -1;
1377 int doff = -1;
1378 DBT key, data;
1379 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001380 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001381 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001382
1383 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001384 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1385 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386 return NULL;
1387
1388 CHECK_DB_NOT_CLOSED(self);
1389 if (!make_key_dbt(self, keyobj, &key, &flags))
1390 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001391 if (!checkTxnObj(txnobj, &txn)) {
1392 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001394 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001395
1396 CLEAR_DBT(data);
1397 if (CHECK_DBFLAG(self, DB_THREAD)) {
1398 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1399 data.flags = DB_DBT_MALLOC;
1400 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001401 if (!add_partial_dbt(&data, dlen, doff)) {
1402 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001404 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405
1406 MYDB_BEGIN_ALLOW_THREADS;
1407 err = self->db->get(self->db, txn, &key, &data, flags);
1408 MYDB_END_ALLOW_THREADS;
1409
Gregory P. Smithe9477062005-06-04 06:46:59 +00001410 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 err = 0;
1412 Py_INCREF(dfltobj);
1413 retval = dfltobj;
1414 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001415 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1416 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001417 err = 0;
1418 Py_INCREF(Py_None);
1419 retval = Py_None;
1420 }
1421 else if (!err) {
1422 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001423 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1424 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425 else /* return just the data */
1426 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 FREE_DBT(data);
1428 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001429 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001430
1431 RETURN_IF_ERR();
1432 return retval;
1433}
1434
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001435#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001436static PyObject*
1437DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1438{
1439 int err, flags=0;
1440 PyObject* txnobj = NULL;
1441 PyObject* keyobj;
1442 PyObject* dfltobj = NULL;
1443 PyObject* retval = NULL;
1444 int dlen = -1;
1445 int doff = -1;
1446 DBT key, pkey, data;
1447 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001448 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001449 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001450
1451 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1452 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1453 &doff))
1454 return NULL;
1455
1456 CHECK_DB_NOT_CLOSED(self);
1457 if (!make_key_dbt(self, keyobj, &key, &flags))
1458 return NULL;
1459 if (!checkTxnObj(txnobj, &txn)) {
1460 FREE_DBT(key);
1461 return NULL;
1462 }
1463
1464 CLEAR_DBT(data);
1465 if (CHECK_DBFLAG(self, DB_THREAD)) {
1466 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1467 data.flags = DB_DBT_MALLOC;
1468 }
1469 if (!add_partial_dbt(&data, dlen, doff)) {
1470 FREE_DBT(key);
1471 return NULL;
1472 }
1473
1474 CLEAR_DBT(pkey);
1475 pkey.flags = DB_DBT_MALLOC;
1476
1477 MYDB_BEGIN_ALLOW_THREADS;
1478 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1479 MYDB_END_ALLOW_THREADS;
1480
Gregory P. Smithe9477062005-06-04 06:46:59 +00001481 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001482 err = 0;
1483 Py_INCREF(dfltobj);
1484 retval = dfltobj;
1485 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001486 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1487 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001488 err = 0;
1489 Py_INCREF(Py_None);
1490 retval = Py_None;
1491 }
1492 else if (!err) {
1493 PyObject *pkeyObj;
1494 PyObject *dataObj;
1495 dataObj = PyString_FromStringAndSize(data.data, data.size);
1496
1497 if (self->primaryDBType == DB_RECNO ||
1498 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001499 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001500 else
1501 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1502
1503 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1504 {
1505 PyObject *keyObj;
1506 int type = _DB_get_type(self);
1507 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001508 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001509 else
1510 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001511#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001512 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001513#else
1514 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1515#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001516 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001517 }
1518 else /* return just the pkey and data */
1519 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001520#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001521 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001522#else
1523 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1524#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001525 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001526 Py_DECREF(dataObj);
1527 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001528 FREE_DBT(pkey);
1529 FREE_DBT(data);
1530 }
1531 FREE_DBT(key);
1532
1533 RETURN_IF_ERR();
1534 return retval;
1535}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001536#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001537
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001538
1539/* Return size of entry */
1540static PyObject*
1541DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1542{
1543 int err, flags=0;
1544 PyObject* txnobj = NULL;
1545 PyObject* keyobj;
1546 PyObject* retval = NULL;
1547 DBT key, data;
1548 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001549 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550
1551 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1552 &keyobj, &txnobj))
1553 return NULL;
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001559 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001560 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001561 CLEAR_DBT(data);
1562
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001563 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1564 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001565 data.flags = DB_DBT_USERMEM;
1566 data.ulen = 0;
1567 MYDB_BEGIN_ALLOW_THREADS;
1568 err = self->db->get(self->db, txn, &key, &data, flags);
1569 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001570 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001571 retval = PyInt_FromLong((long)data.size);
1572 err = 0;
1573 }
1574
1575 FREE_DBT(key);
1576 FREE_DBT(data);
1577 RETURN_IF_ERR();
1578 return retval;
1579}
1580
1581
1582static PyObject*
1583DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1584{
1585 int err, flags=0;
1586 PyObject* txnobj = NULL;
1587 PyObject* keyobj;
1588 PyObject* dataobj;
1589 PyObject* retval = NULL;
1590 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001591 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001592 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001593 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001594
1595
1596 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1597 &keyobj, &dataobj, &txnobj, &flags))
1598 return NULL;
1599
1600 CHECK_DB_NOT_CLOSED(self);
1601 if (!make_key_dbt(self, keyobj, &key, NULL))
1602 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001603 if ( !make_dbt(dataobj, &data) ||
1604 !checkTxnObj(txnobj, &txn) )
1605 {
1606 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001607 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001608 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001609
1610 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001611 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001612
1613 if (CHECK_DBFLAG(self, DB_THREAD)) {
1614 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001615 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001616 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617 }
1618
1619 MYDB_BEGIN_ALLOW_THREADS;
1620 err = self->db->get(self->db, txn, &key, &data, flags);
1621 MYDB_END_ALLOW_THREADS;
1622
Gregory P. Smithe9477062005-06-04 06:46:59 +00001623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1624 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001625 err = 0;
1626 Py_INCREF(Py_None);
1627 retval = Py_None;
1628 }
1629 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001630 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001632
1633 /* Even though the flags require DB_DBT_MALLOC, data is not always
1634 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1635 if (data.data != orig_data)
1636 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637 }
1638
1639 FREE_DBT(key);
1640 RETURN_IF_ERR();
1641 return retval;
1642}
1643
1644
1645static PyObject*
1646DB_get_byteswapped(DBObject* self, PyObject* args)
1647{
1648#if (DBVER >= 33)
1649 int err = 0;
1650#endif
1651 int retval = -1;
1652
1653 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1654 return NULL;
1655 CHECK_DB_NOT_CLOSED(self);
1656
1657#if (DBVER >= 33)
1658 MYDB_BEGIN_ALLOW_THREADS;
1659 err = self->db->get_byteswapped(self->db, &retval);
1660 MYDB_END_ALLOW_THREADS;
1661 RETURN_IF_ERR();
1662#else
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 retval = self->db->get_byteswapped(self->db);
1665 MYDB_END_ALLOW_THREADS;
1666#endif
1667 return PyInt_FromLong(retval);
1668}
1669
1670
1671static PyObject*
1672DB_get_type(DBObject* self, PyObject* args)
1673{
1674 int type;
1675
1676 if (!PyArg_ParseTuple(args,":get_type"))
1677 return NULL;
1678 CHECK_DB_NOT_CLOSED(self);
1679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001680 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001681 if (type == -1)
1682 return NULL;
1683 return PyInt_FromLong(type);
1684}
1685
1686
1687static PyObject*
1688DB_join(DBObject* self, PyObject* args)
1689{
1690 int err, flags=0;
1691 int length, x;
1692 PyObject* cursorsObj;
1693 DBC** cursors;
1694 DBC* dbc;
1695
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1697 return NULL;
1698
1699 CHECK_DB_NOT_CLOSED(self);
1700
1701 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001702 PyErr_SetString(PyExc_TypeError,
1703 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
1705 }
1706
1707 length = PyObject_Length(cursorsObj);
1708 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001709 if (!cursors) {
1710 PyErr_NoMemory();
1711 return NULL;
1712 }
1713
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 cursors[length] = NULL;
1715 for (x=0; x<length; x++) {
1716 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001717 if (item == NULL) {
1718 free(cursors);
1719 return NULL;
1720 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001722 PyErr_SetString(PyExc_TypeError,
1723 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001724 free(cursors);
1725 return NULL;
1726 }
1727 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001728 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729 }
1730
1731 MYDB_BEGIN_ALLOW_THREADS;
1732 err = self->db->join(self->db, cursors, &dbc, flags);
1733 MYDB_END_ALLOW_THREADS;
1734 free(cursors);
1735 RETURN_IF_ERR();
1736
Gregory P. Smith7441e652003-11-03 21:35:31 +00001737 /* FIXME: this is a buggy interface. The returned cursor
1738 contains internal references to the passed in cursors
1739 but does not hold python references to them or prevent
1740 them from being closed prematurely. This can cause
1741 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 return (PyObject*) newDBCursorObject(dbc, self);
1743}
1744
1745
1746static PyObject*
1747DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1748{
1749 int err, flags=0;
1750 PyObject* txnobj = NULL;
1751 PyObject* keyobj;
1752 DBT key;
1753 DB_TXN *txn = NULL;
1754 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001755 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756
1757 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1758 &keyobj, &txnobj, &flags))
1759 return NULL;
1760 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001761 if (!make_dbt(keyobj, &key))
1762 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001763 return NULL;
1764 if (!checkTxnObj(txnobj, &txn))
1765 return NULL;
1766
1767 MYDB_BEGIN_ALLOW_THREADS;
1768 err = self->db->key_range(self->db, txn, &key, &range, flags);
1769 MYDB_END_ALLOW_THREADS;
1770
1771 RETURN_IF_ERR();
1772 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1773}
1774
1775
1776static PyObject*
1777DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1778{
1779 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1780 char* filename = NULL;
1781 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001782#if (DBVER >= 41)
1783 PyObject *txnobj = NULL;
1784 DB_TXN *txn = NULL;
1785 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001786 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001787 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1788 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001789 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001790 "filename", "dbtype", "flags", "mode", "txn", NULL};
1791#else
1792 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001793 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001794 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1795 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001796 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001797 "filename", "dbtype", "flags", "mode", NULL};
1798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001800#if (DBVER >= 41)
1801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1802 &filename, &dbname, &type, &flags, &mode,
1803 &txnobj))
1804#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001806 &filename, &dbname, &type, &flags,
1807 &mode))
1808#endif
1809 {
1810 PyErr_Clear();
1811 type = DB_UNKNOWN; flags = 0; mode = 0660;
1812 filename = NULL; dbname = NULL;
1813#if (DBVER >= 41)
1814 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1815 kwnames_basic,
1816 &filename, &type, &flags, &mode,
1817 &txnobj))
1818 return NULL;
1819#else
1820 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1821 kwnames_basic,
1822 &filename, &type, &flags, &mode))
1823 return NULL;
1824#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001825 }
1826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827#if (DBVER >= 41)
1828 if (!checkTxnObj(txnobj, &txn)) return NULL;
1829#endif
1830
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001832 PyObject *t = Py_BuildValue("(is)", 0,
1833 "Cannot call open() twice for DB object");
1834 PyErr_SetObject(DBError, t);
1835 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001836 return NULL;
1837 }
1838
1839 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001840#if (DBVER >= 41)
1841 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1842#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001843 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001844#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 MYDB_END_ALLOW_THREADS;
1846 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001847 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 self->db = NULL;
1849 return NULL;
1850 }
1851
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00001852 self->db->get_flags(self->db, &self->setflags);
1853
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 self->flags = flags;
1855 RETURN_NONE();
1856}
1857
1858
1859static PyObject*
1860DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1861{
1862 int flags=0;
1863 PyObject* txnobj = NULL;
1864 int dlen = -1;
1865 int doff = -1;
1866 PyObject* keyobj, *dataobj, *retval;
1867 DBT key, data;
1868 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001869 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001870 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001871
1872 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1873 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1874 return NULL;
1875
1876 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001877 if (!make_key_dbt(self, keyobj, &key, NULL))
1878 return NULL;
1879 if ( !make_dbt(dataobj, &data) ||
1880 !add_partial_dbt(&data, dlen, doff) ||
1881 !checkTxnObj(txnobj, &txn) )
1882 {
1883 FREE_DBT(key);
1884 return NULL;
1885 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001886
1887 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1888 FREE_DBT(key);
1889 return NULL;
1890 }
1891
1892 if (flags & DB_APPEND)
1893 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1894 else {
1895 retval = Py_None;
1896 Py_INCREF(retval);
1897 }
1898 FREE_DBT(key);
1899 return retval;
1900}
1901
1902
1903
1904static PyObject*
1905DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1906{
1907 char* filename;
1908 char* database = NULL;
1909 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001910 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911
1912 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1913 &filename, &database, &flags))
1914 return NULL;
1915 CHECK_DB_NOT_CLOSED(self);
1916
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001918 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001919 RETURN_IF_ERR();
1920 RETURN_NONE();
1921}
1922
1923
1924
1925static PyObject*
1926DB_rename(DBObject* self, PyObject* args)
1927{
1928 char* filename;
1929 char* database;
1930 char* newname;
1931 int err, flags=0;
1932
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001933 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1934 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001935 return NULL;
1936 CHECK_DB_NOT_CLOSED(self);
1937
1938 MYDB_BEGIN_ALLOW_THREADS;
1939 err = self->db->rename(self->db, filename, database, newname, flags);
1940 MYDB_END_ALLOW_THREADS;
1941 RETURN_IF_ERR();
1942 RETURN_NONE();
1943}
1944
1945
1946static PyObject*
1947DB_set_bt_minkey(DBObject* self, PyObject* args)
1948{
1949 int err, minkey;
1950
1951 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1952 return NULL;
1953 CHECK_DB_NOT_CLOSED(self);
1954
1955 MYDB_BEGIN_ALLOW_THREADS;
1956 err = self->db->set_bt_minkey(self->db, minkey);
1957 MYDB_END_ALLOW_THREADS;
1958 RETURN_IF_ERR();
1959 RETURN_NONE();
1960}
1961
Neal Norwitz84562352005-10-20 04:30:15 +00001962#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001963static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001964_default_cmp(const DBT *leftKey,
1965 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001966{
1967 int res;
1968 int lsize = leftKey->size, rsize = rightKey->size;
1969
Georg Brandlef1701f2006-03-07 14:57:48 +00001970 res = memcmp(leftKey->data, rightKey->data,
1971 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001972
1973 if (res == 0) {
1974 if (lsize < rsize) {
1975 res = -1;
1976 }
1977 else if (lsize > rsize) {
1978 res = 1;
1979 }
1980 }
1981 return res;
1982}
1983
1984static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001985_db_compareCallback(DB* db,
1986 const DBT *leftKey,
1987 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001988{
1989 int res = 0;
1990 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001991 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00001992 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001993
1994 if (self == NULL || self->btCompareCallback == NULL) {
1995 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00001996 PyErr_SetString(PyExc_TypeError,
1997 (self == 0
1998 ? "DB_bt_compare db is NULL."
1999 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002000 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002001 PyErr_Print();
2002 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002003 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002004 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002005 MYDB_BEGIN_BLOCK_THREADS;
2006
Thomas Woutersb3153832006-03-08 01:47:19 +00002007 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2008 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002009 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002010 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002011 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002012 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002013 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002014 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002015 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002016 PyErr_Print();
2017 res = _default_cmp(leftKey, rightKey);
2018 } else if (PyInt_Check(result)) {
2019 res = PyInt_AsLong(result);
2020 } else {
2021 PyErr_SetString(PyExc_TypeError,
2022 "DB_bt_compare callback MUST return an int.");
2023 /* we're in a callback within the DB code, we can't raise */
2024 PyErr_Print();
2025 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002026 }
2027
Thomas Woutersb3153832006-03-08 01:47:19 +00002028 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002029 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002030
2031 MYDB_END_BLOCK_THREADS;
2032 }
2033 return res;
2034}
2035
2036static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002037DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002038{
2039 int err;
2040 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002041 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002042
Georg Brandlef1701f2006-03-07 14:57:48 +00002043 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002044 return NULL;
2045
Georg Brandlef1701f2006-03-07 14:57:48 +00002046 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002047
Georg Brandlef1701f2006-03-07 14:57:48 +00002048 if (!PyCallable_Check(comparator)) {
2049 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002050 return NULL;
2051 }
2052
2053 /*
2054 * Perform a test call of the comparator function with two empty
2055 * string objects here. verify that it returns an int (0).
2056 * err if not.
2057 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002058 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002059 result = PyEval_CallObject(comparator, tuple);
2060 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002061 if (result == NULL)
2062 return NULL;
2063 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002064 PyErr_SetString(PyExc_TypeError,
2065 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002066 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002067 } else if (PyInt_AsLong(result) != 0) {
2068 PyErr_SetString(PyExc_TypeError,
2069 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002070 return NULL;
2071 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002072 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002073
2074 /* We don't accept multiple set_bt_compare operations, in order to
2075 * simplify the code. This would have no real use, as one cannot
2076 * change the function once the db is opened anyway */
2077 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002078 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002079 return NULL;
2080 }
2081
Georg Brandlef1701f2006-03-07 14:57:48 +00002082 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002083 self->btCompareCallback = comparator;
2084
2085 /* This is to workaround a problem with un-initialized threads (see
2086 comment in DB_associate) */
2087#ifdef WITH_THREAD
2088 PyEval_InitThreads();
2089#endif
2090
Thomas Woutersb3153832006-03-08 01:47:19 +00002091 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002092
2093 if (err) {
2094 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002095 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002096 self->btCompareCallback = NULL;
2097 }
2098
Georg Brandlef1701f2006-03-07 14:57:48 +00002099 RETURN_IF_ERR();
2100 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002101}
Neal Norwitz84562352005-10-20 04:30:15 +00002102#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002104
2105static PyObject*
2106DB_set_cachesize(DBObject* self, PyObject* args)
2107{
2108 int err;
2109 int gbytes = 0, bytes = 0, ncache = 0;
2110
2111 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2112 &gbytes,&bytes,&ncache))
2113 return NULL;
2114 CHECK_DB_NOT_CLOSED(self);
2115
2116 MYDB_BEGIN_ALLOW_THREADS;
2117 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2118 MYDB_END_ALLOW_THREADS;
2119 RETURN_IF_ERR();
2120 RETURN_NONE();
2121}
2122
2123
2124static PyObject*
2125DB_set_flags(DBObject* self, PyObject* args)
2126{
2127 int err, flags;
2128
2129 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2130 return NULL;
2131 CHECK_DB_NOT_CLOSED(self);
2132
2133 MYDB_BEGIN_ALLOW_THREADS;
2134 err = self->db->set_flags(self->db, flags);
2135 MYDB_END_ALLOW_THREADS;
2136 RETURN_IF_ERR();
2137
2138 self->setflags |= flags;
2139 RETURN_NONE();
2140}
2141
2142
2143static PyObject*
2144DB_set_h_ffactor(DBObject* self, PyObject* args)
2145{
2146 int err, ffactor;
2147
2148 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2149 return NULL;
2150 CHECK_DB_NOT_CLOSED(self);
2151
2152 MYDB_BEGIN_ALLOW_THREADS;
2153 err = self->db->set_h_ffactor(self->db, ffactor);
2154 MYDB_END_ALLOW_THREADS;
2155 RETURN_IF_ERR();
2156 RETURN_NONE();
2157}
2158
2159
2160static PyObject*
2161DB_set_h_nelem(DBObject* self, PyObject* args)
2162{
2163 int err, nelem;
2164
2165 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2166 return NULL;
2167 CHECK_DB_NOT_CLOSED(self);
2168
2169 MYDB_BEGIN_ALLOW_THREADS;
2170 err = self->db->set_h_nelem(self->db, nelem);
2171 MYDB_END_ALLOW_THREADS;
2172 RETURN_IF_ERR();
2173 RETURN_NONE();
2174}
2175
2176
2177static PyObject*
2178DB_set_lorder(DBObject* self, PyObject* args)
2179{
2180 int err, lorder;
2181
2182 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2183 return NULL;
2184 CHECK_DB_NOT_CLOSED(self);
2185
2186 MYDB_BEGIN_ALLOW_THREADS;
2187 err = self->db->set_lorder(self->db, lorder);
2188 MYDB_END_ALLOW_THREADS;
2189 RETURN_IF_ERR();
2190 RETURN_NONE();
2191}
2192
2193
2194static PyObject*
2195DB_set_pagesize(DBObject* self, PyObject* args)
2196{
2197 int err, pagesize;
2198
2199 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2200 return NULL;
2201 CHECK_DB_NOT_CLOSED(self);
2202
2203 MYDB_BEGIN_ALLOW_THREADS;
2204 err = self->db->set_pagesize(self->db, pagesize);
2205 MYDB_END_ALLOW_THREADS;
2206 RETURN_IF_ERR();
2207 RETURN_NONE();
2208}
2209
2210
2211static PyObject*
2212DB_set_re_delim(DBObject* self, PyObject* args)
2213{
2214 int err;
2215 char delim;
2216
2217 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2218 PyErr_Clear();
2219 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2220 return NULL;
2221 }
2222
2223 CHECK_DB_NOT_CLOSED(self);
2224
2225 MYDB_BEGIN_ALLOW_THREADS;
2226 err = self->db->set_re_delim(self->db, delim);
2227 MYDB_END_ALLOW_THREADS;
2228 RETURN_IF_ERR();
2229 RETURN_NONE();
2230}
2231
2232static PyObject*
2233DB_set_re_len(DBObject* self, PyObject* args)
2234{
2235 int err, len;
2236
2237 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2238 return NULL;
2239 CHECK_DB_NOT_CLOSED(self);
2240
2241 MYDB_BEGIN_ALLOW_THREADS;
2242 err = self->db->set_re_len(self->db, len);
2243 MYDB_END_ALLOW_THREADS;
2244 RETURN_IF_ERR();
2245 RETURN_NONE();
2246}
2247
2248
2249static PyObject*
2250DB_set_re_pad(DBObject* self, PyObject* args)
2251{
2252 int err;
2253 char pad;
2254
2255 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2256 PyErr_Clear();
2257 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2258 return NULL;
2259 }
2260 CHECK_DB_NOT_CLOSED(self);
2261
2262 MYDB_BEGIN_ALLOW_THREADS;
2263 err = self->db->set_re_pad(self->db, pad);
2264 MYDB_END_ALLOW_THREADS;
2265 RETURN_IF_ERR();
2266 RETURN_NONE();
2267}
2268
2269
2270static PyObject*
2271DB_set_re_source(DBObject* self, PyObject* args)
2272{
2273 int err;
2274 char *re_source;
2275
2276 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2277 return NULL;
2278 CHECK_DB_NOT_CLOSED(self);
2279
2280 MYDB_BEGIN_ALLOW_THREADS;
2281 err = self->db->set_re_source(self->db, re_source);
2282 MYDB_END_ALLOW_THREADS;
2283 RETURN_IF_ERR();
2284 RETURN_NONE();
2285}
2286
2287
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002288static PyObject*
2289DB_set_q_extentsize(DBObject* self, PyObject* args)
2290{
2291 int err;
2292 int extentsize;
2293
2294 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2295 return NULL;
2296 CHECK_DB_NOT_CLOSED(self);
2297
2298 MYDB_BEGIN_ALLOW_THREADS;
2299 err = self->db->set_q_extentsize(self->db, extentsize);
2300 MYDB_END_ALLOW_THREADS;
2301 RETURN_IF_ERR();
2302 RETURN_NONE();
2303}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002304
2305static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002306DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002307{
2308 int err, flags = 0, type;
2309 void* sp;
2310 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002311#if (DBVER >= 43)
2312 PyObject* txnobj = NULL;
2313 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002314 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002315#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002316 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002317#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002318
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002319#if (DBVER >= 43)
2320 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2321 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002322 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002323 if (!checkTxnObj(txnobj, &txn))
2324 return NULL;
2325#else
2326 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2327 return NULL;
2328#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002329 CHECK_DB_NOT_CLOSED(self);
2330
2331 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002332#if (DBVER >= 43)
2333 err = self->db->stat(self->db, txn, &sp, flags);
2334#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002335 err = self->db->stat(self->db, &sp, flags);
2336#else
2337 err = self->db->stat(self->db, &sp, NULL, flags);
2338#endif
2339 MYDB_END_ALLOW_THREADS;
2340 RETURN_IF_ERR();
2341
2342 self->haveStat = 1;
2343
2344 /* Turn the stat structure into a dictionary */
2345 type = _DB_get_type(self);
2346 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2347 free(sp);
2348 return NULL;
2349 }
2350
2351#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2352#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2353#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2354
2355 switch (type) {
2356 case DB_HASH:
2357 MAKE_HASH_ENTRY(magic);
2358 MAKE_HASH_ENTRY(version);
2359 MAKE_HASH_ENTRY(nkeys);
2360 MAKE_HASH_ENTRY(ndata);
2361 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002362#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002363 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002364#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002365 MAKE_HASH_ENTRY(ffactor);
2366 MAKE_HASH_ENTRY(buckets);
2367 MAKE_HASH_ENTRY(free);
2368 MAKE_HASH_ENTRY(bfree);
2369 MAKE_HASH_ENTRY(bigpages);
2370 MAKE_HASH_ENTRY(big_bfree);
2371 MAKE_HASH_ENTRY(overflows);
2372 MAKE_HASH_ENTRY(ovfl_free);
2373 MAKE_HASH_ENTRY(dup);
2374 MAKE_HASH_ENTRY(dup_free);
2375 break;
2376
2377 case DB_BTREE:
2378 case DB_RECNO:
2379 MAKE_BT_ENTRY(magic);
2380 MAKE_BT_ENTRY(version);
2381 MAKE_BT_ENTRY(nkeys);
2382 MAKE_BT_ENTRY(ndata);
2383 MAKE_BT_ENTRY(pagesize);
2384 MAKE_BT_ENTRY(minkey);
2385 MAKE_BT_ENTRY(re_len);
2386 MAKE_BT_ENTRY(re_pad);
2387 MAKE_BT_ENTRY(levels);
2388 MAKE_BT_ENTRY(int_pg);
2389 MAKE_BT_ENTRY(leaf_pg);
2390 MAKE_BT_ENTRY(dup_pg);
2391 MAKE_BT_ENTRY(over_pg);
2392 MAKE_BT_ENTRY(free);
2393 MAKE_BT_ENTRY(int_pgfree);
2394 MAKE_BT_ENTRY(leaf_pgfree);
2395 MAKE_BT_ENTRY(dup_pgfree);
2396 MAKE_BT_ENTRY(over_pgfree);
2397 break;
2398
2399 case DB_QUEUE:
2400 MAKE_QUEUE_ENTRY(magic);
2401 MAKE_QUEUE_ENTRY(version);
2402 MAKE_QUEUE_ENTRY(nkeys);
2403 MAKE_QUEUE_ENTRY(ndata);
2404 MAKE_QUEUE_ENTRY(pagesize);
2405 MAKE_QUEUE_ENTRY(pages);
2406 MAKE_QUEUE_ENTRY(re_len);
2407 MAKE_QUEUE_ENTRY(re_pad);
2408 MAKE_QUEUE_ENTRY(pgfree);
2409#if (DBVER == 31)
2410 MAKE_QUEUE_ENTRY(start);
2411#endif
2412 MAKE_QUEUE_ENTRY(first_recno);
2413 MAKE_QUEUE_ENTRY(cur_recno);
2414 break;
2415
2416 default:
2417 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2418 Py_DECREF(d);
2419 d = NULL;
2420 }
2421
2422#undef MAKE_HASH_ENTRY
2423#undef MAKE_BT_ENTRY
2424#undef MAKE_QUEUE_ENTRY
2425
2426 free(sp);
2427 return d;
2428}
2429
2430static PyObject*
2431DB_sync(DBObject* self, PyObject* args)
2432{
2433 int err;
2434 int flags = 0;
2435
2436 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2437 return NULL;
2438 CHECK_DB_NOT_CLOSED(self);
2439
2440 MYDB_BEGIN_ALLOW_THREADS;
2441 err = self->db->sync(self->db, flags);
2442 MYDB_END_ALLOW_THREADS;
2443 RETURN_IF_ERR();
2444 RETURN_NONE();
2445}
2446
2447
2448#if (DBVER >= 33)
2449static PyObject*
2450DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2451{
2452 int err, flags=0;
2453 u_int32_t count=0;
2454 PyObject* txnobj = NULL;
2455 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002456 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002457
2458 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2459 &txnobj, &flags))
2460 return NULL;
2461 CHECK_DB_NOT_CLOSED(self);
2462 if (!checkTxnObj(txnobj, &txn))
2463 return NULL;
2464
2465 MYDB_BEGIN_ALLOW_THREADS;
2466 err = self->db->truncate(self->db, txn, &count, flags);
2467 MYDB_END_ALLOW_THREADS;
2468 RETURN_IF_ERR();
2469 return PyInt_FromLong(count);
2470}
2471#endif
2472
2473
2474static PyObject*
2475DB_upgrade(DBObject* self, PyObject* args)
2476{
2477 int err, flags=0;
2478 char *filename;
2479
2480 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2481 return NULL;
2482 CHECK_DB_NOT_CLOSED(self);
2483
2484 MYDB_BEGIN_ALLOW_THREADS;
2485 err = self->db->upgrade(self->db, filename, flags);
2486 MYDB_END_ALLOW_THREADS;
2487 RETURN_IF_ERR();
2488 RETURN_NONE();
2489}
2490
2491
2492static PyObject*
2493DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2494{
2495 int err, flags=0;
2496 char* fileName;
2497 char* dbName=NULL;
2498 char* outFileName=NULL;
2499 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002500 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002501 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002502
2503 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2504 &fileName, &dbName, &outFileName, &flags))
2505 return NULL;
2506
2507 CHECK_DB_NOT_CLOSED(self);
2508 if (outFileName)
2509 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002510 /* XXX(nnorwitz): it should probably be an exception if outFile
2511 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002512
2513 MYDB_BEGIN_ALLOW_THREADS;
2514 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2515 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002516 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002517 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002518
2519 /* DB.verify acts as a DB handle destructor (like close); this was
2520 * documented in BerkeleyDB 4.2 but had the undocumented effect
2521 * of not being safe in prior versions while still requiring an explicit
2522 * DB.close call afterwards. Lets call close for the user to emulate
2523 * the safe 4.2 behaviour. */
2524#if (DBVER <= 41)
2525 self->db->close(self->db, 0);
2526#endif
2527 self->db = NULL;
2528
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002529 RETURN_IF_ERR();
2530 RETURN_NONE();
2531}
2532
2533
2534static PyObject*
2535DB_set_get_returns_none(DBObject* self, PyObject* args)
2536{
2537 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002538 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002539
2540 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2541 return NULL;
2542 CHECK_DB_NOT_CLOSED(self);
2543
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002544 if (self->moduleFlags.getReturnsNone)
2545 ++oldValue;
2546 if (self->moduleFlags.cursorSetReturnsNone)
2547 ++oldValue;
2548 self->moduleFlags.getReturnsNone = (flags >= 1);
2549 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002550 return PyInt_FromLong(oldValue);
2551}
2552
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002553#if (DBVER >= 41)
2554static PyObject*
2555DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2556{
2557 int err;
2558 u_int32_t flags=0;
2559 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002560 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002561
2562 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2563 &passwd, &flags)) {
2564 return NULL;
2565 }
2566
2567 MYDB_BEGIN_ALLOW_THREADS;
2568 err = self->db->set_encrypt(self->db, passwd, flags);
2569 MYDB_END_ALLOW_THREADS;
2570
2571 RETURN_IF_ERR();
2572 RETURN_NONE();
2573}
2574#endif /* DBVER >= 41 */
2575
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002576
2577/*-------------------------------------------------------------- */
2578/* Mapping and Dictionary-like access routines */
2579
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002580Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002581{
2582 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002583 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002584 int flags = 0;
2585 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002586 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587
2588 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002589 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2590 PyErr_SetObject(DBError, t);
2591 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002592 return -1;
2593 }
2594
2595 if (self->haveStat) { /* Has the stat function been called recently? If
2596 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002597 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002598 }
2599
2600 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002601redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002602#if (DBVER >= 43)
2603 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2604#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002605 err = self->db->stat(self->db, &sp, flags);
2606#else
2607 err = self->db->stat(self->db, &sp, NULL, flags);
2608#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002609
2610 /* All the stat structures have matching fields upto the ndata field,
2611 so we can use any of them for the type cast */
2612 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2613
2614 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2615 * redo a full stat to make sure.
2616 * Fixes SF python bug 1493322, pybsddb bug 1184012
2617 */
2618 if (size == 0 && (flags & DB_FAST_STAT)) {
2619 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002620 if (!err)
2621 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002622 goto redo_stat_for_length;
2623 }
2624
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002625 MYDB_END_ALLOW_THREADS;
2626
2627 if (err)
2628 return -1;
2629
2630 self->haveStat = 1;
2631
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002632 free(sp);
2633 return size;
2634}
2635
2636
2637PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2638{
2639 int err;
2640 PyObject* retval;
2641 DBT key;
2642 DBT data;
2643
2644 CHECK_DB_NOT_CLOSED(self);
2645 if (!make_key_dbt(self, keyobj, &key, NULL))
2646 return NULL;
2647
2648 CLEAR_DBT(data);
2649 if (CHECK_DBFLAG(self, DB_THREAD)) {
2650 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2651 data.flags = DB_DBT_MALLOC;
2652 }
2653 MYDB_BEGIN_ALLOW_THREADS;
2654 err = self->db->get(self->db, NULL, &key, &data, 0);
2655 MYDB_END_ALLOW_THREADS;
2656 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2657 PyErr_SetObject(PyExc_KeyError, keyobj);
2658 retval = NULL;
2659 }
2660 else if (makeDBError(err)) {
2661 retval = NULL;
2662 }
2663 else {
2664 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2665 FREE_DBT(data);
2666 }
2667
2668 FREE_DBT(key);
2669 return retval;
2670}
2671
2672
2673static int
2674DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2675{
2676 DBT key, data;
2677 int retval;
2678 int flags = 0;
2679
2680 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002681 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2682 PyErr_SetObject(DBError, t);
2683 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002684 return -1;
2685 }
2686
2687 if (!make_key_dbt(self, keyobj, &key, NULL))
2688 return -1;
2689
2690 if (dataobj != NULL) {
2691 if (!make_dbt(dataobj, &data))
2692 retval = -1;
2693 else {
2694 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002695 /* dictionaries shouldn't have duplicate keys */
2696 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002697 retval = _DB_put(self, NULL, &key, &data, flags);
2698
2699 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002700 /* try deleting any old record that matches and then PUT it
2701 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 _DB_delete(self, NULL, &key, 0);
2703 PyErr_Clear();
2704 retval = _DB_put(self, NULL, &key, &data, flags);
2705 }
2706 }
2707 }
2708 else {
2709 /* dataobj == NULL, so delete the key */
2710 retval = _DB_delete(self, NULL, &key, 0);
2711 }
2712 FREE_DBT(key);
2713 return retval;
2714}
2715
2716
2717static PyObject*
2718DB_has_key(DBObject* self, PyObject* args)
2719{
2720 int err;
2721 PyObject* keyobj;
2722 DBT key, data;
2723 PyObject* txnobj = NULL;
2724 DB_TXN *txn = NULL;
2725
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002726 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 return NULL;
2728 CHECK_DB_NOT_CLOSED(self);
2729 if (!make_key_dbt(self, keyobj, &key, NULL))
2730 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002731 if (!checkTxnObj(txnobj, &txn)) {
2732 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002733 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002734 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002735
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002736 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 it has a record but can't allocate a buffer for the data. This saves
2738 having to deal with data we won't be using.
2739 */
2740 CLEAR_DBT(data);
2741 data.flags = DB_DBT_USERMEM;
2742
2743 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002744 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002745 MYDB_END_ALLOW_THREADS;
2746 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002747
2748 if (err == DB_BUFFER_SMALL || err == 0) {
2749 return PyInt_FromLong(1);
2750 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2751 return PyInt_FromLong(0);
2752 }
2753
2754 makeDBError(err);
2755 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002756}
2757
2758
2759#define _KEYS_LIST 1
2760#define _VALUES_LIST 2
2761#define _ITEMS_LIST 3
2762
2763static PyObject*
2764_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2765{
2766 int err, dbtype;
2767 DBT key;
2768 DBT data;
2769 DBC *cursor;
2770 PyObject* list;
2771 PyObject* item = NULL;
2772
2773 CHECK_DB_NOT_CLOSED(self);
2774 CLEAR_DBT(key);
2775 CLEAR_DBT(data);
2776
2777 dbtype = _DB_get_type(self);
2778 if (dbtype == -1)
2779 return NULL;
2780
2781 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002782 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002783 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002784
2785 /* get a cursor */
2786 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002787 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002789 if (makeDBError(err)) {
2790 Py_DECREF(list);
2791 return NULL;
2792 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002793
2794 if (CHECK_DBFLAG(self, DB_THREAD)) {
2795 key.flags = DB_DBT_REALLOC;
2796 data.flags = DB_DBT_REALLOC;
2797 }
2798
2799 while (1) { /* use the cursor to traverse the DB, collecting items */
2800 MYDB_BEGIN_ALLOW_THREADS;
2801 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2802 MYDB_END_ALLOW_THREADS;
2803
2804 if (err) {
2805 /* for any error, break out of the loop */
2806 break;
2807 }
2808
2809 switch (type) {
2810 case _KEYS_LIST:
2811 switch(dbtype) {
2812 case DB_BTREE:
2813 case DB_HASH:
2814 default:
2815 item = PyString_FromStringAndSize((char*)key.data, key.size);
2816 break;
2817 case DB_RECNO:
2818 case DB_QUEUE:
2819 item = PyInt_FromLong(*((db_recno_t*)key.data));
2820 break;
2821 }
2822 break;
2823
2824 case _VALUES_LIST:
2825 item = PyString_FromStringAndSize((char*)data.data, data.size);
2826 break;
2827
2828 case _ITEMS_LIST:
2829 switch(dbtype) {
2830 case DB_BTREE:
2831 case DB_HASH:
2832 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002833 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2834 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 break;
2836 case DB_RECNO:
2837 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002838 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2839 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002840 break;
2841 }
2842 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002843 default:
2844 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2845 item = NULL;
2846 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 }
2848 if (item == NULL) {
2849 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 list = NULL;
2851 goto done;
2852 }
2853 PyList_Append(list, item);
2854 Py_DECREF(item);
2855 }
2856
Gregory P. Smithe9477062005-06-04 06:46:59 +00002857 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2858 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002859 Py_DECREF(list);
2860 list = NULL;
2861 }
2862
2863 done:
2864 FREE_DBT(key);
2865 FREE_DBT(data);
2866 MYDB_BEGIN_ALLOW_THREADS;
2867 cursor->c_close(cursor);
2868 MYDB_END_ALLOW_THREADS;
2869 return list;
2870}
2871
2872
2873static PyObject*
2874DB_keys(DBObject* self, PyObject* args)
2875{
2876 PyObject* txnobj = NULL;
2877 DB_TXN *txn = NULL;
2878
Georg Brandl96a8c392006-05-29 21:04:52 +00002879 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880 return NULL;
2881 if (!checkTxnObj(txnobj, &txn))
2882 return NULL;
2883 return _DB_make_list(self, txn, _KEYS_LIST);
2884}
2885
2886
2887static PyObject*
2888DB_items(DBObject* self, PyObject* args)
2889{
2890 PyObject* txnobj = NULL;
2891 DB_TXN *txn = NULL;
2892
Georg Brandl96a8c392006-05-29 21:04:52 +00002893 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894 return NULL;
2895 if (!checkTxnObj(txnobj, &txn))
2896 return NULL;
2897 return _DB_make_list(self, txn, _ITEMS_LIST);
2898}
2899
2900
2901static PyObject*
2902DB_values(DBObject* self, PyObject* args)
2903{
2904 PyObject* txnobj = NULL;
2905 DB_TXN *txn = NULL;
2906
Georg Brandl96a8c392006-05-29 21:04:52 +00002907 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002908 return NULL;
2909 if (!checkTxnObj(txnobj, &txn))
2910 return NULL;
2911 return _DB_make_list(self, txn, _VALUES_LIST);
2912}
2913
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002914/* --------------------------------------------------------------------- */
2915/* DBCursor methods */
2916
2917
2918static PyObject*
2919DBC_close(DBCursorObject* self, PyObject* args)
2920{
2921 int err = 0;
2922
2923 if (!PyArg_ParseTuple(args, ":close"))
2924 return NULL;
2925
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002926 if (self->dbc != NULL) {
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = self->dbc->c_close(self->dbc);
2929 self->dbc = NULL;
2930 MYDB_END_ALLOW_THREADS;
2931 }
2932 RETURN_IF_ERR();
2933 RETURN_NONE();
2934}
2935
2936
2937static PyObject*
2938DBC_count(DBCursorObject* self, PyObject* args)
2939{
2940 int err = 0;
2941 db_recno_t count;
2942 int flags = 0;
2943
2944 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2945 return NULL;
2946
2947 CHECK_CURSOR_NOT_CLOSED(self);
2948
2949 MYDB_BEGIN_ALLOW_THREADS;
2950 err = self->dbc->c_count(self->dbc, &count, flags);
2951 MYDB_END_ALLOW_THREADS;
2952 RETURN_IF_ERR();
2953
2954 return PyInt_FromLong(count);
2955}
2956
2957
2958static PyObject*
2959DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2960{
2961 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2962}
2963
2964
2965static PyObject*
2966DBC_delete(DBCursorObject* self, PyObject* args)
2967{
2968 int err, flags=0;
2969
2970 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2971 return NULL;
2972
2973 CHECK_CURSOR_NOT_CLOSED(self);
2974
2975 MYDB_BEGIN_ALLOW_THREADS;
2976 err = self->dbc->c_del(self->dbc, flags);
2977 MYDB_END_ALLOW_THREADS;
2978 RETURN_IF_ERR();
2979
2980 self->mydb->haveStat = 0;
2981 RETURN_NONE();
2982}
2983
2984
2985static PyObject*
2986DBC_dup(DBCursorObject* self, PyObject* args)
2987{
2988 int err, flags =0;
2989 DBC* dbc = NULL;
2990
2991 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2992 return NULL;
2993
2994 CHECK_CURSOR_NOT_CLOSED(self);
2995
2996 MYDB_BEGIN_ALLOW_THREADS;
2997 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2998 MYDB_END_ALLOW_THREADS;
2999 RETURN_IF_ERR();
3000
3001 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3002}
3003
3004static PyObject*
3005DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3006{
3007 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3008}
3009
3010
3011static PyObject*
3012DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3013{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003014 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 PyObject* keyobj = NULL;
3016 PyObject* dataobj = NULL;
3017 PyObject* retval = NULL;
3018 int dlen = -1;
3019 int doff = -1;
3020 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003021 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003022 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003023
3024 CLEAR_DBT(key);
3025 CLEAR_DBT(data);
3026 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003027 &flags, &dlen, &doff))
3028 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003029 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003030 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3031 &kwnames[1],
3032 &keyobj, &flags, &dlen, &doff))
3033 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003035 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3036 kwnames, &keyobj, &dataobj,
3037 &flags, &dlen, &doff))
3038 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003039 return NULL;
3040 }
3041 }
3042 }
3043
3044 CHECK_CURSOR_NOT_CLOSED(self);
3045
3046 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3047 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003048 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3049 (!add_partial_dbt(&data, dlen, doff)) )
3050 {
3051 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003052 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003053 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003054
3055 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3056 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003057 if (!(key.flags & DB_DBT_REALLOC)) {
3058 key.flags |= DB_DBT_MALLOC;
3059 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 }
3061
3062 MYDB_BEGIN_ALLOW_THREADS;
3063 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3064 MYDB_END_ALLOW_THREADS;
3065
Gregory P. Smithe9477062005-06-04 06:46:59 +00003066 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3067 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068 Py_INCREF(Py_None);
3069 retval = Py_None;
3070 }
3071 else if (makeDBError(err)) {
3072 retval = NULL;
3073 }
3074 else {
3075 switch (_DB_get_type(self->mydb)) {
3076 case -1:
3077 retval = NULL;
3078 break;
3079 case DB_BTREE:
3080 case DB_HASH:
3081 default:
3082 retval = Py_BuildValue("s#s#", key.data, key.size,
3083 data.data, data.size);
3084 break;
3085 case DB_RECNO:
3086 case DB_QUEUE:
3087 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3088 data.data, data.size);
3089 break;
3090 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003091 FREE_DBT(data);
3092 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003093 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003094 return retval;
3095}
3096
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003097#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003098static PyObject*
3099DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3100{
3101 int err, flags=0;
3102 PyObject* keyobj = NULL;
3103 PyObject* dataobj = NULL;
3104 PyObject* retval = NULL;
3105 int dlen = -1;
3106 int doff = -1;
3107 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003108 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3109 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003110
3111 CLEAR_DBT(key);
3112 CLEAR_DBT(data);
3113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3114 &flags, &dlen, &doff))
3115 {
3116 PyErr_Clear();
3117 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003118 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003119 &keyobj, &flags, &dlen, &doff))
3120 {
3121 PyErr_Clear();
3122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3123 kwnames, &keyobj, &dataobj,
3124 &flags, &dlen, &doff))
3125 {
3126 return NULL;
3127 }
3128 }
3129 }
3130
3131 CHECK_CURSOR_NOT_CLOSED(self);
3132
3133 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3134 return NULL;
3135 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3136 (!add_partial_dbt(&data, dlen, doff)) ) {
3137 FREE_DBT(key);
3138 return NULL;
3139 }
3140
3141 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3142 data.flags = DB_DBT_MALLOC;
3143 if (!(key.flags & DB_DBT_REALLOC)) {
3144 key.flags |= DB_DBT_MALLOC;
3145 }
3146 }
3147
3148 CLEAR_DBT(pkey);
3149 pkey.flags = DB_DBT_MALLOC;
3150
3151 MYDB_BEGIN_ALLOW_THREADS;
3152 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3153 MYDB_END_ALLOW_THREADS;
3154
Gregory P. Smithe9477062005-06-04 06:46:59 +00003155 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3156 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003157 Py_INCREF(Py_None);
3158 retval = Py_None;
3159 }
3160 else if (makeDBError(err)) {
3161 retval = NULL;
3162 }
3163 else {
3164 PyObject *pkeyObj;
3165 PyObject *dataObj;
3166 dataObj = PyString_FromStringAndSize(data.data, data.size);
3167
3168 if (self->mydb->primaryDBType == DB_RECNO ||
3169 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003170 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003171 else
3172 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3173
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003174 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003175 {
3176 PyObject *keyObj;
3177 int type = _DB_get_type(self->mydb);
3178 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003179 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003180 else
3181 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003182#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003183 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003184#else
3185 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3186#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003187 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003188 FREE_DBT(key);
3189 }
3190 else /* return just the pkey and data */
3191 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003192#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003193 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003194#else
3195 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3196#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003197 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003198 Py_DECREF(dataObj);
3199 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003200 FREE_DBT(pkey);
3201 FREE_DBT(data);
3202 }
3203 /* the only time REALLOC should be set is if we used an integer
3204 * key that make_key_dbt malloc'd for us. always free these. */
3205 if (key.flags & DB_DBT_REALLOC) {
3206 FREE_DBT(key);
3207 }
3208 return retval;
3209}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003210#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003211
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003212
3213static PyObject*
3214DBC_get_recno(DBCursorObject* self, PyObject* args)
3215{
3216 int err;
3217 db_recno_t recno;
3218 DBT key;
3219 DBT data;
3220
3221 if (!PyArg_ParseTuple(args, ":get_recno"))
3222 return NULL;
3223
3224 CHECK_CURSOR_NOT_CLOSED(self);
3225
3226 CLEAR_DBT(key);
3227 CLEAR_DBT(data);
3228 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3229 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3230 data.flags = DB_DBT_MALLOC;
3231 key.flags = DB_DBT_MALLOC;
3232 }
3233
3234 MYDB_BEGIN_ALLOW_THREADS;
3235 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3236 MYDB_END_ALLOW_THREADS;
3237 RETURN_IF_ERR();
3238
3239 recno = *((db_recno_t*)data.data);
3240 FREE_DBT(key);
3241 FREE_DBT(data);
3242 return PyInt_FromLong(recno);
3243}
3244
3245
3246static PyObject*
3247DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3248{
3249 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3250}
3251
3252
3253static PyObject*
3254DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3255{
3256 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3257}
3258
3259
3260static PyObject*
3261DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3262{
3263 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3264}
3265
3266
3267static PyObject*
3268DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3269{
3270 int err, flags = 0;
3271 PyObject* keyobj, *dataobj;
3272 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003273 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003274 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003275 int dlen = -1;
3276 int doff = -1;
3277
3278 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3279 &keyobj, &dataobj, &flags, &dlen, &doff))
3280 return NULL;
3281
3282 CHECK_CURSOR_NOT_CLOSED(self);
3283
3284 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3285 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003286 if (!make_dbt(dataobj, &data) ||
3287 !add_partial_dbt(&data, dlen, doff) )
3288 {
3289 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003290 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003291 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003292
3293 MYDB_BEGIN_ALLOW_THREADS;
3294 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3295 MYDB_END_ALLOW_THREADS;
3296 FREE_DBT(key);
3297 RETURN_IF_ERR();
3298 self->mydb->haveStat = 0;
3299 RETURN_NONE();
3300}
3301
3302
3303static PyObject*
3304DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3305{
3306 int err, flags = 0;
3307 DBT key, data;
3308 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003309 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003310 int dlen = -1;
3311 int doff = -1;
3312
3313 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3314 &keyobj, &flags, &dlen, &doff))
3315 return NULL;
3316
3317 CHECK_CURSOR_NOT_CLOSED(self);
3318
3319 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3320 return NULL;
3321
3322 CLEAR_DBT(data);
3323 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3324 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3325 data.flags = DB_DBT_MALLOC;
3326 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003327 if (!add_partial_dbt(&data, dlen, doff)) {
3328 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003329 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003330 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003331
3332 MYDB_BEGIN_ALLOW_THREADS;
3333 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3334 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003335 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3336 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003337 Py_INCREF(Py_None);
3338 retval = Py_None;
3339 }
3340 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341 retval = NULL;
3342 }
3343 else {
3344 switch (_DB_get_type(self->mydb)) {
3345 case -1:
3346 retval = NULL;
3347 break;
3348 case DB_BTREE:
3349 case DB_HASH:
3350 default:
3351 retval = Py_BuildValue("s#s#", key.data, key.size,
3352 data.data, data.size);
3353 break;
3354 case DB_RECNO:
3355 case DB_QUEUE:
3356 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3357 data.data, data.size);
3358 break;
3359 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003361 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003363 /* the only time REALLOC should be set is if we used an integer
3364 * key that make_key_dbt malloc'd for us. always free these. */
3365 if (key.flags & DB_DBT_REALLOC) {
3366 FREE_DBT(key);
3367 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003368
3369 return retval;
3370}
3371
3372
3373static PyObject*
3374DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3375{
3376 int err, flags = 0;
3377 DBT key, data;
3378 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003379 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003380 int dlen = -1;
3381 int doff = -1;
3382
3383 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3384 &keyobj, &flags, &dlen, &doff))
3385 return NULL;
3386
3387 CHECK_CURSOR_NOT_CLOSED(self);
3388
3389 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3390 return NULL;
3391
3392 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003393 if (!add_partial_dbt(&data, dlen, doff)) {
3394 FREE_DBT(key);
3395 return NULL;
3396 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003397 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3398 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003399 data.flags |= DB_DBT_MALLOC;
3400 /* only BTREE databases will return anything in the key */
3401 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3402 key.flags |= DB_DBT_MALLOC;
3403 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003404 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003405 MYDB_BEGIN_ALLOW_THREADS;
3406 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3407 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003408 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3409 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003410 Py_INCREF(Py_None);
3411 retval = Py_None;
3412 }
3413 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 retval = NULL;
3415 }
3416 else {
3417 switch (_DB_get_type(self->mydb)) {
3418 case -1:
3419 retval = NULL;
3420 break;
3421 case DB_BTREE:
3422 case DB_HASH:
3423 default:
3424 retval = Py_BuildValue("s#s#", key.data, key.size,
3425 data.data, data.size);
3426 break;
3427 case DB_RECNO:
3428 case DB_QUEUE:
3429 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3430 data.data, data.size);
3431 break;
3432 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003433 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003434 FREE_DBT(data);
3435 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003436 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003437 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003438 if (key.flags & DB_DBT_REALLOC) {
3439 FREE_DBT(key);
3440 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003441
3442 return retval;
3443}
3444
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003446_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3447 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003449 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003450 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003451 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452
Gregory P. Smith7441e652003-11-03 21:35:31 +00003453 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3455 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003456 if (!make_dbt(dataobj, &data)) {
3457 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003458 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003459 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461 MYDB_BEGIN_ALLOW_THREADS;
3462 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3463 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003464 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003465 Py_INCREF(Py_None);
3466 retval = Py_None;
3467 }
3468 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 retval = NULL;
3470 }
3471 else {
3472 switch (_DB_get_type(self->mydb)) {
3473 case -1:
3474 retval = NULL;
3475 break;
3476 case DB_BTREE:
3477 case DB_HASH:
3478 default:
3479 retval = Py_BuildValue("s#s#", key.data, key.size,
3480 data.data, data.size);
3481 break;
3482 case DB_RECNO:
3483 case DB_QUEUE:
3484 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3485 data.data, data.size);
3486 break;
3487 }
3488 }
3489
3490 FREE_DBT(key);
3491 return retval;
3492}
3493
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003494static PyObject*
3495DBC_get_both(DBCursorObject* self, PyObject* args)
3496{
3497 int flags=0;
3498 PyObject *keyobj, *dataobj;
3499
3500 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3501 return NULL;
3502
Gregory P. Smith7441e652003-11-03 21:35:31 +00003503 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003504 CHECK_CURSOR_NOT_CLOSED(self);
3505
3506 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3507 self->mydb->moduleFlags.getReturnsNone);
3508}
3509
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003510/* Return size of entry */
3511static PyObject*
3512DBC_get_current_size(DBCursorObject* self, PyObject* args)
3513{
3514 int err, flags=DB_CURRENT;
3515 PyObject* retval = NULL;
3516 DBT key, data;
3517
3518 if (!PyArg_ParseTuple(args, ":get_current_size"))
3519 return NULL;
3520 CHECK_CURSOR_NOT_CLOSED(self);
3521 CLEAR_DBT(key);
3522 CLEAR_DBT(data);
3523
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003524 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003525 getting the record size. */
3526 data.flags = DB_DBT_USERMEM;
3527 data.ulen = 0;
3528 MYDB_BEGIN_ALLOW_THREADS;
3529 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3530 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003531 if (err == DB_BUFFER_SMALL || !err) {
3532 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003533 retval = PyInt_FromLong((long)data.size);
3534 err = 0;
3535 }
3536
3537 FREE_DBT(key);
3538 FREE_DBT(data);
3539 RETURN_IF_ERR();
3540 return retval;
3541}
3542
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003543static PyObject*
3544DBC_set_both(DBCursorObject* self, PyObject* args)
3545{
3546 int flags=0;
3547 PyObject *keyobj, *dataobj;
3548
3549 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3550 return NULL;
3551
Gregory P. Smith7441e652003-11-03 21:35:31 +00003552 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003553 CHECK_CURSOR_NOT_CLOSED(self);
3554
3555 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3556 self->mydb->moduleFlags.cursorSetReturnsNone);
3557}
3558
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003559
3560static PyObject*
3561DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3562{
3563 int err, irecno, flags=0;
3564 db_recno_t recno;
3565 DBT key, data;
3566 PyObject* retval;
3567 int dlen = -1;
3568 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003569 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570
3571 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3572 &irecno, &flags, &dlen, &doff))
3573 return NULL;
3574
3575 CHECK_CURSOR_NOT_CLOSED(self);
3576
3577 CLEAR_DBT(key);
3578 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003579 /* use allocated space so DB will be able to realloc room for the real
3580 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581 key.data = malloc(sizeof(db_recno_t));
3582 if (key.data == NULL) {
3583 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3584 return NULL;
3585 }
3586 key.size = sizeof(db_recno_t);
3587 key.ulen = key.size;
3588 memcpy(key.data, &recno, sizeof(db_recno_t));
3589 key.flags = DB_DBT_REALLOC;
3590
3591 CLEAR_DBT(data);
3592 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3593 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3594 data.flags = DB_DBT_MALLOC;
3595 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003596 if (!add_partial_dbt(&data, dlen, doff)) {
3597 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003598 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003599 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600
3601 MYDB_BEGIN_ALLOW_THREADS;
3602 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3603 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003604 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3605 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003606 Py_INCREF(Py_None);
3607 retval = Py_None;
3608 }
3609 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003610 retval = NULL;
3611 }
3612 else { /* Can only be used for BTrees, so no need to return int key */
3613 retval = Py_BuildValue("s#s#", key.data, key.size,
3614 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003615 FREE_DBT(data);
3616 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003617 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003618
3619 return retval;
3620}
3621
3622
3623static PyObject*
3624DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3625{
3626 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3627}
3628
3629
3630static PyObject*
3631DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3632{
3633 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3634}
3635
3636
3637static PyObject*
3638DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3639{
3640 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3641}
3642
3643
3644static PyObject*
3645DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3646{
3647 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3648}
3649
3650
3651static PyObject*
3652DBC_join_item(DBCursorObject* self, PyObject* args)
3653{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003654 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003655 DBT key, data;
3656 PyObject* retval;
3657
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003658 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003659 return NULL;
3660
3661 CHECK_CURSOR_NOT_CLOSED(self);
3662
3663 CLEAR_DBT(key);
3664 CLEAR_DBT(data);
3665 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3666 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3667 key.flags = DB_DBT_MALLOC;
3668 }
3669
3670 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003673 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3674 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003675 Py_INCREF(Py_None);
3676 retval = Py_None;
3677 }
3678 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003679 retval = NULL;
3680 }
3681 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003682 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683 FREE_DBT(key);
3684 }
3685
3686 return retval;
3687}
3688
3689
3690
3691/* --------------------------------------------------------------------- */
3692/* DBEnv methods */
3693
3694
3695static PyObject*
3696DBEnv_close(DBEnvObject* self, PyObject* args)
3697{
3698 int err, flags = 0;
3699
3700 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3701 return NULL;
3702 if (!self->closed) { /* Don't close more than once */
3703 MYDB_BEGIN_ALLOW_THREADS;
3704 err = self->db_env->close(self->db_env, flags);
3705 MYDB_END_ALLOW_THREADS;
3706 /* after calling DBEnv->close, regardless of error, this DBEnv
3707 * may not be accessed again (BerkeleyDB docs). */
3708 self->closed = 1;
3709 self->db_env = NULL;
3710 RETURN_IF_ERR();
3711 }
3712 RETURN_NONE();
3713}
3714
3715
3716static PyObject*
3717DBEnv_open(DBEnvObject* self, PyObject* args)
3718{
3719 int err, flags=0, mode=0660;
3720 char *db_home;
3721
3722 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3723 return NULL;
3724
3725 CHECK_ENV_NOT_CLOSED(self);
3726
3727 MYDB_BEGIN_ALLOW_THREADS;
3728 err = self->db_env->open(self->db_env, db_home, flags, mode);
3729 MYDB_END_ALLOW_THREADS;
3730 RETURN_IF_ERR();
3731 self->closed = 0;
3732 self->flags = flags;
3733 RETURN_NONE();
3734}
3735
3736
3737static PyObject*
3738DBEnv_remove(DBEnvObject* self, PyObject* args)
3739{
3740 int err, flags=0;
3741 char *db_home;
3742
3743 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3744 return NULL;
3745 CHECK_ENV_NOT_CLOSED(self);
3746 MYDB_BEGIN_ALLOW_THREADS;
3747 err = self->db_env->remove(self->db_env, db_home, flags);
3748 MYDB_END_ALLOW_THREADS;
3749 RETURN_IF_ERR();
3750 RETURN_NONE();
3751}
3752
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003753#if (DBVER >= 41)
3754static PyObject*
3755DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3756{
3757 int err;
3758 u_int32_t flags=0;
3759 char *file = NULL;
3760 char *database = NULL;
3761 PyObject *txnobj = NULL;
3762 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003763 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003764 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003765
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003766 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003767 &file, &database, &txnobj, &flags)) {
3768 return NULL;
3769 }
3770 if (!checkTxnObj(txnobj, &txn)) {
3771 return NULL;
3772 }
3773 CHECK_ENV_NOT_CLOSED(self);
3774 MYDB_BEGIN_ALLOW_THREADS;
3775 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3776 MYDB_END_ALLOW_THREADS;
3777 RETURN_IF_ERR();
3778 RETURN_NONE();
3779}
3780
3781static PyObject*
3782DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3783{
3784 int err;
3785 u_int32_t flags=0;
3786 char *file = NULL;
3787 char *database = NULL;
3788 char *newname = NULL;
3789 PyObject *txnobj = NULL;
3790 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003791 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003792 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003793
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003794 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003795 &file, &database, &newname, &txnobj, &flags)) {
3796 return NULL;
3797 }
3798 if (!checkTxnObj(txnobj, &txn)) {
3799 return NULL;
3800 }
3801 CHECK_ENV_NOT_CLOSED(self);
3802 MYDB_BEGIN_ALLOW_THREADS;
3803 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3804 flags);
3805 MYDB_END_ALLOW_THREADS;
3806 RETURN_IF_ERR();
3807 RETURN_NONE();
3808}
3809
3810static PyObject*
3811DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3812{
3813 int err;
3814 u_int32_t flags=0;
3815 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003816 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003817
3818 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3819 &passwd, &flags)) {
3820 return NULL;
3821 }
3822
3823 MYDB_BEGIN_ALLOW_THREADS;
3824 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3825 MYDB_END_ALLOW_THREADS;
3826
3827 RETURN_IF_ERR();
3828 RETURN_NONE();
3829}
3830#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003831
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003832#if (DBVER >= 40)
3833static PyObject*
3834DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3835{
3836 int err;
3837 u_int32_t flags=0;
3838 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003839 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003840
3841 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3842 &timeout, &flags)) {
3843 return NULL;
3844 }
3845
3846 MYDB_BEGIN_ALLOW_THREADS;
3847 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3848 MYDB_END_ALLOW_THREADS;
3849
3850 RETURN_IF_ERR();
3851 RETURN_NONE();
3852}
3853#endif /* DBVER >= 40 */
3854
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003856DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3857{
3858 int err;
3859 long shm_key = 0;
3860
3861 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3862 return NULL;
3863 CHECK_ENV_NOT_CLOSED(self);
3864
3865 err = self->db_env->set_shm_key(self->db_env, shm_key);
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3868}
3869
3870static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003871DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3872{
3873 int err, gbytes=0, bytes=0, ncache=0;
3874
3875 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3876 &gbytes, &bytes, &ncache))
3877 return NULL;
3878 CHECK_ENV_NOT_CLOSED(self);
3879
3880 MYDB_BEGIN_ALLOW_THREADS;
3881 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3882 MYDB_END_ALLOW_THREADS;
3883 RETURN_IF_ERR();
3884 RETURN_NONE();
3885}
3886
3887
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003888static PyObject*
3889DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3890{
3891 int err, flags=0, onoff=0;
3892
3893 if (!PyArg_ParseTuple(args, "ii:set_flags",
3894 &flags, &onoff))
3895 return NULL;
3896 CHECK_ENV_NOT_CLOSED(self);
3897
3898 MYDB_BEGIN_ALLOW_THREADS;
3899 err = self->db_env->set_flags(self->db_env, flags, onoff);
3900 MYDB_END_ALLOW_THREADS;
3901 RETURN_IF_ERR();
3902 RETURN_NONE();
3903}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003904
3905
3906static PyObject*
3907DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3908{
3909 int err;
3910 char *dir;
3911
3912 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3913 return NULL;
3914 CHECK_ENV_NOT_CLOSED(self);
3915
3916 MYDB_BEGIN_ALLOW_THREADS;
3917 err = self->db_env->set_data_dir(self->db_env, dir);
3918 MYDB_END_ALLOW_THREADS;
3919 RETURN_IF_ERR();
3920 RETURN_NONE();
3921}
3922
3923
3924static PyObject*
3925DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3926{
3927 int err, lg_bsize;
3928
3929 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3930 return NULL;
3931 CHECK_ENV_NOT_CLOSED(self);
3932
3933 MYDB_BEGIN_ALLOW_THREADS;
3934 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3935 MYDB_END_ALLOW_THREADS;
3936 RETURN_IF_ERR();
3937 RETURN_NONE();
3938}
3939
3940
3941static PyObject*
3942DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3943{
3944 int err;
3945 char *dir;
3946
3947 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3948 return NULL;
3949 CHECK_ENV_NOT_CLOSED(self);
3950
3951 MYDB_BEGIN_ALLOW_THREADS;
3952 err = self->db_env->set_lg_dir(self->db_env, dir);
3953 MYDB_END_ALLOW_THREADS;
3954 RETURN_IF_ERR();
3955 RETURN_NONE();
3956}
3957
3958static PyObject*
3959DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3960{
3961 int err, lg_max;
3962
3963 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3964 return NULL;
3965 CHECK_ENV_NOT_CLOSED(self);
3966
3967 MYDB_BEGIN_ALLOW_THREADS;
3968 err = self->db_env->set_lg_max(self->db_env, lg_max);
3969 MYDB_END_ALLOW_THREADS;
3970 RETURN_IF_ERR();
3971 RETURN_NONE();
3972}
3973
3974
Neal Norwitz84562352005-10-20 04:30:15 +00003975#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003976static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003977DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3978{
3979 int err, lg_max;
3980
3981 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3982 return NULL;
3983 CHECK_ENV_NOT_CLOSED(self);
3984
3985 MYDB_BEGIN_ALLOW_THREADS;
3986 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3987 MYDB_END_ALLOW_THREADS;
3988 RETURN_IF_ERR();
3989 RETURN_NONE();
3990}
Neal Norwitz84562352005-10-20 04:30:15 +00003991#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00003992
3993
3994static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003995DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3996{
3997 int err, lk_detect;
3998
3999 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4000 return NULL;
4001 CHECK_ENV_NOT_CLOSED(self);
4002
4003 MYDB_BEGIN_ALLOW_THREADS;
4004 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4005 MYDB_END_ALLOW_THREADS;
4006 RETURN_IF_ERR();
4007 RETURN_NONE();
4008}
4009
4010
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004011#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004012static PyObject*
4013DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4014{
4015 int err, max;
4016
4017 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4018 return NULL;
4019 CHECK_ENV_NOT_CLOSED(self);
4020
4021 MYDB_BEGIN_ALLOW_THREADS;
4022 err = self->db_env->set_lk_max(self->db_env, max);
4023 MYDB_END_ALLOW_THREADS;
4024 RETURN_IF_ERR();
4025 RETURN_NONE();
4026}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004027#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004028
4029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004030
4031static PyObject*
4032DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4033{
4034 int err, max;
4035
4036 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4037 return NULL;
4038 CHECK_ENV_NOT_CLOSED(self);
4039
4040 MYDB_BEGIN_ALLOW_THREADS;
4041 err = self->db_env->set_lk_max_locks(self->db_env, max);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4045}
4046
4047
4048static PyObject*
4049DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4050{
4051 int err, max;
4052
4053 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4056
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063
4064
4065static PyObject*
4066DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4067{
4068 int err, max;
4069
4070 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4071 return NULL;
4072 CHECK_ENV_NOT_CLOSED(self);
4073
4074 MYDB_BEGIN_ALLOW_THREADS;
4075 err = self->db_env->set_lk_max_objects(self->db_env, max);
4076 MYDB_END_ALLOW_THREADS;
4077 RETURN_IF_ERR();
4078 RETURN_NONE();
4079}
4080
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004081
4082static PyObject*
4083DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4084{
4085 int err, mp_mmapsize;
4086
4087 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
4098
4099static PyObject*
4100DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4101{
4102 int err;
4103 char *dir;
4104
4105 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_tmp_dir(self->db_env, dir);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
4115
4116
4117static PyObject*
4118DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4119{
4120 int flags = 0;
4121 PyObject* txnobj = NULL;
4122 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004123 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004124
4125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4126 &txnobj, &flags))
4127 return NULL;
4128
4129 if (!checkTxnObj(txnobj, &txn))
4130 return NULL;
4131 CHECK_ENV_NOT_CLOSED(self);
4132
4133 return (PyObject*)newDBTxnObject(self, txn, flags);
4134}
4135
4136
4137static PyObject*
4138DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4139{
4140 int err, kbyte=0, min=0, flags=0;
4141
4142 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4143 return NULL;
4144 CHECK_ENV_NOT_CLOSED(self);
4145
4146 MYDB_BEGIN_ALLOW_THREADS;
4147#if (DBVER >= 40)
4148 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4149#else
4150 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4151#endif
4152 MYDB_END_ALLOW_THREADS;
4153 RETURN_IF_ERR();
4154 RETURN_NONE();
4155}
4156
4157
4158static PyObject*
4159DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4160{
4161 int err, max;
4162
4163 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4164 return NULL;
4165 CHECK_ENV_NOT_CLOSED(self);
4166
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004167 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004168 RETURN_IF_ERR();
4169 RETURN_NONE();
4170}
4171
4172
4173static PyObject*
4174DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4175{
4176 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004177 long stamp;
4178 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004179
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004180 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004181 return NULL;
4182 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004183 timestamp = (time_t)stamp;
4184 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004185 RETURN_IF_ERR();
4186 RETURN_NONE();
4187}
4188
4189
4190static PyObject*
4191DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4192{
4193 int err, atype, flags=0;
4194 int aborted = 0;
4195
4196 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4197 return NULL;
4198 CHECK_ENV_NOT_CLOSED(self);
4199
4200 MYDB_BEGIN_ALLOW_THREADS;
4201#if (DBVER >= 40)
4202 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4203#else
4204 err = lock_detect(self->db_env, flags, atype, &aborted);
4205#endif
4206 MYDB_END_ALLOW_THREADS;
4207 RETURN_IF_ERR();
4208 return PyInt_FromLong(aborted);
4209}
4210
4211
4212static PyObject*
4213DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4214{
4215 int flags=0;
4216 int locker, lock_mode;
4217 DBT obj;
4218 PyObject* objobj;
4219
4220 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4221 return NULL;
4222
4223
4224 if (!make_dbt(objobj, &obj))
4225 return NULL;
4226
4227 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4228}
4229
4230
4231static PyObject*
4232DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4233{
4234 int err;
4235 u_int32_t theID;
4236
4237 if (!PyArg_ParseTuple(args, ":lock_id"))
4238 return NULL;
4239
4240 CHECK_ENV_NOT_CLOSED(self);
4241 MYDB_BEGIN_ALLOW_THREADS;
4242#if (DBVER >= 40)
4243 err = self->db_env->lock_id(self->db_env, &theID);
4244#else
4245 err = lock_id(self->db_env, &theID);
4246#endif
4247 MYDB_END_ALLOW_THREADS;
4248 RETURN_IF_ERR();
4249
4250 return PyInt_FromLong((long)theID);
4251}
4252
4253
4254static PyObject*
4255DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4256{
4257 int err;
4258 DBLockObject* dblockobj;
4259
4260 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4261 return NULL;
4262
4263 CHECK_ENV_NOT_CLOSED(self);
4264 MYDB_BEGIN_ALLOW_THREADS;
4265#if (DBVER >= 40)
4266 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4267#else
4268 err = lock_put(self->db_env, &dblockobj->lock);
4269#endif
4270 MYDB_END_ALLOW_THREADS;
4271 RETURN_IF_ERR();
4272 RETURN_NONE();
4273}
4274
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004275#if (DBVER >= 44)
4276static PyObject*
4277DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4278{
4279 int err;
4280 char *file;
4281 u_int32_t flags = 0;
4282 static char* kwnames[] = { "file", "flags", NULL};
4283
4284 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4285 &file, &flags))
4286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
4288
4289 MYDB_BEGIN_ALLOW_THREADS;
4290 err = self->db_env->lsn_reset(self->db_env, file, flags);
4291 MYDB_END_ALLOW_THREADS;
4292 RETURN_IF_ERR();
4293 RETURN_NONE();
4294}
4295#endif /* DBVER >= 4.4 */
4296
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004297#if (DBVER >= 40)
4298static PyObject*
4299DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4300{
4301 int err;
4302 DB_LOG_STAT* statp = NULL;
4303 PyObject* d = NULL;
4304 u_int32_t flags = 0;
4305
4306 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4307 return NULL;
4308 CHECK_ENV_NOT_CLOSED(self);
4309
4310 MYDB_BEGIN_ALLOW_THREADS;
4311 err = self->db_env->log_stat(self->db_env, &statp, flags);
4312 MYDB_END_ALLOW_THREADS;
4313 RETURN_IF_ERR();
4314
4315 /* Turn the stat structure into a dictionary */
4316 d = PyDict_New();
4317 if (d == NULL) {
4318 if (statp)
4319 free(statp);
4320 return NULL;
4321 }
4322
4323#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4324
4325 MAKE_ENTRY(magic);
4326 MAKE_ENTRY(version);
4327 MAKE_ENTRY(mode);
4328 MAKE_ENTRY(lg_bsize);
4329#if (DBVER >= 44)
4330 MAKE_ENTRY(lg_size);
4331 MAKE_ENTRY(record);
4332#endif
4333#if (DBVER <= 40)
4334 MAKE_ENTRY(lg_max);
4335#endif
4336 MAKE_ENTRY(w_mbytes);
4337 MAKE_ENTRY(w_bytes);
4338 MAKE_ENTRY(wc_mbytes);
4339 MAKE_ENTRY(wc_bytes);
4340 MAKE_ENTRY(wcount);
4341 MAKE_ENTRY(wcount_fill);
4342#if (DBVER >= 44)
4343 MAKE_ENTRY(rcount);
4344#endif
4345 MAKE_ENTRY(scount);
4346 MAKE_ENTRY(cur_file);
4347 MAKE_ENTRY(cur_offset);
4348 MAKE_ENTRY(disk_file);
4349 MAKE_ENTRY(disk_offset);
4350 MAKE_ENTRY(maxcommitperflush);
4351 MAKE_ENTRY(mincommitperflush);
4352 MAKE_ENTRY(regsize);
4353 MAKE_ENTRY(region_wait);
4354 MAKE_ENTRY(region_nowait);
4355
4356#undef MAKE_ENTRY
4357 free(statp);
4358 return d;
4359} /* DBEnv_log_stat */
4360#endif /* DBVER >= 4.0 for log_stat method */
4361
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004362
4363static PyObject*
4364DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4365{
4366 int err;
4367 DB_LOCK_STAT* sp;
4368 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004369 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004370
4371 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4372 return NULL;
4373 CHECK_ENV_NOT_CLOSED(self);
4374
4375 MYDB_BEGIN_ALLOW_THREADS;
4376#if (DBVER >= 40)
4377 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4378#else
4379#if (DBVER >= 33)
4380 err = lock_stat(self->db_env, &sp);
4381#else
4382 err = lock_stat(self->db_env, &sp, NULL);
4383#endif
4384#endif
4385 MYDB_END_ALLOW_THREADS;
4386 RETURN_IF_ERR();
4387
4388 /* Turn the stat structure into a dictionary */
4389 d = PyDict_New();
4390 if (d == NULL) {
4391 free(sp);
4392 return NULL;
4393 }
4394
4395#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4396
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004397#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004398 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004399#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004400 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004401 MAKE_ENTRY(maxlocks);
4402 MAKE_ENTRY(maxlockers);
4403 MAKE_ENTRY(maxobjects);
4404 MAKE_ENTRY(nlocks);
4405 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004406 MAKE_ENTRY(nlockers);
4407 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004408 MAKE_ENTRY(nobjects);
4409 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004410 MAKE_ENTRY(nrequests);
4411 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004412#if (DBVER < 44)
4413 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004414 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004415#else
4416 MAKE_ENTRY(lock_nowait);
4417 MAKE_ENTRY(lock_wait);
4418#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004419 MAKE_ENTRY(ndeadlocks);
4420 MAKE_ENTRY(regsize);
4421 MAKE_ENTRY(region_wait);
4422 MAKE_ENTRY(region_nowait);
4423
4424#undef MAKE_ENTRY
4425 free(sp);
4426 return d;
4427}
4428
4429
4430static PyObject*
4431DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4432{
4433 int flags=0;
4434 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004435 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004436 PyObject* list;
4437 PyObject* item = NULL;
4438
4439 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4440 return NULL;
4441
4442 CHECK_ENV_NOT_CLOSED(self);
4443 MYDB_BEGIN_ALLOW_THREADS;
4444#if (DBVER >= 40)
4445 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4446#elif (DBVER == 33)
4447 err = log_archive(self->db_env, &log_list, flags);
4448#else
4449 err = log_archive(self->db_env, &log_list, flags, NULL);
4450#endif
4451 MYDB_END_ALLOW_THREADS;
4452 RETURN_IF_ERR();
4453
Gregory P. Smithbad47452006-06-05 00:33:35 +00004454 list = PyList_New(0);
4455 if (list == NULL) {
4456 if (log_list)
4457 free(log_list);
4458 return NULL;
4459 }
4460
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004461 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004462 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004463 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4464 item = PyString_FromString (*log_list);
4465 if (item == NULL) {
4466 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004467 list = NULL;
4468 break;
4469 }
4470 PyList_Append(list, item);
4471 Py_DECREF(item);
4472 }
4473 free(log_list_start);
4474 }
4475 return list;
4476}
4477
4478
4479static PyObject*
4480DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4481{
4482 int err;
4483 DB_TXN_STAT* sp;
4484 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004485 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004486
4487 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4488 return NULL;
4489 CHECK_ENV_NOT_CLOSED(self);
4490
4491 MYDB_BEGIN_ALLOW_THREADS;
4492#if (DBVER >= 40)
4493 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4494#elif (DBVER == 33)
4495 err = txn_stat(self->db_env, &sp);
4496#else
4497 err = txn_stat(self->db_env, &sp, NULL);
4498#endif
4499 MYDB_END_ALLOW_THREADS;
4500 RETURN_IF_ERR();
4501
4502 /* Turn the stat structure into a dictionary */
4503 d = PyDict_New();
4504 if (d == NULL) {
4505 free(sp);
4506 return NULL;
4507 }
4508
4509#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004510#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004511
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004512 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004513 MAKE_ENTRY(last_txnid);
4514 MAKE_ENTRY(maxtxns);
4515 MAKE_ENTRY(nactive);
4516 MAKE_ENTRY(maxnactive);
4517 MAKE_ENTRY(nbegins);
4518 MAKE_ENTRY(naborts);
4519 MAKE_ENTRY(ncommits);
4520 MAKE_ENTRY(regsize);
4521 MAKE_ENTRY(region_wait);
4522 MAKE_ENTRY(region_nowait);
4523
4524#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004525#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004526 free(sp);
4527 return d;
4528}
4529
4530
4531static PyObject*
4532DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4533{
4534 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004535 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004536
4537 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4538 return NULL;
4539 CHECK_ENV_NOT_CLOSED(self);
4540
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004541 if (self->moduleFlags.getReturnsNone)
4542 ++oldValue;
4543 if (self->moduleFlags.cursorSetReturnsNone)
4544 ++oldValue;
4545 self->moduleFlags.getReturnsNone = (flags >= 1);
4546 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547 return PyInt_FromLong(oldValue);
4548}
4549
4550
4551/* --------------------------------------------------------------------- */
4552/* DBTxn methods */
4553
4554
4555static PyObject*
4556DBTxn_commit(DBTxnObject* self, PyObject* args)
4557{
4558 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004559 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560
4561 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4562 return NULL;
4563
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004564 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004565 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4566 "after txn_commit or txn_abort");
4567 PyErr_SetObject(DBError, t);
4568 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004569 return NULL;
4570 }
4571 txn = self->txn;
4572 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004573 MYDB_BEGIN_ALLOW_THREADS;
4574#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004575 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004577 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004578#endif
4579 MYDB_END_ALLOW_THREADS;
4580 RETURN_IF_ERR();
4581 RETURN_NONE();
4582}
4583
4584static PyObject*
4585DBTxn_prepare(DBTxnObject* self, PyObject* args)
4586{
4587#if (DBVER >= 33)
4588 int err;
4589 char* gid=NULL;
4590 int gid_size=0;
4591
4592 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4593 return NULL;
4594
4595 if (gid_size != DB_XIDDATASIZE) {
4596 PyErr_SetString(PyExc_TypeError,
4597 "gid must be DB_XIDDATASIZE bytes long");
4598 return NULL;
4599 }
4600
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004601 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004602 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4603 "after txn_commit or txn_abort");
4604 PyErr_SetObject(DBError, t);
4605 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004606 return NULL;
4607 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608 MYDB_BEGIN_ALLOW_THREADS;
4609#if (DBVER >= 40)
4610 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4611#else
4612 err = txn_prepare(self->txn, (u_int8_t*)gid);
4613#endif
4614 MYDB_END_ALLOW_THREADS;
4615 RETURN_IF_ERR();
4616 RETURN_NONE();
4617#else
4618 int err;
4619
4620 if (!PyArg_ParseTuple(args, ":prepare"))
4621 return NULL;
4622
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004623 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004624 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4625 "after txn_commit or txn_abort");
4626 PyErr_SetObject(DBError, t);
4627 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004628 return NULL;
4629 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630 MYDB_BEGIN_ALLOW_THREADS;
4631 err = txn_prepare(self->txn);
4632 MYDB_END_ALLOW_THREADS;
4633 RETURN_IF_ERR();
4634 RETURN_NONE();
4635#endif
4636}
4637
4638
4639static PyObject*
4640DBTxn_abort(DBTxnObject* self, PyObject* args)
4641{
4642 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004643 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004644
4645 if (!PyArg_ParseTuple(args, ":abort"))
4646 return NULL;
4647
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004648 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004649 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4650 "after txn_commit or txn_abort");
4651 PyErr_SetObject(DBError, t);
4652 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004653 return NULL;
4654 }
4655 txn = self->txn;
4656 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004657 MYDB_BEGIN_ALLOW_THREADS;
4658#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004659 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004660#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004661 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004662#endif
4663 MYDB_END_ALLOW_THREADS;
4664 RETURN_IF_ERR();
4665 RETURN_NONE();
4666}
4667
4668
4669static PyObject*
4670DBTxn_id(DBTxnObject* self, PyObject* args)
4671{
4672 int id;
4673
4674 if (!PyArg_ParseTuple(args, ":id"))
4675 return NULL;
4676
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004677 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004678 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4679 "after txn_commit or txn_abort");
4680 PyErr_SetObject(DBError, t);
4681 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004682 return NULL;
4683 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684 MYDB_BEGIN_ALLOW_THREADS;
4685#if (DBVER >= 40)
4686 id = self->txn->id(self->txn);
4687#else
4688 id = txn_id(self->txn);
4689#endif
4690 MYDB_END_ALLOW_THREADS;
4691 return PyInt_FromLong(id);
4692}
4693
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004694#if (DBVER >= 43)
4695/* --------------------------------------------------------------------- */
4696/* DBSequence methods */
4697
4698
4699static PyObject*
4700DBSequence_close(DBSequenceObject* self, PyObject* args)
4701{
4702 int err, flags=0;
4703 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4704 return NULL;
4705 CHECK_SEQUENCE_NOT_CLOSED(self)
4706
4707 MYDB_BEGIN_ALLOW_THREADS
4708 err = self->sequence->close(self->sequence, flags);
4709 self->sequence = NULL;
4710 MYDB_END_ALLOW_THREADS
4711
4712 RETURN_IF_ERR();
4713
4714 RETURN_NONE();
4715}
4716
4717static PyObject*
4718DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4719{
4720 int err, flags = 0;
4721 int delta = 1;
4722 db_seq_t value;
4723 PyObject *txnobj = NULL;
4724 DB_TXN *txn = NULL;
4725 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4726 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4727 return NULL;
4728 CHECK_SEQUENCE_NOT_CLOSED(self)
4729
4730 if (!checkTxnObj(txnobj, &txn))
4731 return NULL;
4732
4733 MYDB_BEGIN_ALLOW_THREADS
4734 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4735 MYDB_END_ALLOW_THREADS
4736
4737 RETURN_IF_ERR();
4738 return PyLong_FromLongLong(value);
4739
4740}
4741
4742static PyObject*
4743DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4744{
4745 if (!PyArg_ParseTuple(args,":get_dbp"))
4746 return NULL;
4747 CHECK_SEQUENCE_NOT_CLOSED(self)
4748 Py_INCREF(self->mydb);
4749 return (PyObject* )self->mydb;
4750}
4751
4752static PyObject*
4753DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4754{
4755 int err;
4756 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00004757 PyObject *retval = NULL;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004758 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004759 CHECK_SEQUENCE_NOT_CLOSED(self)
4760 MYDB_BEGIN_ALLOW_THREADS
4761 err = self->sequence->get_key(self->sequence, &key);
4762 MYDB_END_ALLOW_THREADS
4763
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004764 if (!err)
4765 retval = PyString_FromStringAndSize(key.data, key.size);
4766
4767 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004768 RETURN_IF_ERR();
4769
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004770 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004771}
4772
4773static PyObject*
4774DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4775{
4776 int err;
4777 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004778 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004779 return NULL;
4780 CHECK_SEQUENCE_NOT_CLOSED(self)
4781
4782 MYDB_BEGIN_ALLOW_THREADS
4783 err = self->sequence->initial_value(self->sequence, value);
4784 MYDB_END_ALLOW_THREADS
4785
4786 RETURN_IF_ERR();
4787
4788 RETURN_NONE();
4789}
4790
4791static PyObject*
4792DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4793{
4794 int err, flags = 0;
4795 PyObject* keyobj;
4796 PyObject *txnobj = NULL;
4797 DB_TXN *txn = NULL;
4798 DBT key;
4799
4800 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004802 return NULL;
4803
4804 if (!checkTxnObj(txnobj, &txn))
4805 return NULL;
4806
4807 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4808 return NULL;
4809
4810 MYDB_BEGIN_ALLOW_THREADS
4811 err = self->sequence->open(self->sequence, txn, &key, flags);
4812 MYDB_END_ALLOW_THREADS
4813
4814 CLEAR_DBT(key);
4815 RETURN_IF_ERR();
4816
4817 RETURN_NONE();
4818}
4819
4820static PyObject*
4821DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4822{
4823 int err, flags = 0;
4824 PyObject *txnobj = NULL;
4825 DB_TXN *txn = NULL;
4826
4827 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004829 return NULL;
4830
4831 if (!checkTxnObj(txnobj, &txn))
4832 return NULL;
4833
4834 CHECK_SEQUENCE_NOT_CLOSED(self)
4835
4836 MYDB_BEGIN_ALLOW_THREADS
4837 err = self->sequence->remove(self->sequence, txn, flags);
4838 MYDB_END_ALLOW_THREADS
4839
4840 RETURN_IF_ERR();
4841 RETURN_NONE();
4842}
4843
4844static PyObject*
4845DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4846{
4847 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004848 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004849 return NULL;
4850 CHECK_SEQUENCE_NOT_CLOSED(self)
4851
4852 MYDB_BEGIN_ALLOW_THREADS
4853 err = self->sequence->set_cachesize(self->sequence, size);
4854 MYDB_END_ALLOW_THREADS
4855
4856 RETURN_IF_ERR();
4857 RETURN_NONE();
4858}
4859
4860static PyObject*
4861DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4862{
4863 int err, size;
4864 if (!PyArg_ParseTuple(args,":get_cachesize"))
4865 return NULL;
4866 CHECK_SEQUENCE_NOT_CLOSED(self)
4867
4868 MYDB_BEGIN_ALLOW_THREADS
4869 err = self->sequence->get_cachesize(self->sequence, &size);
4870 MYDB_END_ALLOW_THREADS
4871
4872 RETURN_IF_ERR();
4873 return PyInt_FromLong(size);
4874}
4875
4876static PyObject*
4877DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4878{
4879 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004880 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004881 return NULL;
4882 CHECK_SEQUENCE_NOT_CLOSED(self)
4883
4884 MYDB_BEGIN_ALLOW_THREADS
4885 err = self->sequence->set_flags(self->sequence, flags);
4886 MYDB_END_ALLOW_THREADS
4887
4888 RETURN_IF_ERR();
4889 RETURN_NONE();
4890
4891}
4892
4893static PyObject*
4894DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4895{
4896 unsigned int flags;
4897 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004898 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004899 return NULL;
4900 CHECK_SEQUENCE_NOT_CLOSED(self)
4901
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->sequence->get_flags(self->sequence, &flags);
4904 MYDB_END_ALLOW_THREADS
4905
4906 RETURN_IF_ERR();
4907 return PyInt_FromLong((int)flags);
4908}
4909
4910static PyObject*
4911DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4912{
4913 int err;
4914 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004915 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004916 return NULL;
4917 CHECK_SEQUENCE_NOT_CLOSED(self)
4918
4919 MYDB_BEGIN_ALLOW_THREADS
4920 err = self->sequence->set_range(self->sequence, min, max);
4921 MYDB_END_ALLOW_THREADS
4922
4923 RETURN_IF_ERR();
4924 RETURN_NONE();
4925}
4926
4927static PyObject*
4928DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4929{
4930 int err;
4931 db_seq_t min, max;
4932 if (!PyArg_ParseTuple(args,":get_range"))
4933 return NULL;
4934 CHECK_SEQUENCE_NOT_CLOSED(self)
4935
4936 MYDB_BEGIN_ALLOW_THREADS
4937 err = self->sequence->get_range(self->sequence, &min, &max);
4938 MYDB_END_ALLOW_THREADS
4939
4940 RETURN_IF_ERR();
4941 return Py_BuildValue("(LL)", min, max);
4942}
4943
4944static PyObject*
4945DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4946{
4947 int err, flags = 0;
4948 DB_SEQUENCE_STAT* sp = NULL;
4949 PyObject* dict_stat;
4950 static char* kwnames[] = {"flags", NULL };
4951 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4952 return NULL;
4953 CHECK_SEQUENCE_NOT_CLOSED(self);
4954
4955 MYDB_BEGIN_ALLOW_THREADS;
4956 err = self->sequence->stat(self->sequence, &sp, flags);
4957 MYDB_END_ALLOW_THREADS;
4958 RETURN_IF_ERR();
4959
4960 if ((dict_stat = PyDict_New()) == NULL) {
4961 free(sp);
4962 return NULL;
4963 }
4964
4965
4966#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4967#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4968
4969 MAKE_INT_ENTRY(wait);
4970 MAKE_INT_ENTRY(nowait);
4971 MAKE_LONG_LONG_ENTRY(current);
4972 MAKE_LONG_LONG_ENTRY(value);
4973 MAKE_LONG_LONG_ENTRY(last_value);
4974 MAKE_LONG_LONG_ENTRY(min);
4975 MAKE_LONG_LONG_ENTRY(max);
4976 MAKE_INT_ENTRY(cache_size);
4977 MAKE_INT_ENTRY(flags);
4978
4979#undef MAKE_INT_ENTRY
4980#undef MAKE_LONG_LONG_ENTRY
4981
4982 free(sp);
4983 return dict_stat;
4984}
4985#endif
4986
4987
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004988/* --------------------------------------------------------------------- */
4989/* Method definition tables and type objects */
4990
4991static PyMethodDef DB_methods[] = {
4992 {"append", (PyCFunction)DB_append, METH_VARARGS},
4993#if (DBVER >= 33)
4994 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4995#endif
4996 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004997 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4998 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004999 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5000 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5001 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5002 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005003#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005004 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005005#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005006 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5007 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5008 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5009 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5010 {"join", (PyCFunction)DB_join, METH_VARARGS},
5011 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5012 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5013 {"items", (PyCFunction)DB_items, METH_VARARGS},
5014 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5015 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5016 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5017 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5018 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5019 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005020#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005021 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005022#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005023 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005024#if (DBVER >= 41)
5025 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5026#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005027 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5028 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5029 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5030 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5031 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5032 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5033 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5034 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5035 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005036 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005037 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005038 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5039#if (DBVER >= 33)
5040 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5041#endif
5042 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5043 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5044 {"values", (PyCFunction)DB_values, METH_VARARGS},
5045 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5046 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5047 {NULL, NULL} /* sentinel */
5048};
5049
5050
5051static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005052 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005053 (binaryfunc)DB_subscript, /*mp_subscript*/
5054 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5055};
5056
5057
5058static PyMethodDef DBCursor_methods[] = {
5059 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5060 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5061 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5062 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5063 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5064 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5065 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005066#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005067 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005068#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005069 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5070 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5071 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5072 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5073 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5074 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5075 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5076 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005077 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005078 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005079 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5080 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5081 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5082 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5083 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5084 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5085 {NULL, NULL} /* sentinel */
5086};
5087
5088
5089static PyMethodDef DBEnv_methods[] = {
5090 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5091 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5092 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005093#if (DBVER >= 41)
5094 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5095 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5096 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5097#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005098#if (DBVER >= 40)
5099 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5100#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005101 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005102 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5103 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005104 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005105 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5106 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5107 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005108#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005109 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005110#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005111 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005112#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005113 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005114#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005115 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5116 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5117 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005118 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5119 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5120 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5121 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5122 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5123 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005124 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005125 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5126 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5127 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5128 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5129 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5130 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005131#if (DBVER >= 40)
5132 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5133#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005134#if (DBVER >= 44)
5135 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5136#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005137 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5138 {NULL, NULL} /* sentinel */
5139};
5140
5141
5142static PyMethodDef DBTxn_methods[] = {
5143 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5144 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5145 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5146 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5147 {NULL, NULL} /* sentinel */
5148};
5149
5150
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005151#if (DBVER >= 43)
5152static PyMethodDef DBSequence_methods[] = {
5153 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5154 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5155 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5156 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005157 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5158 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5159 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5160 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5161 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5162 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5163 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5164 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5165 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5166 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5167 {NULL, NULL} /* sentinel */
5168};
5169#endif
5170
5171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005172static PyObject*
5173DB_getattr(DBObject* self, char *name)
5174{
5175 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5176}
5177
5178
5179static PyObject*
5180DBEnv_getattr(DBEnvObject* self, char *name)
5181{
5182 if (!strcmp(name, "db_home")) {
5183 CHECK_ENV_NOT_CLOSED(self);
5184 if (self->db_env->db_home == NULL) {
5185 RETURN_NONE();
5186 }
5187 return PyString_FromString(self->db_env->db_home);
5188 }
5189
5190 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5191}
5192
5193
5194static PyObject*
5195DBCursor_getattr(DBCursorObject* self, char *name)
5196{
5197 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5198}
5199
5200static PyObject*
5201DBTxn_getattr(DBTxnObject* self, char *name)
5202{
5203 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5204}
5205
5206static PyObject*
5207DBLock_getattr(DBLockObject* self, char *name)
5208{
5209 return NULL;
5210}
5211
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005212#if (DBVER >= 43)
5213static PyObject*
5214DBSequence_getattr(DBSequenceObject* self, char *name)
5215{
5216 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5217}
5218#endif
5219
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005220statichere PyTypeObject DB_Type = {
5221 PyObject_HEAD_INIT(NULL)
5222 0, /*ob_size*/
5223 "DB", /*tp_name*/
5224 sizeof(DBObject), /*tp_basicsize*/
5225 0, /*tp_itemsize*/
5226 /* methods */
5227 (destructor)DB_dealloc, /*tp_dealloc*/
5228 0, /*tp_print*/
5229 (getattrfunc)DB_getattr, /*tp_getattr*/
5230 0, /*tp_setattr*/
5231 0, /*tp_compare*/
5232 0, /*tp_repr*/
5233 0, /*tp_as_number*/
5234 0, /*tp_as_sequence*/
5235 &DB_mapping,/*tp_as_mapping*/
5236 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005237 0, /* tp_call */
5238 0, /* tp_str */
5239 0, /* tp_getattro */
5240 0, /* tp_setattro */
5241 0, /* tp_as_buffer */
5242 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5243 0, /* tp_doc */
5244 0, /* tp_traverse */
5245 0, /* tp_clear */
5246 0, /* tp_richcompare */
5247 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005248};
5249
5250
5251statichere PyTypeObject DBCursor_Type = {
5252 PyObject_HEAD_INIT(NULL)
5253 0, /*ob_size*/
5254 "DBCursor", /*tp_name*/
5255 sizeof(DBCursorObject), /*tp_basicsize*/
5256 0, /*tp_itemsize*/
5257 /* methods */
5258 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5259 0, /*tp_print*/
5260 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5261 0, /*tp_setattr*/
5262 0, /*tp_compare*/
5263 0, /*tp_repr*/
5264 0, /*tp_as_number*/
5265 0, /*tp_as_sequence*/
5266 0, /*tp_as_mapping*/
5267 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005268 0, /* tp_call */
5269 0, /* tp_str */
5270 0, /* tp_getattro */
5271 0, /* tp_setattro */
5272 0, /* tp_as_buffer */
5273 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5274 0, /* tp_doc */
5275 0, /* tp_traverse */
5276 0, /* tp_clear */
5277 0, /* tp_richcompare */
5278 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005279};
5280
5281
5282statichere PyTypeObject DBEnv_Type = {
5283 PyObject_HEAD_INIT(NULL)
5284 0, /*ob_size*/
5285 "DBEnv", /*tp_name*/
5286 sizeof(DBEnvObject), /*tp_basicsize*/
5287 0, /*tp_itemsize*/
5288 /* methods */
5289 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5290 0, /*tp_print*/
5291 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5292 0, /*tp_setattr*/
5293 0, /*tp_compare*/
5294 0, /*tp_repr*/
5295 0, /*tp_as_number*/
5296 0, /*tp_as_sequence*/
5297 0, /*tp_as_mapping*/
5298 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005299 0, /* tp_call */
5300 0, /* tp_str */
5301 0, /* tp_getattro */
5302 0, /* tp_setattro */
5303 0, /* tp_as_buffer */
5304 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5305 0, /* tp_doc */
5306 0, /* tp_traverse */
5307 0, /* tp_clear */
5308 0, /* tp_richcompare */
5309 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005310};
5311
5312statichere PyTypeObject DBTxn_Type = {
5313 PyObject_HEAD_INIT(NULL)
5314 0, /*ob_size*/
5315 "DBTxn", /*tp_name*/
5316 sizeof(DBTxnObject), /*tp_basicsize*/
5317 0, /*tp_itemsize*/
5318 /* methods */
5319 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5320 0, /*tp_print*/
5321 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5322 0, /*tp_setattr*/
5323 0, /*tp_compare*/
5324 0, /*tp_repr*/
5325 0, /*tp_as_number*/
5326 0, /*tp_as_sequence*/
5327 0, /*tp_as_mapping*/
5328 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005329 0, /* tp_call */
5330 0, /* tp_str */
5331 0, /* tp_getattro */
5332 0, /* tp_setattro */
5333 0, /* tp_as_buffer */
5334 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5335 0, /* tp_doc */
5336 0, /* tp_traverse */
5337 0, /* tp_clear */
5338 0, /* tp_richcompare */
5339 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005340};
5341
5342
5343statichere PyTypeObject DBLock_Type = {
5344 PyObject_HEAD_INIT(NULL)
5345 0, /*ob_size*/
5346 "DBLock", /*tp_name*/
5347 sizeof(DBLockObject), /*tp_basicsize*/
5348 0, /*tp_itemsize*/
5349 /* methods */
5350 (destructor)DBLock_dealloc, /*tp_dealloc*/
5351 0, /*tp_print*/
5352 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5353 0, /*tp_setattr*/
5354 0, /*tp_compare*/
5355 0, /*tp_repr*/
5356 0, /*tp_as_number*/
5357 0, /*tp_as_sequence*/
5358 0, /*tp_as_mapping*/
5359 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005360 0, /* tp_call */
5361 0, /* tp_str */
5362 0, /* tp_getattro */
5363 0, /* tp_setattro */
5364 0, /* tp_as_buffer */
5365 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5366 0, /* tp_doc */
5367 0, /* tp_traverse */
5368 0, /* tp_clear */
5369 0, /* tp_richcompare */
5370 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005371};
5372
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005373#if (DBVER >= 43)
5374statichere PyTypeObject DBSequence_Type = {
5375 PyObject_HEAD_INIT(NULL)
5376 0, /*ob_size*/
5377 "DBSequence", /*tp_name*/
5378 sizeof(DBSequenceObject), /*tp_basicsize*/
5379 0, /*tp_itemsize*/
5380 /* methods */
5381 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5382 0, /*tp_print*/
5383 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5384 0, /*tp_setattr*/
5385 0, /*tp_compare*/
5386 0, /*tp_repr*/
5387 0, /*tp_as_number*/
5388 0, /*tp_as_sequence*/
5389 0, /*tp_as_mapping*/
5390 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005391 0, /* tp_call */
5392 0, /* tp_str */
5393 0, /* tp_getattro */
5394 0, /* tp_setattro */
5395 0, /* tp_as_buffer */
5396 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5397 0, /* tp_doc */
5398 0, /* tp_traverse */
5399 0, /* tp_clear */
5400 0, /* tp_richcompare */
5401 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005402};
5403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005404
5405/* --------------------------------------------------------------------- */
5406/* Module-level functions */
5407
5408static PyObject*
5409DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5410{
5411 PyObject* dbenvobj = NULL;
5412 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005413 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005414
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005415 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5416 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005417 return NULL;
5418 if (dbenvobj == Py_None)
5419 dbenvobj = NULL;
5420 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5421 makeTypeError("DBEnv", dbenvobj);
5422 return NULL;
5423 }
5424
5425 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5426}
5427
5428
5429static PyObject*
5430DBEnv_construct(PyObject* self, PyObject* args)
5431{
5432 int flags = 0;
5433 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5434 return (PyObject* )newDBEnvObject(flags);
5435}
5436
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005437#if (DBVER >= 43)
5438static PyObject*
5439DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5440{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005441 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005442 int flags = 0;
5443 static char* kwnames[] = { "db", "flags", NULL};
5444
5445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5446 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005447 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005448 makeTypeError("DB", dbobj);
5449 return NULL;
5450 }
5451 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5452}
5453#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005454
5455static char bsddb_version_doc[] =
5456"Returns a tuple of major, minor, and patch release numbers of the\n\
5457underlying DB library.";
5458
5459static PyObject*
5460bsddb_version(PyObject* self, PyObject* args)
5461{
5462 int major, minor, patch;
5463
5464 if (!PyArg_ParseTuple(args, ":version"))
5465 return NULL;
5466 db_version(&major, &minor, &patch);
5467 return Py_BuildValue("(iii)", major, minor, patch);
5468}
5469
5470
5471/* List of functions defined in the module */
5472
5473static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005474 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5475 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5476#if (DBVER >= 43)
5477 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5478#endif
5479 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005480 {NULL, NULL} /* sentinel */
5481};
5482
Gregory P. Smith39250532007-10-09 06:02:21 +00005483/* API structure */
5484static BSDDB_api bsddb_api;
5485
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005486
5487/* --------------------------------------------------------------------- */
5488/* Module initialization */
5489
5490
5491/* Convenience routine to export an integer value.
5492 * Errors are silently ignored, for better or for worse...
5493 */
5494#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5495
Gregory P. Smith41631e82003-09-21 00:08:14 +00005496#define MODULE_NAME_MAX_LEN 11
5497static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005498
5499DL_EXPORT(void) init_bsddb(void)
5500{
5501 PyObject* m;
5502 PyObject* d;
5503 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5504 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5505 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005506 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005507
5508 /* Initialize the type of the new type objects here; doing it here
5509 is required for portability to Windows without requiring C++. */
Martin v. Löwis68192102007-07-21 06:55:02 +00005510 Py_Type(&DB_Type) = &PyType_Type;
5511 Py_Type(&DBCursor_Type) = &PyType_Type;
5512 Py_Type(&DBEnv_Type) = &PyType_Type;
5513 Py_Type(&DBTxn_Type) = &PyType_Type;
5514 Py_Type(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005515#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +00005516 Py_Type(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005518
5519
Mark Hammonda69d4092003-04-22 23:13:27 +00005520#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005521 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005522 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005523#endif
5524
5525 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005526 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005527 if (m == NULL)
5528 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005529
5530 /* Add some symbolic constants to the module */
5531 d = PyModule_GetDict(m);
5532 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5533 PyDict_SetItemString(d, "cvsid", cvsid_s);
5534 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5535 Py_DECREF(pybsddb_version_s);
5536 pybsddb_version_s = NULL;
5537 Py_DECREF(cvsid_s);
5538 cvsid_s = NULL;
5539 Py_DECREF(db_version_s);
5540 db_version_s = NULL;
5541
5542 ADD_INT(d, DB_VERSION_MAJOR);
5543 ADD_INT(d, DB_VERSION_MINOR);
5544 ADD_INT(d, DB_VERSION_PATCH);
5545
5546 ADD_INT(d, DB_MAX_PAGES);
5547 ADD_INT(d, DB_MAX_RECORDS);
5548
Gregory P. Smith41631e82003-09-21 00:08:14 +00005549#if (DBVER >= 42)
5550 ADD_INT(d, DB_RPCCLIENT);
5551#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005552 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005553 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5554 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5555#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005556 ADD_INT(d, DB_XA_CREATE);
5557
5558 ADD_INT(d, DB_CREATE);
5559 ADD_INT(d, DB_NOMMAP);
5560 ADD_INT(d, DB_THREAD);
5561
5562 ADD_INT(d, DB_FORCE);
5563 ADD_INT(d, DB_INIT_CDB);
5564 ADD_INT(d, DB_INIT_LOCK);
5565 ADD_INT(d, DB_INIT_LOG);
5566 ADD_INT(d, DB_INIT_MPOOL);
5567 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005568 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005569
5570 ADD_INT(d, DB_RECOVER);
5571 ADD_INT(d, DB_RECOVER_FATAL);
5572 ADD_INT(d, DB_TXN_NOSYNC);
5573 ADD_INT(d, DB_USE_ENVIRON);
5574 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5575
5576 ADD_INT(d, DB_LOCKDOWN);
5577 ADD_INT(d, DB_PRIVATE);
5578 ADD_INT(d, DB_SYSTEM_MEM);
5579
5580 ADD_INT(d, DB_TXN_SYNC);
5581 ADD_INT(d, DB_TXN_NOWAIT);
5582
5583 ADD_INT(d, DB_EXCL);
5584 ADD_INT(d, DB_FCNTL_LOCKING);
5585 ADD_INT(d, DB_ODDFILESIZE);
5586 ADD_INT(d, DB_RDWRMASTER);
5587 ADD_INT(d, DB_RDONLY);
5588 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005589 ADD_INT(d, DB_EXTENT);
5590 ADD_INT(d, DB_CDB_ALLDB);
5591 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005592 ADD_INT(d, DB_UPGRADE);
5593
5594 ADD_INT(d, DB_AGGRESSIVE);
5595 ADD_INT(d, DB_NOORDERCHK);
5596 ADD_INT(d, DB_ORDERCHKONLY);
5597 ADD_INT(d, DB_PR_PAGE);
5598#if ! (DBVER >= 33)
5599 ADD_INT(d, DB_VRFY_FLAGMASK);
5600 ADD_INT(d, DB_PR_HEADERS);
5601#endif
5602 ADD_INT(d, DB_PR_RECOVERYTEST);
5603 ADD_INT(d, DB_SALVAGE);
5604
5605 ADD_INT(d, DB_LOCK_NORUN);
5606 ADD_INT(d, DB_LOCK_DEFAULT);
5607 ADD_INT(d, DB_LOCK_OLDEST);
5608 ADD_INT(d, DB_LOCK_RANDOM);
5609 ADD_INT(d, DB_LOCK_YOUNGEST);
5610#if (DBVER >= 33)
5611 ADD_INT(d, DB_LOCK_MAXLOCKS);
5612 ADD_INT(d, DB_LOCK_MINLOCKS);
5613 ADD_INT(d, DB_LOCK_MINWRITE);
5614#endif
5615
5616
5617#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005618 /* docs say to use zero instead */
5619 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005620#else
5621 ADD_INT(d, DB_LOCK_CONFLICT);
5622#endif
5623
5624 ADD_INT(d, DB_LOCK_DUMP);
5625 ADD_INT(d, DB_LOCK_GET);
5626 ADD_INT(d, DB_LOCK_INHERIT);
5627 ADD_INT(d, DB_LOCK_PUT);
5628 ADD_INT(d, DB_LOCK_PUT_ALL);
5629 ADD_INT(d, DB_LOCK_PUT_OBJ);
5630
5631 ADD_INT(d, DB_LOCK_NG);
5632 ADD_INT(d, DB_LOCK_READ);
5633 ADD_INT(d, DB_LOCK_WRITE);
5634 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005635 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005636 ADD_INT(d, DB_LOCK_IWRITE);
5637 ADD_INT(d, DB_LOCK_IREAD);
5638 ADD_INT(d, DB_LOCK_IWR);
5639#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005640#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005641 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005642#else
5643 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5644#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005645 ADD_INT(d, DB_LOCK_WWRITE);
5646#endif
5647
5648 ADD_INT(d, DB_LOCK_RECORD);
5649 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005650 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005651#if (DBVER >= 33)
5652 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5653#endif
5654
5655 ADD_INT(d, DB_LOCK_NOWAIT);
5656 ADD_INT(d, DB_LOCK_RECORD);
5657 ADD_INT(d, DB_LOCK_UPGRADE);
5658
5659#if (DBVER >= 33)
5660 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005661#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005662 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005663#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664 ADD_INT(d, DB_LSTAT_FREE);
5665 ADD_INT(d, DB_LSTAT_HELD);
5666#if (DBVER == 33)
5667 ADD_INT(d, DB_LSTAT_NOGRANT);
5668#endif
5669 ADD_INT(d, DB_LSTAT_PENDING);
5670 ADD_INT(d, DB_LSTAT_WAITING);
5671#endif
5672
5673 ADD_INT(d, DB_ARCH_ABS);
5674 ADD_INT(d, DB_ARCH_DATA);
5675 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005676#if (DBVER >= 42)
5677 ADD_INT(d, DB_ARCH_REMOVE);
5678#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005679
5680 ADD_INT(d, DB_BTREE);
5681 ADD_INT(d, DB_HASH);
5682 ADD_INT(d, DB_RECNO);
5683 ADD_INT(d, DB_QUEUE);
5684 ADD_INT(d, DB_UNKNOWN);
5685
5686 ADD_INT(d, DB_DUP);
5687 ADD_INT(d, DB_DUPSORT);
5688 ADD_INT(d, DB_RECNUM);
5689 ADD_INT(d, DB_RENUMBER);
5690 ADD_INT(d, DB_REVSPLITOFF);
5691 ADD_INT(d, DB_SNAPSHOT);
5692
5693 ADD_INT(d, DB_JOIN_NOSORT);
5694
5695 ADD_INT(d, DB_AFTER);
5696 ADD_INT(d, DB_APPEND);
5697 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005698#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005699 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005700#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005701#if (DBVER >= 41)
5702 _addIntToDict(d, "DB_CHECKPOINT", 0);
5703#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005704 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005705 ADD_INT(d, DB_CURLSN);
5706#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005707#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005708 ADD_INT(d, DB_COMMIT);
5709#endif
5710 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005712 ADD_INT(d, DB_CURRENT);
5713#if (DBVER >= 33)
5714 ADD_INT(d, DB_FAST_STAT);
5715#endif
5716 ADD_INT(d, DB_FIRST);
5717 ADD_INT(d, DB_FLUSH);
5718 ADD_INT(d, DB_GET_BOTH);
5719 ADD_INT(d, DB_GET_RECNO);
5720 ADD_INT(d, DB_JOIN_ITEM);
5721 ADD_INT(d, DB_KEYFIRST);
5722 ADD_INT(d, DB_KEYLAST);
5723 ADD_INT(d, DB_LAST);
5724 ADD_INT(d, DB_NEXT);
5725 ADD_INT(d, DB_NEXT_DUP);
5726 ADD_INT(d, DB_NEXT_NODUP);
5727 ADD_INT(d, DB_NODUPDATA);
5728 ADD_INT(d, DB_NOOVERWRITE);
5729 ADD_INT(d, DB_NOSYNC);
5730 ADD_INT(d, DB_POSITION);
5731 ADD_INT(d, DB_PREV);
5732 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005733#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005734 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005735#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005736 ADD_INT(d, DB_SET);
5737 ADD_INT(d, DB_SET_RANGE);
5738 ADD_INT(d, DB_SET_RECNO);
5739 ADD_INT(d, DB_WRITECURSOR);
5740
5741 ADD_INT(d, DB_OPFLAGS_MASK);
5742 ADD_INT(d, DB_RMW);
5743#if (DBVER >= 33)
5744 ADD_INT(d, DB_DIRTY_READ);
5745 ADD_INT(d, DB_MULTIPLE);
5746 ADD_INT(d, DB_MULTIPLE_KEY);
5747#endif
5748
Gregory P. Smith29602d22006-01-24 09:46:48 +00005749#if (DBVER >= 44)
5750 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5751 ADD_INT(d, DB_READ_COMMITTED);
5752#endif
5753
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005754#if (DBVER >= 33)
5755 ADD_INT(d, DB_DONOTINDEX);
5756#endif
5757
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005758#if (DBVER >= 41)
5759 _addIntToDict(d, "DB_INCOMPLETE", 0);
5760#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005761 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005762#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005763 ADD_INT(d, DB_KEYEMPTY);
5764 ADD_INT(d, DB_KEYEXIST);
5765 ADD_INT(d, DB_LOCK_DEADLOCK);
5766 ADD_INT(d, DB_LOCK_NOTGRANTED);
5767 ADD_INT(d, DB_NOSERVER);
5768 ADD_INT(d, DB_NOSERVER_HOME);
5769 ADD_INT(d, DB_NOSERVER_ID);
5770 ADD_INT(d, DB_NOTFOUND);
5771 ADD_INT(d, DB_OLD_VERSION);
5772 ADD_INT(d, DB_RUNRECOVERY);
5773 ADD_INT(d, DB_VERIFY_BAD);
5774#if (DBVER >= 33)
5775 ADD_INT(d, DB_PAGE_NOTFOUND);
5776 ADD_INT(d, DB_SECONDARY_BAD);
5777#endif
5778#if (DBVER >= 40)
5779 ADD_INT(d, DB_STAT_CLEAR);
5780 ADD_INT(d, DB_REGION_INIT);
5781 ADD_INT(d, DB_NOLOCKING);
5782 ADD_INT(d, DB_YIELDCPU);
5783 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5784 ADD_INT(d, DB_NOPANIC);
5785#endif
5786
Gregory P. Smithaae141a2007-11-01 21:08:14 +00005787#ifdef DB_REGISTER
5788 ADD_INT(d, DB_REGISTER);
5789#endif
5790
Gregory P. Smith41631e82003-09-21 00:08:14 +00005791#if (DBVER >= 42)
5792 ADD_INT(d, DB_TIME_NOTGRANTED);
5793 ADD_INT(d, DB_TXN_NOT_DURABLE);
5794 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5795 ADD_INT(d, DB_LOG_AUTOREMOVE);
5796 ADD_INT(d, DB_DIRECT_LOG);
5797 ADD_INT(d, DB_DIRECT_DB);
5798 ADD_INT(d, DB_INIT_REP);
5799 ADD_INT(d, DB_ENCRYPT);
5800 ADD_INT(d, DB_CHKSUM);
5801#endif
5802
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005803#if (DBVER >= 43)
5804 ADD_INT(d, DB_LOG_INMEMORY);
5805 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005806 ADD_INT(d, DB_SEQ_DEC);
5807 ADD_INT(d, DB_SEQ_INC);
5808 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005809#endif
5810
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005811#if (DBVER >= 41)
5812 ADD_INT(d, DB_ENCRYPT_AES);
5813 ADD_INT(d, DB_AUTO_COMMIT);
5814#else
5815 /* allow berkeleydb 4.1 aware apps to run on older versions */
5816 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5817#endif
5818
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005819 ADD_INT(d, EINVAL);
5820 ADD_INT(d, EACCES);
5821 ADD_INT(d, ENOSPC);
5822 ADD_INT(d, ENOMEM);
5823 ADD_INT(d, EAGAIN);
5824 ADD_INT(d, EBUSY);
5825 ADD_INT(d, EEXIST);
5826 ADD_INT(d, ENOENT);
5827 ADD_INT(d, EPERM);
5828
Barry Warsaw1baa9822003-03-31 19:51:29 +00005829#if (DBVER >= 40)
5830 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5831 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5832#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005833
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005834 /* The exception name must be correct for pickled exception *
5835 * objects to unpickle properly. */
5836#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5837#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5838#else
5839#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5840#endif
5841
5842 /* All the rest of the exceptions derive only from DBError */
5843#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5844 PyDict_SetItemString(d, #name, name)
5845
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005847 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5848 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005849
Gregory P. Smithe9477062005-06-04 06:46:59 +00005850 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5851 * from both DBError and KeyError, since the API only supports
5852 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005853 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005854 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5855 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005856 Py_file_input, d, d);
5857 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005858 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005859 PyDict_DelItemString(d, "KeyError");
5860
5861
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005862#if !INCOMPLETE_IS_WARNING
5863 MAKE_EX(DBIncompleteError);
5864#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005865 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005866 MAKE_EX(DBKeyEmptyError);
5867 MAKE_EX(DBKeyExistError);
5868 MAKE_EX(DBLockDeadlockError);
5869 MAKE_EX(DBLockNotGrantedError);
5870 MAKE_EX(DBOldVersionError);
5871 MAKE_EX(DBRunRecoveryError);
5872 MAKE_EX(DBVerifyBadError);
5873 MAKE_EX(DBNoServerError);
5874 MAKE_EX(DBNoServerHomeError);
5875 MAKE_EX(DBNoServerIDError);
5876#if (DBVER >= 33)
5877 MAKE_EX(DBPageNotFoundError);
5878 MAKE_EX(DBSecondaryBadError);
5879#endif
5880
5881 MAKE_EX(DBInvalidArgError);
5882 MAKE_EX(DBAccessError);
5883 MAKE_EX(DBNoSpaceError);
5884 MAKE_EX(DBNoMemoryError);
5885 MAKE_EX(DBAgainError);
5886 MAKE_EX(DBBusyError);
5887 MAKE_EX(DBFileExistsError);
5888 MAKE_EX(DBNoSuchFileError);
5889 MAKE_EX(DBPermissionsError);
5890
5891#undef MAKE_EX
5892
Gregory P. Smith39250532007-10-09 06:02:21 +00005893 /* Initiliase the C API structure and add it to the module */
5894 bsddb_api.db_type = &DB_Type;
5895 bsddb_api.dbcursor_type = &DBCursor_Type;
5896 bsddb_api.dbenv_type = &DBEnv_Type;
5897 bsddb_api.dbtxn_type = &DBTxn_Type;
5898 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005899#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00005900 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005901#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00005902 bsddb_api.makeDBError = makeDBError;
5903
5904 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5905 PyDict_SetItemString(d, "api", py_api);
5906 Py_DECREF(py_api);
5907
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005908 /* Check for errors */
5909 if (PyErr_Occurred()) {
5910 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005911 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005912 }
5913}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005914
5915/* allow this module to be named _pybsddb so that it can be installed
5916 * and imported on top of python >= 2.3 that includes its own older
5917 * copy of the library named _bsddb without importing the old version. */
5918DL_EXPORT(void) init_pybsddb(void)
5919{
5920 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5921 init_bsddb();
5922}