blob: c840eaf268e173fbf58f37adf9c2c12a62a5e0da [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
331 key->data = PyString_AS_STRING(keyobj);
332 key->size = PyString_GET_SIZE(keyobj);
333 }
334
335 else if (PyInt_Check(keyobj)) {
336 /* verify access method type */
337 type = _DB_get_type(self);
338 if (type == -1)
339 return 0;
340 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000341 /* if BTREE then an Integer key is allowed with the
342 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000343 *pflags |= DB_SET_RECNO;
344 }
345 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000346 PyErr_SetString(
347 PyExc_TypeError,
348 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000349 return 0;
350 }
351
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000352 /* Make a key out of the requested recno, use allocated space so DB
353 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000354 recno = PyInt_AS_LONG(keyobj);
355 key->data = malloc(sizeof(db_recno_t));
356 if (key->data == NULL) {
357 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
358 return 0;
359 }
360 key->ulen = key->size = sizeof(db_recno_t);
361 memcpy(key->data, &recno, sizeof(db_recno_t));
362 key->flags = DB_DBT_REALLOC;
363 }
364 else {
365 PyErr_Format(PyExc_TypeError,
366 "String or Integer object expected for key, %s found",
Martin v. Löwis68192102007-07-21 06:55:02 +0000367 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000368 return 0;
369 }
370
371 return 1;
372}
373
374
375/* Add partial record access to an existing DBT data struct.
376 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
377 and the data storage/retrieval will be done using dlen and doff. */
378static int add_partial_dbt(DBT* d, int dlen, int doff) {
379 /* if neither were set we do nothing (-1 is the default value) */
380 if ((dlen == -1) && (doff == -1)) {
381 return 1;
382 }
383
384 if ((dlen < 0) || (doff < 0)) {
385 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
386 return 0;
387 }
388
389 d->flags = d->flags | DB_DBT_PARTIAL;
390 d->dlen = (unsigned int) dlen;
391 d->doff = (unsigned int) doff;
392 return 1;
393}
394
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000395/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
396/* TODO: make this use the native libc strlcpy() when available (BSD) */
397unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
398{
399 unsigned int srclen, copylen;
400
401 srclen = strlen(src);
402 if (n <= 0)
403 return srclen;
404 copylen = (srclen > n-1) ? n-1 : srclen;
405 /* populate dest[0] thru dest[copylen-1] */
406 memcpy(dest, src, copylen);
407 /* guarantee null termination */
408 dest[copylen] = 0;
409
410 return srclen;
411}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000412
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000413/* Callback used to save away more information about errors from the DB
414 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000415static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000416#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000417static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000418#else
419static void _db_errorCallback(const DB_ENV *db_env,
420 const char* prefix, const char* msg)
421#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000422{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000423 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000424}
425
426
427/* make a nice exception object to raise for errors. */
428static int makeDBError(int err)
429{
430 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000431 PyObject *errObj = NULL;
432 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000433 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000434 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000435
436 switch (err) {
437 case 0: /* successful, no error */ break;
438
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000439#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 case DB_INCOMPLETE:
441#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000442 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
443 /* Ensure that bytes_left never goes negative */
444 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
445 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
446 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000448 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000449 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000450 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000452
453#else /* do an exception instead */
454 errObj = DBIncompleteError;
455#endif
456 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000457#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000458
459 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
460 case DB_KEYEXIST: errObj = DBKeyExistError; break;
461 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
462 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
463 case DB_NOTFOUND: errObj = DBNotFoundError; break;
464 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
465 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
466 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
467 case DB_NOSERVER: errObj = DBNoServerError; break;
468 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
469 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
470#if (DBVER >= 33)
471 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
472 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
473#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000474 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000475
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000476#if (DBVER >= 43)
477 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
478 case ENOMEM: errObj = PyExc_MemoryError; break;
479#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000480 case EINVAL: errObj = DBInvalidArgError; break;
481 case EACCES: errObj = DBAccessError; break;
482 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000483 case EAGAIN: errObj = DBAgainError; break;
484 case EBUSY : errObj = DBBusyError; break;
485 case EEXIST: errObj = DBFileExistsError; break;
486 case ENOENT: errObj = DBNoSuchFileError; break;
487 case EPERM : errObj = DBPermissionsError; break;
488
489 default: errObj = DBError; break;
490 }
491
492 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000493 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
494 /* Ensure that bytes_left never goes negative */
495 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
496 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
497 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000498 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000499 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000500 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000501 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000502
503 errTuple = Py_BuildValue("(is)", err, errTxt);
504 PyErr_SetObject(errObj, errTuple);
505 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000506 }
507
508 return ((errObj != NULL) || exceptionRaised);
509}
510
511
512
513/* set a type exception */
514static void makeTypeError(char* expected, PyObject* found)
515{
516 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis68192102007-07-21 06:55:02 +0000517 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518}
519
520
521/* verify that an obj is either None or a DBTxn, and set the txn pointer */
522static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
523{
524 if (txnobj == Py_None || txnobj == NULL) {
525 *txn = NULL;
526 return 1;
527 }
528 if (DBTxnObject_Check(txnobj)) {
529 *txn = ((DBTxnObject*)txnobj)->txn;
530 return 1;
531 }
532 else
533 makeTypeError("DBTxn", txnobj);
534 return 0;
535}
536
537
538/* Delete a key from a database
539 Returns 0 on success, -1 on an error. */
540static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
541{
542 int err;
543
544 MYDB_BEGIN_ALLOW_THREADS;
545 err = self->db->del(self->db, txn, key, 0);
546 MYDB_END_ALLOW_THREADS;
547 if (makeDBError(err)) {
548 return -1;
549 }
550 self->haveStat = 0;
551 return 0;
552}
553
554
555/* Store a key into a database
556 Returns 0 on success, -1 on an error. */
557static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
558{
559 int err;
560
561 MYDB_BEGIN_ALLOW_THREADS;
562 err = self->db->put(self->db, txn, key, data, flags);
563 MYDB_END_ALLOW_THREADS;
564 if (makeDBError(err)) {
565 return -1;
566 }
567 self->haveStat = 0;
568 return 0;
569}
570
571/* Get a key/data pair from a cursor */
572static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
573 PyObject *args, PyObject *kwargs, char *format)
574{
575 int err;
576 PyObject* retval = NULL;
577 DBT key, data;
578 int dlen = -1;
579 int doff = -1;
580 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000581 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582
583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
584 &flags, &dlen, &doff))
585 return NULL;
586
587 CHECK_CURSOR_NOT_CLOSED(self);
588
589 flags |= extra_flags;
590 CLEAR_DBT(key);
591 CLEAR_DBT(data);
592 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
593 /* Tell BerkeleyDB to malloc the return value (thread safe) */
594 data.flags = DB_DBT_MALLOC;
595 key.flags = DB_DBT_MALLOC;
596 }
597 if (!add_partial_dbt(&data, dlen, doff))
598 return NULL;
599
600 MYDB_BEGIN_ALLOW_THREADS;
601 err = self->dbc->c_get(self->dbc, &key, &data, flags);
602 MYDB_END_ALLOW_THREADS;
603
Gregory P. Smithe9477062005-06-04 06:46:59 +0000604 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
605 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000606 Py_INCREF(Py_None);
607 retval = Py_None;
608 }
609 else if (makeDBError(err)) {
610 retval = NULL;
611 }
612 else { /* otherwise, success! */
613
614 /* if Recno or Queue, return the key as an Int */
615 switch (_DB_get_type(self->mydb)) {
616 case -1:
617 retval = NULL;
618 break;
619
620 case DB_RECNO:
621 case DB_QUEUE:
622 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
623 data.data, data.size);
624 break;
625 case DB_HASH:
626 case DB_BTREE:
627 default:
628 retval = Py_BuildValue("s#s#", key.data, key.size,
629 data.data, data.size);
630 break;
631 }
632 }
633 if (!err) {
634 FREE_DBT(key);
635 FREE_DBT(data);
636 }
637 return retval;
638}
639
640
641/* add an integer to a dictionary using the given name as a key */
642static void _addIntToDict(PyObject* dict, char *name, int value)
643{
644 PyObject* v = PyInt_FromLong((long) value);
645 if (!v || PyDict_SetItemString(dict, name, v))
646 PyErr_Clear();
647
648 Py_XDECREF(v);
649}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000650
651/* The same, when the value is a time_t */
652static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
653{
654 PyObject* v;
655 /* if the value fits in regular int, use that. */
656#ifdef HAVE_LONG_LONG
657 if (sizeof(time_t) > sizeof(long))
658 v = PyLong_FromLongLong((PY_LONG_LONG) value);
659 else
660#endif
661 v = PyInt_FromLong((long) value);
662 if (!v || PyDict_SetItemString(dict, name, v))
663 PyErr_Clear();
664
665 Py_XDECREF(v);
666}
667
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000668#if (DBVER >= 43)
669/* add an db_seq_t to a dictionary using the given name as a key */
670static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
671{
672 PyObject* v = PyLong_FromLongLong(value);
673 if (!v || PyDict_SetItemString(dict, name, v))
674 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000675
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000676 Py_XDECREF(v);
677}
678#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679
680
681
682/* --------------------------------------------------------------------- */
683/* Allocators and deallocators */
684
685static DBObject*
686newDBObject(DBEnvObject* arg, int flags)
687{
688 DBObject* self;
689 DB_ENV* db_env = NULL;
690 int err;
691
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000692 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000693 if (self == NULL)
694 return NULL;
695
696 self->haveStat = 0;
697 self->flags = 0;
698 self->setflags = 0;
699 self->myenvobj = NULL;
700#if (DBVER >= 33)
701 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000702 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 self->primaryDBType = 0;
704#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000705 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706
707 /* keep a reference to our python DBEnv object */
708 if (arg) {
709 Py_INCREF(arg);
710 self->myenvobj = arg;
711 db_env = arg->db_env;
712 }
713
714 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000715 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000716 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000717 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
718 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000719
720 MYDB_BEGIN_ALLOW_THREADS;
721 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000722 if (self->db != NULL) {
723 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000724#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000725 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000727 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000728 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000729 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
730 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000731 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000732 if (makeDBError(err)) {
733 if (self->myenvobj) {
734 Py_DECREF(self->myenvobj);
735 self->myenvobj = NULL;
736 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000737 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738 self = NULL;
739 }
740 return self;
741}
742
743
744static void
745DB_dealloc(DBObject* self)
746{
747 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000748 /* avoid closing a DB when its DBEnv has been closed out from under
749 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000750 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000751 (self->myenvobj && self->myenvobj->db_env))
752 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000753 MYDB_BEGIN_ALLOW_THREADS;
754 self->db->close(self->db, 0);
755 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000756 } else {
757 PyErr_Warn(PyExc_RuntimeWarning,
758 "DB could not be closed in destructor: DBEnv already closed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759 }
760 self->db = NULL;
761 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000762 if (self->in_weakreflist != NULL) {
763 PyObject_ClearWeakRefs((PyObject *) self);
764 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765 if (self->myenvobj) {
766 Py_DECREF(self->myenvobj);
767 self->myenvobj = NULL;
768 }
769#if (DBVER >= 33)
770 if (self->associateCallback != NULL) {
771 Py_DECREF(self->associateCallback);
772 self->associateCallback = NULL;
773 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000774 if (self->btCompareCallback != NULL) {
775 Py_DECREF(self->btCompareCallback);
776 self->btCompareCallback = NULL;
777 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000778#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000779 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000780}
781
782
783static DBCursorObject*
784newDBCursorObject(DBC* dbc, DBObject* db)
785{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000786 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 if (self == NULL)
788 return NULL;
789
790 self->dbc = dbc;
791 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000792 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 Py_INCREF(self->mydb);
794 return self;
795}
796
797
798static void
799DBCursor_dealloc(DBCursorObject* self)
800{
801 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000802
Gregory P. Smitha703a212003-11-03 01:04:41 +0000803 if (self->in_weakreflist != NULL) {
804 PyObject_ClearWeakRefs((PyObject *) self);
805 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000806
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000807 if (self->dbc != NULL) {
808 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000809 /* If the underlying database has been closed, we don't
810 need to do anything. If the environment has been closed
811 we need to leak, as BerkeleyDB will crash trying to access
812 the environment. There was an exception when the
813 user closed the environment even though there still was
814 a database open. */
815 if (self->mydb->db && self->mydb->myenvobj &&
816 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000817 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 self->dbc = NULL;
819 MYDB_END_ALLOW_THREADS;
820 }
821 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000822 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823}
824
825
826static DBEnvObject*
827newDBEnvObject(int flags)
828{
829 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000830 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000831 if (self == NULL)
832 return NULL;
833
834 self->closed = 1;
835 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000836 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
837 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000838 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839
840 MYDB_BEGIN_ALLOW_THREADS;
841 err = db_env_create(&self->db_env, flags);
842 MYDB_END_ALLOW_THREADS;
843 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000844 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000845 self = NULL;
846 }
847 else {
848 self->db_env->set_errcall(self->db_env, _db_errorCallback);
849 }
850 return self;
851}
852
853
854static void
855DBEnv_dealloc(DBEnvObject* self)
856{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000857 if (self->in_weakreflist != NULL) {
858 PyObject_ClearWeakRefs((PyObject *) self);
859 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000860
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000861 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862 MYDB_BEGIN_ALLOW_THREADS;
863 self->db_env->close(self->db_env, 0);
864 MYDB_END_ALLOW_THREADS;
865 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000866 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867}
868
869
870static DBTxnObject*
871newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
872{
873 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000874 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (self == NULL)
876 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000877 Py_INCREF(myenv);
878 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000879 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000880
881 MYDB_BEGIN_ALLOW_THREADS;
882#if (DBVER >= 40)
883 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
884#else
885 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
886#endif
887 MYDB_END_ALLOW_THREADS;
888 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000889 Py_DECREF(self->env);
890 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000891 self = NULL;
892 }
893 return self;
894}
895
896
897static void
898DBTxn_dealloc(DBTxnObject* self)
899{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000900 if (self->in_weakreflist != NULL) {
901 PyObject_ClearWeakRefs((PyObject *) self);
902 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903
Gregory P. Smith31c50652004-06-28 01:20:40 +0000904 if (self->txn) {
905 /* it hasn't been finalized, abort it! */
906 MYDB_BEGIN_ALLOW_THREADS;
907#if (DBVER >= 40)
908 self->txn->abort(self->txn);
909#else
910 txn_abort(self->txn);
911#endif
912 MYDB_END_ALLOW_THREADS;
913 PyErr_Warn(PyExc_RuntimeWarning,
914 "DBTxn aborted in destructor. No prior commit() or abort().");
915 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916
Neal Norwitz62a21122006-01-25 05:21:55 +0000917 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919}
920
921
922static DBLockObject*
923newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
924 db_lockmode_t lock_mode, int flags)
925{
926 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000927 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928 if (self == NULL)
929 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000930 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931
932 MYDB_BEGIN_ALLOW_THREADS;
933#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000934 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
935 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000936#else
937 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
938#endif
939 MYDB_END_ALLOW_THREADS;
940 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000941 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 self = NULL;
943 }
944
945 return self;
946}
947
948
949static void
950DBLock_dealloc(DBLockObject* self)
951{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000952 if (self->in_weakreflist != NULL) {
953 PyObject_ClearWeakRefs((PyObject *) self);
954 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000955 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000957 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958}
959
960
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000961#if (DBVER >= 43)
962static DBSequenceObject*
963newDBSequenceObject(DBObject* mydb, int flags)
964{
965 int err;
966 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
967 if (self == NULL)
968 return NULL;
969 Py_INCREF(mydb);
970 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000971 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000972
973
974 MYDB_BEGIN_ALLOW_THREADS;
975 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
976 MYDB_END_ALLOW_THREADS;
977 if (makeDBError(err)) {
978 Py_DECREF(self->mydb);
979 PyObject_Del(self);
980 self = NULL;
981 }
982
983 return self;
984}
985
986
987static void
988DBSequence_dealloc(DBSequenceObject* self)
989{
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000990 if (self->in_weakreflist != NULL) {
991 PyObject_ClearWeakRefs((PyObject *) self);
992 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000993
994 Py_DECREF(self->mydb);
995 PyObject_Del(self);
996}
997#endif
998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999/* --------------------------------------------------------------------- */
1000/* DB methods */
1001
1002static PyObject*
1003DB_append(DBObject* self, PyObject* args)
1004{
1005 PyObject* txnobj = NULL;
1006 PyObject* dataobj;
1007 db_recno_t recno;
1008 DBT key, data;
1009 DB_TXN *txn = NULL;
1010
Georg Brandl96a8c392006-05-29 21:04:52 +00001011 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001012 return NULL;
1013
1014 CHECK_DB_NOT_CLOSED(self);
1015
1016 /* make a dummy key out of a recno */
1017 recno = 0;
1018 CLEAR_DBT(key);
1019 key.data = &recno;
1020 key.size = sizeof(recno);
1021 key.ulen = key.size;
1022 key.flags = DB_DBT_USERMEM;
1023
1024 if (!make_dbt(dataobj, &data)) return NULL;
1025 if (!checkTxnObj(txnobj, &txn)) return NULL;
1026
1027 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1028 return NULL;
1029
1030 return PyInt_FromLong(recno);
1031}
1032
1033
1034#if (DBVER >= 33)
1035
1036static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001037_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1038 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001039{
1040 int retval = DB_DONOTINDEX;
1041 DBObject* secondaryDB = (DBObject*)db->app_private;
1042 PyObject* callback = secondaryDB->associateCallback;
1043 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001045 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046
1047
1048 if (callback != NULL) {
1049 MYDB_BEGIN_BLOCK_THREADS;
1050
Thomas Woutersb3153832006-03-08 01:47:19 +00001051 if (type == DB_RECNO || type == DB_QUEUE)
1052 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1053 priData->data, priData->size);
1054 else
1055 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1056 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001057 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001058 result = PyEval_CallObject(callback, args);
1059 }
1060 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001061 PyErr_Print();
1062 }
1063 else if (result == Py_None) {
1064 retval = DB_DONOTINDEX;
1065 }
1066 else if (PyInt_Check(result)) {
1067 retval = PyInt_AsLong(result);
1068 }
1069 else if (PyString_Check(result)) {
1070 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001071 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001072
1073 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001074 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001075 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1076 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001077 if (secKey->data) {
1078 memcpy(secKey->data, data, size);
1079 secKey->size = size;
1080 retval = 0;
1081 }
1082 else {
1083 PyErr_SetString(PyExc_MemoryError,
1084 "malloc failed in _db_associateCallback");
1085 PyErr_Print();
1086 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001087 }
1088 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001089 PyErr_SetString(
1090 PyExc_TypeError,
1091 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001092 PyErr_Print();
1093 }
1094
Thomas Woutersb3153832006-03-08 01:47:19 +00001095 Py_XDECREF(args);
1096 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001097
1098 MYDB_END_BLOCK_THREADS;
1099 }
1100 return retval;
1101}
1102
1103
1104static PyObject*
1105DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1106{
1107 int err, flags=0;
1108 DBObject* secondaryDB;
1109 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001110#if (DBVER >= 41)
1111 PyObject *txnobj = NULL;
1112 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001113 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001114 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001115#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001116 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001117#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001118
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001119#if (DBVER >= 41)
1120 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1121 &secondaryDB, &callback, &flags,
1122 &txnobj)) {
1123#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001125 &secondaryDB, &callback, &flags)) {
1126#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001128 }
1129
1130#if (DBVER >= 41)
1131 if (!checkTxnObj(txnobj, &txn)) return NULL;
1132#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133
1134 CHECK_DB_NOT_CLOSED(self);
1135 if (!DBObject_Check(secondaryDB)) {
1136 makeTypeError("DB", (PyObject*)secondaryDB);
1137 return NULL;
1138 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001139 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001140 if (callback == Py_None) {
1141 callback = NULL;
1142 }
1143 else if (!PyCallable_Check(callback)) {
1144 makeTypeError("Callable", callback);
1145 return NULL;
1146 }
1147
1148 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001149 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001150 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151 secondaryDB->associateCallback = callback;
1152 secondaryDB->primaryDBType = _DB_get_type(self);
1153
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001154 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1155 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1156 * The global interepreter lock is not initialized until the first
1157 * thread is created using thread.start_new_thread() or fork() is
1158 * called. that would cause the ALLOW_THREADS here to segfault due
1159 * to a null pointer reference if no threads or child processes
1160 * have been created. This works around that and is a no-op if
1161 * threads have already been initialized.
1162 * (see pybsddb-users mailing list post on 2002-08-07)
1163 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001164#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001165 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001166#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001167 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001168#if (DBVER >= 41)
1169 err = self->db->associate(self->db,
1170 txn,
1171 secondaryDB->db,
1172 _db_associateCallback,
1173 flags);
1174#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 err = self->db->associate(self->db,
1176 secondaryDB->db,
1177 _db_associateCallback,
1178 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001179#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001180 MYDB_END_ALLOW_THREADS;
1181
1182 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001183 Py_XDECREF(secondaryDB->associateCallback);
1184 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001185 secondaryDB->primaryDBType = 0;
1186 }
1187
1188 RETURN_IF_ERR();
1189 RETURN_NONE();
1190}
1191
1192
1193#endif
1194
1195
1196static PyObject*
1197DB_close(DBObject* self, PyObject* args)
1198{
1199 int err, flags=0;
1200 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1201 return NULL;
1202 if (self->db != NULL) {
1203 if (self->myenvobj)
1204 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206 self->db = NULL;
1207 RETURN_IF_ERR();
1208 }
1209 RETURN_NONE();
1210}
1211
1212
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001213static PyObject*
1214_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1215{
1216 int err, flags=0, type;
1217 PyObject* txnobj = NULL;
1218 PyObject* retval = NULL;
1219 DBT key, data;
1220 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001221 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001222
1223 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1224 &txnobj, &flags))
1225 return NULL;
1226
1227 CHECK_DB_NOT_CLOSED(self);
1228 type = _DB_get_type(self);
1229 if (type == -1)
1230 return NULL;
1231 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001232 PyErr_SetString(PyExc_TypeError,
1233 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001234 return NULL;
1235 }
1236 if (!checkTxnObj(txnobj, &txn))
1237 return NULL;
1238
1239 CLEAR_DBT(key);
1240 CLEAR_DBT(data);
1241 if (CHECK_DBFLAG(self, DB_THREAD)) {
1242 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1243 data.flags = DB_DBT_MALLOC;
1244 key.flags = DB_DBT_MALLOC;
1245 }
1246
1247 MYDB_BEGIN_ALLOW_THREADS;
1248 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1249 MYDB_END_ALLOW_THREADS;
1250
Gregory P. Smithe9477062005-06-04 06:46:59 +00001251 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1252 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001253 err = 0;
1254 Py_INCREF(Py_None);
1255 retval = Py_None;
1256 }
1257 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001258 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1259 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 FREE_DBT(key);
1261 FREE_DBT(data);
1262 }
1263
1264 RETURN_IF_ERR();
1265 return retval;
1266}
1267
1268static PyObject*
1269DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1270{
1271 return _DB_consume(self, args, kwargs, DB_CONSUME);
1272}
1273
1274static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001275DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1276 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277{
1278 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1279}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001280
1281
1282static PyObject*
1283DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1284{
1285 int err, flags=0;
1286 DBC* dbc;
1287 PyObject* txnobj = NULL;
1288 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001289 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290
1291 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1292 &txnobj, &flags))
1293 return NULL;
1294 CHECK_DB_NOT_CLOSED(self);
1295 if (!checkTxnObj(txnobj, &txn))
1296 return NULL;
1297
1298 MYDB_BEGIN_ALLOW_THREADS;
1299 err = self->db->cursor(self->db, txn, &dbc, flags);
1300 MYDB_END_ALLOW_THREADS;
1301 RETURN_IF_ERR();
1302 return (PyObject*) newDBCursorObject(dbc, self);
1303}
1304
1305
1306static PyObject*
1307DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1308{
1309 PyObject* txnobj = NULL;
1310 int flags = 0;
1311 PyObject* keyobj;
1312 DBT key;
1313 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001314 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315
1316 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1317 &keyobj, &txnobj, &flags))
1318 return NULL;
1319 CHECK_DB_NOT_CLOSED(self);
1320 if (!make_key_dbt(self, keyobj, &key, NULL))
1321 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001322 if (!checkTxnObj(txnobj, &txn)) {
1323 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001324 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001325 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001326
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001327 if (-1 == _DB_delete(self, txn, &key, 0)) {
1328 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001329 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001330 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001331
1332 FREE_DBT(key);
1333 RETURN_NONE();
1334}
1335
1336
1337static PyObject*
1338DB_fd(DBObject* self, PyObject* args)
1339{
1340 int err, the_fd;
1341
1342 if (!PyArg_ParseTuple(args,":fd"))
1343 return NULL;
1344 CHECK_DB_NOT_CLOSED(self);
1345
1346 MYDB_BEGIN_ALLOW_THREADS;
1347 err = self->db->fd(self->db, &the_fd);
1348 MYDB_END_ALLOW_THREADS;
1349 RETURN_IF_ERR();
1350 return PyInt_FromLong(the_fd);
1351}
1352
1353
1354static PyObject*
1355DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1356{
1357 int err, flags=0;
1358 PyObject* txnobj = NULL;
1359 PyObject* keyobj;
1360 PyObject* dfltobj = NULL;
1361 PyObject* retval = NULL;
1362 int dlen = -1;
1363 int doff = -1;
1364 DBT key, data;
1365 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001366 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001367 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368
1369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001370 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1371 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 return NULL;
1373
1374 CHECK_DB_NOT_CLOSED(self);
1375 if (!make_key_dbt(self, keyobj, &key, &flags))
1376 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001377 if (!checkTxnObj(txnobj, &txn)) {
1378 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001379 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001381
1382 CLEAR_DBT(data);
1383 if (CHECK_DBFLAG(self, DB_THREAD)) {
1384 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1385 data.flags = DB_DBT_MALLOC;
1386 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001387 if (!add_partial_dbt(&data, dlen, doff)) {
1388 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001389 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391
1392 MYDB_BEGIN_ALLOW_THREADS;
1393 err = self->db->get(self->db, txn, &key, &data, flags);
1394 MYDB_END_ALLOW_THREADS;
1395
Gregory P. Smithe9477062005-06-04 06:46:59 +00001396 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001397 err = 0;
1398 Py_INCREF(dfltobj);
1399 retval = dfltobj;
1400 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001401 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1402 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403 err = 0;
1404 Py_INCREF(Py_None);
1405 retval = Py_None;
1406 }
1407 else if (!err) {
1408 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001409 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1410 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 else /* return just the data */
1412 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001413 FREE_DBT(data);
1414 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001415 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001416
1417 RETURN_IF_ERR();
1418 return retval;
1419}
1420
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001421#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001422static PyObject*
1423DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1424{
1425 int err, flags=0;
1426 PyObject* txnobj = NULL;
1427 PyObject* keyobj;
1428 PyObject* dfltobj = NULL;
1429 PyObject* retval = NULL;
1430 int dlen = -1;
1431 int doff = -1;
1432 DBT key, pkey, data;
1433 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001434 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001435 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1438 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1439 &doff))
1440 return NULL;
1441
1442 CHECK_DB_NOT_CLOSED(self);
1443 if (!make_key_dbt(self, keyobj, &key, &flags))
1444 return NULL;
1445 if (!checkTxnObj(txnobj, &txn)) {
1446 FREE_DBT(key);
1447 return NULL;
1448 }
1449
1450 CLEAR_DBT(data);
1451 if (CHECK_DBFLAG(self, DB_THREAD)) {
1452 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1453 data.flags = DB_DBT_MALLOC;
1454 }
1455 if (!add_partial_dbt(&data, dlen, doff)) {
1456 FREE_DBT(key);
1457 return NULL;
1458 }
1459
1460 CLEAR_DBT(pkey);
1461 pkey.flags = DB_DBT_MALLOC;
1462
1463 MYDB_BEGIN_ALLOW_THREADS;
1464 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1465 MYDB_END_ALLOW_THREADS;
1466
Gregory P. Smithe9477062005-06-04 06:46:59 +00001467 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001468 err = 0;
1469 Py_INCREF(dfltobj);
1470 retval = dfltobj;
1471 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001472 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1473 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001474 err = 0;
1475 Py_INCREF(Py_None);
1476 retval = Py_None;
1477 }
1478 else if (!err) {
1479 PyObject *pkeyObj;
1480 PyObject *dataObj;
1481 dataObj = PyString_FromStringAndSize(data.data, data.size);
1482
1483 if (self->primaryDBType == DB_RECNO ||
1484 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001485 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001486 else
1487 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1488
1489 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1490 {
1491 PyObject *keyObj;
1492 int type = _DB_get_type(self);
1493 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001494 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001495 else
1496 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001497#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001498 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001499#else
1500 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1501#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001502 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001503 }
1504 else /* return just the pkey and data */
1505 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001506#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001507 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001508#else
1509 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1510#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001511 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001512 Py_DECREF(dataObj);
1513 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001514 FREE_DBT(pkey);
1515 FREE_DBT(data);
1516 }
1517 FREE_DBT(key);
1518
1519 RETURN_IF_ERR();
1520 return retval;
1521}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001522#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001523
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524
1525/* Return size of entry */
1526static PyObject*
1527DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1528{
1529 int err, flags=0;
1530 PyObject* txnobj = NULL;
1531 PyObject* keyobj;
1532 PyObject* retval = NULL;
1533 DBT key, data;
1534 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001535 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536
1537 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1538 &keyobj, &txnobj))
1539 return NULL;
1540 CHECK_DB_NOT_CLOSED(self);
1541 if (!make_key_dbt(self, keyobj, &key, &flags))
1542 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001543 if (!checkTxnObj(txnobj, &txn)) {
1544 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001545 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001546 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001547 CLEAR_DBT(data);
1548
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001549 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1550 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001551 data.flags = DB_DBT_USERMEM;
1552 data.ulen = 0;
1553 MYDB_BEGIN_ALLOW_THREADS;
1554 err = self->db->get(self->db, txn, &key, &data, flags);
1555 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001556 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001557 retval = PyInt_FromLong((long)data.size);
1558 err = 0;
1559 }
1560
1561 FREE_DBT(key);
1562 FREE_DBT(data);
1563 RETURN_IF_ERR();
1564 return retval;
1565}
1566
1567
1568static PyObject*
1569DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1570{
1571 int err, flags=0;
1572 PyObject* txnobj = NULL;
1573 PyObject* keyobj;
1574 PyObject* dataobj;
1575 PyObject* retval = NULL;
1576 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001577 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001578 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001579 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001580
1581
1582 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1583 &keyobj, &dataobj, &txnobj, &flags))
1584 return NULL;
1585
1586 CHECK_DB_NOT_CLOSED(self);
1587 if (!make_key_dbt(self, keyobj, &key, NULL))
1588 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001589 if ( !make_dbt(dataobj, &data) ||
1590 !checkTxnObj(txnobj, &txn) )
1591 {
1592 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001593 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001594 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001595
1596 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001597 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001598
1599 if (CHECK_DBFLAG(self, DB_THREAD)) {
1600 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001601 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001602 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001603 }
1604
1605 MYDB_BEGIN_ALLOW_THREADS;
1606 err = self->db->get(self->db, txn, &key, &data, flags);
1607 MYDB_END_ALLOW_THREADS;
1608
Gregory P. Smithe9477062005-06-04 06:46:59 +00001609 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1610 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001611 err = 0;
1612 Py_INCREF(Py_None);
1613 retval = Py_None;
1614 }
1615 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001616 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001618
1619 /* Even though the flags require DB_DBT_MALLOC, data is not always
1620 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1621 if (data.data != orig_data)
1622 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001623 }
1624
1625 FREE_DBT(key);
1626 RETURN_IF_ERR();
1627 return retval;
1628}
1629
1630
1631static PyObject*
1632DB_get_byteswapped(DBObject* self, PyObject* args)
1633{
1634#if (DBVER >= 33)
1635 int err = 0;
1636#endif
1637 int retval = -1;
1638
1639 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1640 return NULL;
1641 CHECK_DB_NOT_CLOSED(self);
1642
1643#if (DBVER >= 33)
1644 MYDB_BEGIN_ALLOW_THREADS;
1645 err = self->db->get_byteswapped(self->db, &retval);
1646 MYDB_END_ALLOW_THREADS;
1647 RETURN_IF_ERR();
1648#else
1649 MYDB_BEGIN_ALLOW_THREADS;
1650 retval = self->db->get_byteswapped(self->db);
1651 MYDB_END_ALLOW_THREADS;
1652#endif
1653 return PyInt_FromLong(retval);
1654}
1655
1656
1657static PyObject*
1658DB_get_type(DBObject* self, PyObject* args)
1659{
1660 int type;
1661
1662 if (!PyArg_ParseTuple(args,":get_type"))
1663 return NULL;
1664 CHECK_DB_NOT_CLOSED(self);
1665
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001667 if (type == -1)
1668 return NULL;
1669 return PyInt_FromLong(type);
1670}
1671
1672
1673static PyObject*
1674DB_join(DBObject* self, PyObject* args)
1675{
1676 int err, flags=0;
1677 int length, x;
1678 PyObject* cursorsObj;
1679 DBC** cursors;
1680 DBC* dbc;
1681
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001682 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1683 return NULL;
1684
1685 CHECK_DB_NOT_CLOSED(self);
1686
1687 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001688 PyErr_SetString(PyExc_TypeError,
1689 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 return NULL;
1691 }
1692
1693 length = PyObject_Length(cursorsObj);
1694 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001695 if (!cursors) {
1696 PyErr_NoMemory();
1697 return NULL;
1698 }
1699
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700 cursors[length] = NULL;
1701 for (x=0; x<length; x++) {
1702 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001703 if (item == NULL) {
1704 free(cursors);
1705 return NULL;
1706 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001707 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001708 PyErr_SetString(PyExc_TypeError,
1709 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001710 free(cursors);
1711 return NULL;
1712 }
1713 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001714 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715 }
1716
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->join(self->db, cursors, &dbc, flags);
1719 MYDB_END_ALLOW_THREADS;
1720 free(cursors);
1721 RETURN_IF_ERR();
1722
Gregory P. Smith7441e652003-11-03 21:35:31 +00001723 /* FIXME: this is a buggy interface. The returned cursor
1724 contains internal references to the passed in cursors
1725 but does not hold python references to them or prevent
1726 them from being closed prematurely. This can cause
1727 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728 return (PyObject*) newDBCursorObject(dbc, self);
1729}
1730
1731
1732static PyObject*
1733DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1734{
1735 int err, flags=0;
1736 PyObject* txnobj = NULL;
1737 PyObject* keyobj;
1738 DBT key;
1739 DB_TXN *txn = NULL;
1740 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001741 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742
1743 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1744 &keyobj, &txnobj, &flags))
1745 return NULL;
1746 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001747 if (!make_dbt(keyobj, &key))
1748 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001749 return NULL;
1750 if (!checkTxnObj(txnobj, &txn))
1751 return NULL;
1752
1753 MYDB_BEGIN_ALLOW_THREADS;
1754 err = self->db->key_range(self->db, txn, &key, &range, flags);
1755 MYDB_END_ALLOW_THREADS;
1756
1757 RETURN_IF_ERR();
1758 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1759}
1760
1761
1762static PyObject*
1763DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1764{
1765 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1766 char* filename = NULL;
1767 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001768#if (DBVER >= 41)
1769 PyObject *txnobj = NULL;
1770 DB_TXN *txn = NULL;
1771 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001772 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001773 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1774 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001775 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001776 "filename", "dbtype", "flags", "mode", "txn", NULL};
1777#else
1778 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001779 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001780 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1781 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001782 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001783 "filename", "dbtype", "flags", "mode", NULL};
1784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001785
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001786#if (DBVER >= 41)
1787 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1788 &filename, &dbname, &type, &flags, &mode,
1789 &txnobj))
1790#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001791 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001792 &filename, &dbname, &type, &flags,
1793 &mode))
1794#endif
1795 {
1796 PyErr_Clear();
1797 type = DB_UNKNOWN; flags = 0; mode = 0660;
1798 filename = NULL; dbname = NULL;
1799#if (DBVER >= 41)
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1801 kwnames_basic,
1802 &filename, &type, &flags, &mode,
1803 &txnobj))
1804 return NULL;
1805#else
1806 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1807 kwnames_basic,
1808 &filename, &type, &flags, &mode))
1809 return NULL;
1810#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001811 }
1812
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001813#if (DBVER >= 41)
1814 if (!checkTxnObj(txnobj, &txn)) return NULL;
1815#endif
1816
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001817 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001818 PyObject *t = Py_BuildValue("(is)", 0,
1819 "Cannot call open() twice for DB object");
1820 PyErr_SetObject(DBError, t);
1821 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001822 return NULL;
1823 }
1824
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001825#if 0 && (DBVER >= 41)
1826 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1827 && (self->myenvobj->flags & DB_INIT_TXN))
1828 {
1829 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1830 * explicitly passed) but we are in a transaction ready environment:
1831 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1832 * to work on BerkeleyDB 4.1 without needing to modify their
1833 * DBEnv or DB open calls.
1834 * TODO make this behaviour of the library configurable.
1835 */
1836 flags |= DB_AUTO_COMMIT;
1837 }
1838#endif
1839
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001840 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001841#if (DBVER >= 41)
1842 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1843#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846 MYDB_END_ALLOW_THREADS;
1847 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001848 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849 self->db = NULL;
1850 return NULL;
1851 }
1852
1853 self->flags = flags;
1854 RETURN_NONE();
1855}
1856
1857
1858static PyObject*
1859DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1860{
1861 int flags=0;
1862 PyObject* txnobj = NULL;
1863 int dlen = -1;
1864 int doff = -1;
1865 PyObject* keyobj, *dataobj, *retval;
1866 DBT key, data;
1867 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001868 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001869 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001870
1871 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1872 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1873 return NULL;
1874
1875 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001876 if (!make_key_dbt(self, keyobj, &key, NULL))
1877 return NULL;
1878 if ( !make_dbt(dataobj, &data) ||
1879 !add_partial_dbt(&data, dlen, doff) ||
1880 !checkTxnObj(txnobj, &txn) )
1881 {
1882 FREE_DBT(key);
1883 return NULL;
1884 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001885
1886 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1887 FREE_DBT(key);
1888 return NULL;
1889 }
1890
1891 if (flags & DB_APPEND)
1892 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1893 else {
1894 retval = Py_None;
1895 Py_INCREF(retval);
1896 }
1897 FREE_DBT(key);
1898 return retval;
1899}
1900
1901
1902
1903static PyObject*
1904DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1905{
1906 char* filename;
1907 char* database = NULL;
1908 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001909 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001910
1911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1912 &filename, &database, &flags))
1913 return NULL;
1914 CHECK_DB_NOT_CLOSED(self);
1915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001917 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001918 RETURN_IF_ERR();
1919 RETURN_NONE();
1920}
1921
1922
1923
1924static PyObject*
1925DB_rename(DBObject* self, PyObject* args)
1926{
1927 char* filename;
1928 char* database;
1929 char* newname;
1930 int err, flags=0;
1931
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001932 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1933 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001934 return NULL;
1935 CHECK_DB_NOT_CLOSED(self);
1936
1937 MYDB_BEGIN_ALLOW_THREADS;
1938 err = self->db->rename(self->db, filename, database, newname, flags);
1939 MYDB_END_ALLOW_THREADS;
1940 RETURN_IF_ERR();
1941 RETURN_NONE();
1942}
1943
1944
1945static PyObject*
1946DB_set_bt_minkey(DBObject* self, PyObject* args)
1947{
1948 int err, minkey;
1949
1950 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1951 return NULL;
1952 CHECK_DB_NOT_CLOSED(self);
1953
1954 MYDB_BEGIN_ALLOW_THREADS;
1955 err = self->db->set_bt_minkey(self->db, minkey);
1956 MYDB_END_ALLOW_THREADS;
1957 RETURN_IF_ERR();
1958 RETURN_NONE();
1959}
1960
Neal Norwitz84562352005-10-20 04:30:15 +00001961#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001962static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001963_default_cmp(const DBT *leftKey,
1964 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001965{
1966 int res;
1967 int lsize = leftKey->size, rsize = rightKey->size;
1968
Georg Brandlef1701f2006-03-07 14:57:48 +00001969 res = memcmp(leftKey->data, rightKey->data,
1970 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001971
1972 if (res == 0) {
1973 if (lsize < rsize) {
1974 res = -1;
1975 }
1976 else if (lsize > rsize) {
1977 res = 1;
1978 }
1979 }
1980 return res;
1981}
1982
1983static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001984_db_compareCallback(DB* db,
1985 const DBT *leftKey,
1986 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001987{
1988 int res = 0;
1989 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001990 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00001991 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001992
1993 if (self == NULL || self->btCompareCallback == NULL) {
1994 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00001995 PyErr_SetString(PyExc_TypeError,
1996 (self == 0
1997 ? "DB_bt_compare db is NULL."
1998 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001999 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002000 PyErr_Print();
2001 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002002 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002003 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002004 MYDB_BEGIN_BLOCK_THREADS;
2005
Thomas Woutersb3153832006-03-08 01:47:19 +00002006 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2007 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002008 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002009 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002010 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002011 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002012 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002013 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002014 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002015 PyErr_Print();
2016 res = _default_cmp(leftKey, rightKey);
2017 } else if (PyInt_Check(result)) {
2018 res = PyInt_AsLong(result);
2019 } else {
2020 PyErr_SetString(PyExc_TypeError,
2021 "DB_bt_compare callback MUST return an int.");
2022 /* we're in a callback within the DB code, we can't raise */
2023 PyErr_Print();
2024 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002025 }
2026
Thomas Woutersb3153832006-03-08 01:47:19 +00002027 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002028 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002029
2030 MYDB_END_BLOCK_THREADS;
2031 }
2032 return res;
2033}
2034
2035static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002036DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002037{
2038 int err;
2039 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002040 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002041
Georg Brandlef1701f2006-03-07 14:57:48 +00002042 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002043 return NULL;
2044
Georg Brandlef1701f2006-03-07 14:57:48 +00002045 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002046
Georg Brandlef1701f2006-03-07 14:57:48 +00002047 if (!PyCallable_Check(comparator)) {
2048 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002049 return NULL;
2050 }
2051
2052 /*
2053 * Perform a test call of the comparator function with two empty
2054 * string objects here. verify that it returns an int (0).
2055 * err if not.
2056 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002057 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002058 result = PyEval_CallObject(comparator, tuple);
2059 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002060 if (result == NULL)
2061 return NULL;
2062 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002063 PyErr_SetString(PyExc_TypeError,
2064 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002065 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002066 } else if (PyInt_AsLong(result) != 0) {
2067 PyErr_SetString(PyExc_TypeError,
2068 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002069 return NULL;
2070 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002071 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002072
2073 /* We don't accept multiple set_bt_compare operations, in order to
2074 * simplify the code. This would have no real use, as one cannot
2075 * change the function once the db is opened anyway */
2076 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002077 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002078 return NULL;
2079 }
2080
Georg Brandlef1701f2006-03-07 14:57:48 +00002081 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002082 self->btCompareCallback = comparator;
2083
2084 /* This is to workaround a problem with un-initialized threads (see
2085 comment in DB_associate) */
2086#ifdef WITH_THREAD
2087 PyEval_InitThreads();
2088#endif
2089
Thomas Woutersb3153832006-03-08 01:47:19 +00002090 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002091
2092 if (err) {
2093 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002094 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002095 self->btCompareCallback = NULL;
2096 }
2097
Georg Brandlef1701f2006-03-07 14:57:48 +00002098 RETURN_IF_ERR();
2099 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100}
Neal Norwitz84562352005-10-20 04:30:15 +00002101#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002102
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002103
2104static PyObject*
2105DB_set_cachesize(DBObject* self, PyObject* args)
2106{
2107 int err;
2108 int gbytes = 0, bytes = 0, ncache = 0;
2109
2110 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2111 &gbytes,&bytes,&ncache))
2112 return NULL;
2113 CHECK_DB_NOT_CLOSED(self);
2114
2115 MYDB_BEGIN_ALLOW_THREADS;
2116 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2117 MYDB_END_ALLOW_THREADS;
2118 RETURN_IF_ERR();
2119 RETURN_NONE();
2120}
2121
2122
2123static PyObject*
2124DB_set_flags(DBObject* self, PyObject* args)
2125{
2126 int err, flags;
2127
2128 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2129 return NULL;
2130 CHECK_DB_NOT_CLOSED(self);
2131
2132 MYDB_BEGIN_ALLOW_THREADS;
2133 err = self->db->set_flags(self->db, flags);
2134 MYDB_END_ALLOW_THREADS;
2135 RETURN_IF_ERR();
2136
2137 self->setflags |= flags;
2138 RETURN_NONE();
2139}
2140
2141
2142static PyObject*
2143DB_set_h_ffactor(DBObject* self, PyObject* args)
2144{
2145 int err, ffactor;
2146
2147 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2148 return NULL;
2149 CHECK_DB_NOT_CLOSED(self);
2150
2151 MYDB_BEGIN_ALLOW_THREADS;
2152 err = self->db->set_h_ffactor(self->db, ffactor);
2153 MYDB_END_ALLOW_THREADS;
2154 RETURN_IF_ERR();
2155 RETURN_NONE();
2156}
2157
2158
2159static PyObject*
2160DB_set_h_nelem(DBObject* self, PyObject* args)
2161{
2162 int err, nelem;
2163
2164 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2165 return NULL;
2166 CHECK_DB_NOT_CLOSED(self);
2167
2168 MYDB_BEGIN_ALLOW_THREADS;
2169 err = self->db->set_h_nelem(self->db, nelem);
2170 MYDB_END_ALLOW_THREADS;
2171 RETURN_IF_ERR();
2172 RETURN_NONE();
2173}
2174
2175
2176static PyObject*
2177DB_set_lorder(DBObject* self, PyObject* args)
2178{
2179 int err, lorder;
2180
2181 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2182 return NULL;
2183 CHECK_DB_NOT_CLOSED(self);
2184
2185 MYDB_BEGIN_ALLOW_THREADS;
2186 err = self->db->set_lorder(self->db, lorder);
2187 MYDB_END_ALLOW_THREADS;
2188 RETURN_IF_ERR();
2189 RETURN_NONE();
2190}
2191
2192
2193static PyObject*
2194DB_set_pagesize(DBObject* self, PyObject* args)
2195{
2196 int err, pagesize;
2197
2198 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2199 return NULL;
2200 CHECK_DB_NOT_CLOSED(self);
2201
2202 MYDB_BEGIN_ALLOW_THREADS;
2203 err = self->db->set_pagesize(self->db, pagesize);
2204 MYDB_END_ALLOW_THREADS;
2205 RETURN_IF_ERR();
2206 RETURN_NONE();
2207}
2208
2209
2210static PyObject*
2211DB_set_re_delim(DBObject* self, PyObject* args)
2212{
2213 int err;
2214 char delim;
2215
2216 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2217 PyErr_Clear();
2218 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2219 return NULL;
2220 }
2221
2222 CHECK_DB_NOT_CLOSED(self);
2223
2224 MYDB_BEGIN_ALLOW_THREADS;
2225 err = self->db->set_re_delim(self->db, delim);
2226 MYDB_END_ALLOW_THREADS;
2227 RETURN_IF_ERR();
2228 RETURN_NONE();
2229}
2230
2231static PyObject*
2232DB_set_re_len(DBObject* self, PyObject* args)
2233{
2234 int err, len;
2235
2236 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2237 return NULL;
2238 CHECK_DB_NOT_CLOSED(self);
2239
2240 MYDB_BEGIN_ALLOW_THREADS;
2241 err = self->db->set_re_len(self->db, len);
2242 MYDB_END_ALLOW_THREADS;
2243 RETURN_IF_ERR();
2244 RETURN_NONE();
2245}
2246
2247
2248static PyObject*
2249DB_set_re_pad(DBObject* self, PyObject* args)
2250{
2251 int err;
2252 char pad;
2253
2254 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2255 PyErr_Clear();
2256 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2257 return NULL;
2258 }
2259 CHECK_DB_NOT_CLOSED(self);
2260
2261 MYDB_BEGIN_ALLOW_THREADS;
2262 err = self->db->set_re_pad(self->db, pad);
2263 MYDB_END_ALLOW_THREADS;
2264 RETURN_IF_ERR();
2265 RETURN_NONE();
2266}
2267
2268
2269static PyObject*
2270DB_set_re_source(DBObject* self, PyObject* args)
2271{
2272 int err;
2273 char *re_source;
2274
2275 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2276 return NULL;
2277 CHECK_DB_NOT_CLOSED(self);
2278
2279 MYDB_BEGIN_ALLOW_THREADS;
2280 err = self->db->set_re_source(self->db, re_source);
2281 MYDB_END_ALLOW_THREADS;
2282 RETURN_IF_ERR();
2283 RETURN_NONE();
2284}
2285
2286
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002287static PyObject*
2288DB_set_q_extentsize(DBObject* self, PyObject* args)
2289{
2290 int err;
2291 int extentsize;
2292
2293 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2294 return NULL;
2295 CHECK_DB_NOT_CLOSED(self);
2296
2297 MYDB_BEGIN_ALLOW_THREADS;
2298 err = self->db->set_q_extentsize(self->db, extentsize);
2299 MYDB_END_ALLOW_THREADS;
2300 RETURN_IF_ERR();
2301 RETURN_NONE();
2302}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002303
2304static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002305DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002306{
2307 int err, flags = 0, type;
2308 void* sp;
2309 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002310#if (DBVER >= 43)
2311 PyObject* txnobj = NULL;
2312 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002313 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002314#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002315 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002316#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002317
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002318#if (DBVER >= 43)
2319 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2320 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002321 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002322 if (!checkTxnObj(txnobj, &txn))
2323 return NULL;
2324#else
2325 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2326 return NULL;
2327#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002328 CHECK_DB_NOT_CLOSED(self);
2329
2330 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002331#if (DBVER >= 43)
2332 err = self->db->stat(self->db, txn, &sp, flags);
2333#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002334 err = self->db->stat(self->db, &sp, flags);
2335#else
2336 err = self->db->stat(self->db, &sp, NULL, flags);
2337#endif
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340
2341 self->haveStat = 1;
2342
2343 /* Turn the stat structure into a dictionary */
2344 type = _DB_get_type(self);
2345 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2346 free(sp);
2347 return NULL;
2348 }
2349
2350#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2351#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2352#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2353
2354 switch (type) {
2355 case DB_HASH:
2356 MAKE_HASH_ENTRY(magic);
2357 MAKE_HASH_ENTRY(version);
2358 MAKE_HASH_ENTRY(nkeys);
2359 MAKE_HASH_ENTRY(ndata);
2360 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002361#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002362 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002363#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002364 MAKE_HASH_ENTRY(ffactor);
2365 MAKE_HASH_ENTRY(buckets);
2366 MAKE_HASH_ENTRY(free);
2367 MAKE_HASH_ENTRY(bfree);
2368 MAKE_HASH_ENTRY(bigpages);
2369 MAKE_HASH_ENTRY(big_bfree);
2370 MAKE_HASH_ENTRY(overflows);
2371 MAKE_HASH_ENTRY(ovfl_free);
2372 MAKE_HASH_ENTRY(dup);
2373 MAKE_HASH_ENTRY(dup_free);
2374 break;
2375
2376 case DB_BTREE:
2377 case DB_RECNO:
2378 MAKE_BT_ENTRY(magic);
2379 MAKE_BT_ENTRY(version);
2380 MAKE_BT_ENTRY(nkeys);
2381 MAKE_BT_ENTRY(ndata);
2382 MAKE_BT_ENTRY(pagesize);
2383 MAKE_BT_ENTRY(minkey);
2384 MAKE_BT_ENTRY(re_len);
2385 MAKE_BT_ENTRY(re_pad);
2386 MAKE_BT_ENTRY(levels);
2387 MAKE_BT_ENTRY(int_pg);
2388 MAKE_BT_ENTRY(leaf_pg);
2389 MAKE_BT_ENTRY(dup_pg);
2390 MAKE_BT_ENTRY(over_pg);
2391 MAKE_BT_ENTRY(free);
2392 MAKE_BT_ENTRY(int_pgfree);
2393 MAKE_BT_ENTRY(leaf_pgfree);
2394 MAKE_BT_ENTRY(dup_pgfree);
2395 MAKE_BT_ENTRY(over_pgfree);
2396 break;
2397
2398 case DB_QUEUE:
2399 MAKE_QUEUE_ENTRY(magic);
2400 MAKE_QUEUE_ENTRY(version);
2401 MAKE_QUEUE_ENTRY(nkeys);
2402 MAKE_QUEUE_ENTRY(ndata);
2403 MAKE_QUEUE_ENTRY(pagesize);
2404 MAKE_QUEUE_ENTRY(pages);
2405 MAKE_QUEUE_ENTRY(re_len);
2406 MAKE_QUEUE_ENTRY(re_pad);
2407 MAKE_QUEUE_ENTRY(pgfree);
2408#if (DBVER == 31)
2409 MAKE_QUEUE_ENTRY(start);
2410#endif
2411 MAKE_QUEUE_ENTRY(first_recno);
2412 MAKE_QUEUE_ENTRY(cur_recno);
2413 break;
2414
2415 default:
2416 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2417 Py_DECREF(d);
2418 d = NULL;
2419 }
2420
2421#undef MAKE_HASH_ENTRY
2422#undef MAKE_BT_ENTRY
2423#undef MAKE_QUEUE_ENTRY
2424
2425 free(sp);
2426 return d;
2427}
2428
2429static PyObject*
2430DB_sync(DBObject* self, PyObject* args)
2431{
2432 int err;
2433 int flags = 0;
2434
2435 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2436 return NULL;
2437 CHECK_DB_NOT_CLOSED(self);
2438
2439 MYDB_BEGIN_ALLOW_THREADS;
2440 err = self->db->sync(self->db, flags);
2441 MYDB_END_ALLOW_THREADS;
2442 RETURN_IF_ERR();
2443 RETURN_NONE();
2444}
2445
2446
2447#if (DBVER >= 33)
2448static PyObject*
2449DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2450{
2451 int err, flags=0;
2452 u_int32_t count=0;
2453 PyObject* txnobj = NULL;
2454 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002455 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002456
2457 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2458 &txnobj, &flags))
2459 return NULL;
2460 CHECK_DB_NOT_CLOSED(self);
2461 if (!checkTxnObj(txnobj, &txn))
2462 return NULL;
2463
2464 MYDB_BEGIN_ALLOW_THREADS;
2465 err = self->db->truncate(self->db, txn, &count, flags);
2466 MYDB_END_ALLOW_THREADS;
2467 RETURN_IF_ERR();
2468 return PyInt_FromLong(count);
2469}
2470#endif
2471
2472
2473static PyObject*
2474DB_upgrade(DBObject* self, PyObject* args)
2475{
2476 int err, flags=0;
2477 char *filename;
2478
2479 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2480 return NULL;
2481 CHECK_DB_NOT_CLOSED(self);
2482
2483 MYDB_BEGIN_ALLOW_THREADS;
2484 err = self->db->upgrade(self->db, filename, flags);
2485 MYDB_END_ALLOW_THREADS;
2486 RETURN_IF_ERR();
2487 RETURN_NONE();
2488}
2489
2490
2491static PyObject*
2492DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2493{
2494 int err, flags=0;
2495 char* fileName;
2496 char* dbName=NULL;
2497 char* outFileName=NULL;
2498 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002499 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002500 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002501
2502 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2503 &fileName, &dbName, &outFileName, &flags))
2504 return NULL;
2505
2506 CHECK_DB_NOT_CLOSED(self);
2507 if (outFileName)
2508 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002509 /* XXX(nnorwitz): it should probably be an exception if outFile
2510 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002511
2512 MYDB_BEGIN_ALLOW_THREADS;
2513 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2514 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002515 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002516 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002517
2518 /* DB.verify acts as a DB handle destructor (like close); this was
2519 * documented in BerkeleyDB 4.2 but had the undocumented effect
2520 * of not being safe in prior versions while still requiring an explicit
2521 * DB.close call afterwards. Lets call close for the user to emulate
2522 * the safe 4.2 behaviour. */
2523#if (DBVER <= 41)
2524 self->db->close(self->db, 0);
2525#endif
2526 self->db = NULL;
2527
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002528 RETURN_IF_ERR();
2529 RETURN_NONE();
2530}
2531
2532
2533static PyObject*
2534DB_set_get_returns_none(DBObject* self, PyObject* args)
2535{
2536 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002537 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002538
2539 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2540 return NULL;
2541 CHECK_DB_NOT_CLOSED(self);
2542
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002543 if (self->moduleFlags.getReturnsNone)
2544 ++oldValue;
2545 if (self->moduleFlags.cursorSetReturnsNone)
2546 ++oldValue;
2547 self->moduleFlags.getReturnsNone = (flags >= 1);
2548 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002549 return PyInt_FromLong(oldValue);
2550}
2551
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002552#if (DBVER >= 41)
2553static PyObject*
2554DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2555{
2556 int err;
2557 u_int32_t flags=0;
2558 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002559 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002560
2561 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2562 &passwd, &flags)) {
2563 return NULL;
2564 }
2565
2566 MYDB_BEGIN_ALLOW_THREADS;
2567 err = self->db->set_encrypt(self->db, passwd, flags);
2568 MYDB_END_ALLOW_THREADS;
2569
2570 RETURN_IF_ERR();
2571 RETURN_NONE();
2572}
2573#endif /* DBVER >= 41 */
2574
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002575
2576/*-------------------------------------------------------------- */
2577/* Mapping and Dictionary-like access routines */
2578
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002579Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002580{
2581 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002582 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002583 int flags = 0;
2584 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002585 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002586
2587 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002588 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2589 PyErr_SetObject(DBError, t);
2590 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002591 return -1;
2592 }
2593
2594 if (self->haveStat) { /* Has the stat function been called recently? If
2595 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002596 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002597 }
2598
2599 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002600redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002601#if (DBVER >= 43)
2602 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2603#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002604 err = self->db->stat(self->db, &sp, flags);
2605#else
2606 err = self->db->stat(self->db, &sp, NULL, flags);
2607#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002608
2609 /* All the stat structures have matching fields upto the ndata field,
2610 so we can use any of them for the type cast */
2611 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2612
2613 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2614 * redo a full stat to make sure.
2615 * Fixes SF python bug 1493322, pybsddb bug 1184012
2616 */
2617 if (size == 0 && (flags & DB_FAST_STAT)) {
2618 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002619 if (!err)
2620 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002621 goto redo_stat_for_length;
2622 }
2623
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002624 MYDB_END_ALLOW_THREADS;
2625
2626 if (err)
2627 return -1;
2628
2629 self->haveStat = 1;
2630
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002631 free(sp);
2632 return size;
2633}
2634
2635
2636PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2637{
2638 int err;
2639 PyObject* retval;
2640 DBT key;
2641 DBT data;
2642
2643 CHECK_DB_NOT_CLOSED(self);
2644 if (!make_key_dbt(self, keyobj, &key, NULL))
2645 return NULL;
2646
2647 CLEAR_DBT(data);
2648 if (CHECK_DBFLAG(self, DB_THREAD)) {
2649 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2650 data.flags = DB_DBT_MALLOC;
2651 }
2652 MYDB_BEGIN_ALLOW_THREADS;
2653 err = self->db->get(self->db, NULL, &key, &data, 0);
2654 MYDB_END_ALLOW_THREADS;
2655 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2656 PyErr_SetObject(PyExc_KeyError, keyobj);
2657 retval = NULL;
2658 }
2659 else if (makeDBError(err)) {
2660 retval = NULL;
2661 }
2662 else {
2663 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2664 FREE_DBT(data);
2665 }
2666
2667 FREE_DBT(key);
2668 return retval;
2669}
2670
2671
2672static int
2673DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2674{
2675 DBT key, data;
2676 int retval;
2677 int flags = 0;
2678
2679 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002680 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2681 PyErr_SetObject(DBError, t);
2682 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002683 return -1;
2684 }
2685
2686 if (!make_key_dbt(self, keyobj, &key, NULL))
2687 return -1;
2688
2689 if (dataobj != NULL) {
2690 if (!make_dbt(dataobj, &data))
2691 retval = -1;
2692 else {
2693 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002694 /* dictionaries shouldn't have duplicate keys */
2695 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 retval = _DB_put(self, NULL, &key, &data, flags);
2697
2698 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002699 /* try deleting any old record that matches and then PUT it
2700 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002701 _DB_delete(self, NULL, &key, 0);
2702 PyErr_Clear();
2703 retval = _DB_put(self, NULL, &key, &data, flags);
2704 }
2705 }
2706 }
2707 else {
2708 /* dataobj == NULL, so delete the key */
2709 retval = _DB_delete(self, NULL, &key, 0);
2710 }
2711 FREE_DBT(key);
2712 return retval;
2713}
2714
2715
2716static PyObject*
2717DB_has_key(DBObject* self, PyObject* args)
2718{
2719 int err;
2720 PyObject* keyobj;
2721 DBT key, data;
2722 PyObject* txnobj = NULL;
2723 DB_TXN *txn = NULL;
2724
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002725 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726 return NULL;
2727 CHECK_DB_NOT_CLOSED(self);
2728 if (!make_key_dbt(self, keyobj, &key, NULL))
2729 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002730 if (!checkTxnObj(txnobj, &txn)) {
2731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002735 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 it has a record but can't allocate a buffer for the data. This saves
2737 having to deal with data we won't be using.
2738 */
2739 CLEAR_DBT(data);
2740 data.flags = DB_DBT_USERMEM;
2741
2742 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002743 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 MYDB_END_ALLOW_THREADS;
2745 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002746
2747 if (err == DB_BUFFER_SMALL || err == 0) {
2748 return PyInt_FromLong(1);
2749 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2750 return PyInt_FromLong(0);
2751 }
2752
2753 makeDBError(err);
2754 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002755}
2756
2757
2758#define _KEYS_LIST 1
2759#define _VALUES_LIST 2
2760#define _ITEMS_LIST 3
2761
2762static PyObject*
2763_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2764{
2765 int err, dbtype;
2766 DBT key;
2767 DBT data;
2768 DBC *cursor;
2769 PyObject* list;
2770 PyObject* item = NULL;
2771
2772 CHECK_DB_NOT_CLOSED(self);
2773 CLEAR_DBT(key);
2774 CLEAR_DBT(data);
2775
2776 dbtype = _DB_get_type(self);
2777 if (dbtype == -1)
2778 return NULL;
2779
2780 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002781 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002782 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002783
2784 /* get a cursor */
2785 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002786 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002787 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002788 if (makeDBError(err)) {
2789 Py_DECREF(list);
2790 return NULL;
2791 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792
2793 if (CHECK_DBFLAG(self, DB_THREAD)) {
2794 key.flags = DB_DBT_REALLOC;
2795 data.flags = DB_DBT_REALLOC;
2796 }
2797
2798 while (1) { /* use the cursor to traverse the DB, collecting items */
2799 MYDB_BEGIN_ALLOW_THREADS;
2800 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2801 MYDB_END_ALLOW_THREADS;
2802
2803 if (err) {
2804 /* for any error, break out of the loop */
2805 break;
2806 }
2807
2808 switch (type) {
2809 case _KEYS_LIST:
2810 switch(dbtype) {
2811 case DB_BTREE:
2812 case DB_HASH:
2813 default:
2814 item = PyString_FromStringAndSize((char*)key.data, key.size);
2815 break;
2816 case DB_RECNO:
2817 case DB_QUEUE:
2818 item = PyInt_FromLong(*((db_recno_t*)key.data));
2819 break;
2820 }
2821 break;
2822
2823 case _VALUES_LIST:
2824 item = PyString_FromStringAndSize((char*)data.data, data.size);
2825 break;
2826
2827 case _ITEMS_LIST:
2828 switch(dbtype) {
2829 case DB_BTREE:
2830 case DB_HASH:
2831 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002832 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2833 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002834 break;
2835 case DB_RECNO:
2836 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002837 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2838 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 break;
2840 }
2841 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002842 default:
2843 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2844 item = NULL;
2845 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 }
2847 if (item == NULL) {
2848 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849 list = NULL;
2850 goto done;
2851 }
2852 PyList_Append(list, item);
2853 Py_DECREF(item);
2854 }
2855
Gregory P. Smithe9477062005-06-04 06:46:59 +00002856 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2857 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 Py_DECREF(list);
2859 list = NULL;
2860 }
2861
2862 done:
2863 FREE_DBT(key);
2864 FREE_DBT(data);
2865 MYDB_BEGIN_ALLOW_THREADS;
2866 cursor->c_close(cursor);
2867 MYDB_END_ALLOW_THREADS;
2868 return list;
2869}
2870
2871
2872static PyObject*
2873DB_keys(DBObject* self, PyObject* args)
2874{
2875 PyObject* txnobj = NULL;
2876 DB_TXN *txn = NULL;
2877
Georg Brandl96a8c392006-05-29 21:04:52 +00002878 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879 return NULL;
2880 if (!checkTxnObj(txnobj, &txn))
2881 return NULL;
2882 return _DB_make_list(self, txn, _KEYS_LIST);
2883}
2884
2885
2886static PyObject*
2887DB_items(DBObject* self, PyObject* args)
2888{
2889 PyObject* txnobj = NULL;
2890 DB_TXN *txn = NULL;
2891
Georg Brandl96a8c392006-05-29 21:04:52 +00002892 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002893 return NULL;
2894 if (!checkTxnObj(txnobj, &txn))
2895 return NULL;
2896 return _DB_make_list(self, txn, _ITEMS_LIST);
2897}
2898
2899
2900static PyObject*
2901DB_values(DBObject* self, PyObject* args)
2902{
2903 PyObject* txnobj = NULL;
2904 DB_TXN *txn = NULL;
2905
Georg Brandl96a8c392006-05-29 21:04:52 +00002906 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907 return NULL;
2908 if (!checkTxnObj(txnobj, &txn))
2909 return NULL;
2910 return _DB_make_list(self, txn, _VALUES_LIST);
2911}
2912
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913/* --------------------------------------------------------------------- */
2914/* DBCursor methods */
2915
2916
2917static PyObject*
2918DBC_close(DBCursorObject* self, PyObject* args)
2919{
2920 int err = 0;
2921
2922 if (!PyArg_ParseTuple(args, ":close"))
2923 return NULL;
2924
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925 if (self->dbc != NULL) {
2926 MYDB_BEGIN_ALLOW_THREADS;
2927 err = self->dbc->c_close(self->dbc);
2928 self->dbc = NULL;
2929 MYDB_END_ALLOW_THREADS;
2930 }
2931 RETURN_IF_ERR();
2932 RETURN_NONE();
2933}
2934
2935
2936static PyObject*
2937DBC_count(DBCursorObject* self, PyObject* args)
2938{
2939 int err = 0;
2940 db_recno_t count;
2941 int flags = 0;
2942
2943 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2944 return NULL;
2945
2946 CHECK_CURSOR_NOT_CLOSED(self);
2947
2948 MYDB_BEGIN_ALLOW_THREADS;
2949 err = self->dbc->c_count(self->dbc, &count, flags);
2950 MYDB_END_ALLOW_THREADS;
2951 RETURN_IF_ERR();
2952
2953 return PyInt_FromLong(count);
2954}
2955
2956
2957static PyObject*
2958DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2959{
2960 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2961}
2962
2963
2964static PyObject*
2965DBC_delete(DBCursorObject* self, PyObject* args)
2966{
2967 int err, flags=0;
2968
2969 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2970 return NULL;
2971
2972 CHECK_CURSOR_NOT_CLOSED(self);
2973
2974 MYDB_BEGIN_ALLOW_THREADS;
2975 err = self->dbc->c_del(self->dbc, flags);
2976 MYDB_END_ALLOW_THREADS;
2977 RETURN_IF_ERR();
2978
2979 self->mydb->haveStat = 0;
2980 RETURN_NONE();
2981}
2982
2983
2984static PyObject*
2985DBC_dup(DBCursorObject* self, PyObject* args)
2986{
2987 int err, flags =0;
2988 DBC* dbc = NULL;
2989
2990 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2991 return NULL;
2992
2993 CHECK_CURSOR_NOT_CLOSED(self);
2994
2995 MYDB_BEGIN_ALLOW_THREADS;
2996 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2997 MYDB_END_ALLOW_THREADS;
2998 RETURN_IF_ERR();
2999
3000 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3001}
3002
3003static PyObject*
3004DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3005{
3006 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3007}
3008
3009
3010static PyObject*
3011DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3012{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003013 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003014 PyObject* keyobj = NULL;
3015 PyObject* dataobj = NULL;
3016 PyObject* retval = NULL;
3017 int dlen = -1;
3018 int doff = -1;
3019 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003020 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003021 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003022
3023 CLEAR_DBT(key);
3024 CLEAR_DBT(data);
3025 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003026 &flags, &dlen, &doff))
3027 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003029 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3030 &kwnames[1],
3031 &keyobj, &flags, &dlen, &doff))
3032 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003034 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3035 kwnames, &keyobj, &dataobj,
3036 &flags, &dlen, &doff))
3037 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003038 return NULL;
3039 }
3040 }
3041 }
3042
3043 CHECK_CURSOR_NOT_CLOSED(self);
3044
3045 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3046 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003047 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3048 (!add_partial_dbt(&data, dlen, doff)) )
3049 {
3050 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003052 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053
3054 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3055 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003056 if (!(key.flags & DB_DBT_REALLOC)) {
3057 key.flags |= DB_DBT_MALLOC;
3058 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059 }
3060
3061 MYDB_BEGIN_ALLOW_THREADS;
3062 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3063 MYDB_END_ALLOW_THREADS;
3064
Gregory P. Smithe9477062005-06-04 06:46:59 +00003065 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3066 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 Py_INCREF(Py_None);
3068 retval = Py_None;
3069 }
3070 else if (makeDBError(err)) {
3071 retval = NULL;
3072 }
3073 else {
3074 switch (_DB_get_type(self->mydb)) {
3075 case -1:
3076 retval = NULL;
3077 break;
3078 case DB_BTREE:
3079 case DB_HASH:
3080 default:
3081 retval = Py_BuildValue("s#s#", key.data, key.size,
3082 data.data, data.size);
3083 break;
3084 case DB_RECNO:
3085 case DB_QUEUE:
3086 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3087 data.data, data.size);
3088 break;
3089 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003090 FREE_DBT(data);
3091 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003092 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003093 return retval;
3094}
3095
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003096#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003097static PyObject*
3098DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3099{
3100 int err, flags=0;
3101 PyObject* keyobj = NULL;
3102 PyObject* dataobj = NULL;
3103 PyObject* retval = NULL;
3104 int dlen = -1;
3105 int doff = -1;
3106 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003107 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3108 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003109
3110 CLEAR_DBT(key);
3111 CLEAR_DBT(data);
3112 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3113 &flags, &dlen, &doff))
3114 {
3115 PyErr_Clear();
3116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003117 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003118 &keyobj, &flags, &dlen, &doff))
3119 {
3120 PyErr_Clear();
3121 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3122 kwnames, &keyobj, &dataobj,
3123 &flags, &dlen, &doff))
3124 {
3125 return NULL;
3126 }
3127 }
3128 }
3129
3130 CHECK_CURSOR_NOT_CLOSED(self);
3131
3132 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3133 return NULL;
3134 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3135 (!add_partial_dbt(&data, dlen, doff)) ) {
3136 FREE_DBT(key);
3137 return NULL;
3138 }
3139
3140 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3141 data.flags = DB_DBT_MALLOC;
3142 if (!(key.flags & DB_DBT_REALLOC)) {
3143 key.flags |= DB_DBT_MALLOC;
3144 }
3145 }
3146
3147 CLEAR_DBT(pkey);
3148 pkey.flags = DB_DBT_MALLOC;
3149
3150 MYDB_BEGIN_ALLOW_THREADS;
3151 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3152 MYDB_END_ALLOW_THREADS;
3153
Gregory P. Smithe9477062005-06-04 06:46:59 +00003154 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3155 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003156 Py_INCREF(Py_None);
3157 retval = Py_None;
3158 }
3159 else if (makeDBError(err)) {
3160 retval = NULL;
3161 }
3162 else {
3163 PyObject *pkeyObj;
3164 PyObject *dataObj;
3165 dataObj = PyString_FromStringAndSize(data.data, data.size);
3166
3167 if (self->mydb->primaryDBType == DB_RECNO ||
3168 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003169 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003170 else
3171 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3172
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003173 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003174 {
3175 PyObject *keyObj;
3176 int type = _DB_get_type(self->mydb);
3177 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003178 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003179 else
3180 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003181#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003182 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003183#else
3184 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3185#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003186 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003187 FREE_DBT(key);
3188 }
3189 else /* return just the pkey and data */
3190 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003191#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003192 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003193#else
3194 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3195#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003196 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003197 Py_DECREF(dataObj);
3198 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199 FREE_DBT(pkey);
3200 FREE_DBT(data);
3201 }
3202 /* the only time REALLOC should be set is if we used an integer
3203 * key that make_key_dbt malloc'd for us. always free these. */
3204 if (key.flags & DB_DBT_REALLOC) {
3205 FREE_DBT(key);
3206 }
3207 return retval;
3208}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003209#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003210
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003211
3212static PyObject*
3213DBC_get_recno(DBCursorObject* self, PyObject* args)
3214{
3215 int err;
3216 db_recno_t recno;
3217 DBT key;
3218 DBT data;
3219
3220 if (!PyArg_ParseTuple(args, ":get_recno"))
3221 return NULL;
3222
3223 CHECK_CURSOR_NOT_CLOSED(self);
3224
3225 CLEAR_DBT(key);
3226 CLEAR_DBT(data);
3227 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3228 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3229 data.flags = DB_DBT_MALLOC;
3230 key.flags = DB_DBT_MALLOC;
3231 }
3232
3233 MYDB_BEGIN_ALLOW_THREADS;
3234 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3235 MYDB_END_ALLOW_THREADS;
3236 RETURN_IF_ERR();
3237
3238 recno = *((db_recno_t*)data.data);
3239 FREE_DBT(key);
3240 FREE_DBT(data);
3241 return PyInt_FromLong(recno);
3242}
3243
3244
3245static PyObject*
3246DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3247{
3248 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3249}
3250
3251
3252static PyObject*
3253DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3254{
3255 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3256}
3257
3258
3259static PyObject*
3260DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3261{
3262 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3263}
3264
3265
3266static PyObject*
3267DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3268{
3269 int err, flags = 0;
3270 PyObject* keyobj, *dataobj;
3271 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003272 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003273 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003274 int dlen = -1;
3275 int doff = -1;
3276
3277 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3278 &keyobj, &dataobj, &flags, &dlen, &doff))
3279 return NULL;
3280
3281 CHECK_CURSOR_NOT_CLOSED(self);
3282
3283 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3284 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003285 if (!make_dbt(dataobj, &data) ||
3286 !add_partial_dbt(&data, dlen, doff) )
3287 {
3288 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003289 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003290 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003291
3292 MYDB_BEGIN_ALLOW_THREADS;
3293 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3294 MYDB_END_ALLOW_THREADS;
3295 FREE_DBT(key);
3296 RETURN_IF_ERR();
3297 self->mydb->haveStat = 0;
3298 RETURN_NONE();
3299}
3300
3301
3302static PyObject*
3303DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3304{
3305 int err, flags = 0;
3306 DBT key, data;
3307 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003308 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003309 int dlen = -1;
3310 int doff = -1;
3311
3312 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3313 &keyobj, &flags, &dlen, &doff))
3314 return NULL;
3315
3316 CHECK_CURSOR_NOT_CLOSED(self);
3317
3318 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3319 return NULL;
3320
3321 CLEAR_DBT(data);
3322 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3323 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3324 data.flags = DB_DBT_MALLOC;
3325 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003326 if (!add_partial_dbt(&data, dlen, doff)) {
3327 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003328 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003329 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003330
3331 MYDB_BEGIN_ALLOW_THREADS;
3332 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3333 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003334 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3335 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003336 Py_INCREF(Py_None);
3337 retval = Py_None;
3338 }
3339 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003340 retval = NULL;
3341 }
3342 else {
3343 switch (_DB_get_type(self->mydb)) {
3344 case -1:
3345 retval = NULL;
3346 break;
3347 case DB_BTREE:
3348 case DB_HASH:
3349 default:
3350 retval = Py_BuildValue("s#s#", key.data, key.size,
3351 data.data, data.size);
3352 break;
3353 case DB_RECNO:
3354 case DB_QUEUE:
3355 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3356 data.data, data.size);
3357 break;
3358 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003359 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003360 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003361 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003362 /* the only time REALLOC should be set is if we used an integer
3363 * key that make_key_dbt malloc'd for us. always free these. */
3364 if (key.flags & DB_DBT_REALLOC) {
3365 FREE_DBT(key);
3366 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003367
3368 return retval;
3369}
3370
3371
3372static PyObject*
3373DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3374{
3375 int err, flags = 0;
3376 DBT key, data;
3377 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003378 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379 int dlen = -1;
3380 int doff = -1;
3381
3382 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3383 &keyobj, &flags, &dlen, &doff))
3384 return NULL;
3385
3386 CHECK_CURSOR_NOT_CLOSED(self);
3387
3388 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3389 return NULL;
3390
3391 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003392 if (!add_partial_dbt(&data, dlen, doff)) {
3393 FREE_DBT(key);
3394 return NULL;
3395 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003396 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3397 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003398 data.flags |= DB_DBT_MALLOC;
3399 /* only BTREE databases will return anything in the key */
3400 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3401 key.flags |= DB_DBT_MALLOC;
3402 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003403 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003404 MYDB_BEGIN_ALLOW_THREADS;
3405 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3406 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003407 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3408 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003409 Py_INCREF(Py_None);
3410 retval = Py_None;
3411 }
3412 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003413 retval = NULL;
3414 }
3415 else {
3416 switch (_DB_get_type(self->mydb)) {
3417 case -1:
3418 retval = NULL;
3419 break;
3420 case DB_BTREE:
3421 case DB_HASH:
3422 default:
3423 retval = Py_BuildValue("s#s#", key.data, key.size,
3424 data.data, data.size);
3425 break;
3426 case DB_RECNO:
3427 case DB_QUEUE:
3428 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3429 data.data, data.size);
3430 break;
3431 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003432 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433 FREE_DBT(data);
3434 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003435 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003436 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003437 if (key.flags & DB_DBT_REALLOC) {
3438 FREE_DBT(key);
3439 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003440
3441 return retval;
3442}
3443
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003445_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3446 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003448 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003450 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451
Gregory P. Smith7441e652003-11-03 21:35:31 +00003452 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003453 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3454 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003455 if (!make_dbt(dataobj, &data)) {
3456 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003458 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459
3460 MYDB_BEGIN_ALLOW_THREADS;
3461 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3462 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003463 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003464 Py_INCREF(Py_None);
3465 retval = Py_None;
3466 }
3467 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003468 retval = NULL;
3469 }
3470 else {
3471 switch (_DB_get_type(self->mydb)) {
3472 case -1:
3473 retval = NULL;
3474 break;
3475 case DB_BTREE:
3476 case DB_HASH:
3477 default:
3478 retval = Py_BuildValue("s#s#", key.data, key.size,
3479 data.data, data.size);
3480 break;
3481 case DB_RECNO:
3482 case DB_QUEUE:
3483 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3484 data.data, data.size);
3485 break;
3486 }
3487 }
3488
3489 FREE_DBT(key);
3490 return retval;
3491}
3492
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003493static PyObject*
3494DBC_get_both(DBCursorObject* self, PyObject* args)
3495{
3496 int flags=0;
3497 PyObject *keyobj, *dataobj;
3498
3499 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3500 return NULL;
3501
Gregory P. Smith7441e652003-11-03 21:35:31 +00003502 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003503 CHECK_CURSOR_NOT_CLOSED(self);
3504
3505 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3506 self->mydb->moduleFlags.getReturnsNone);
3507}
3508
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003509/* Return size of entry */
3510static PyObject*
3511DBC_get_current_size(DBCursorObject* self, PyObject* args)
3512{
3513 int err, flags=DB_CURRENT;
3514 PyObject* retval = NULL;
3515 DBT key, data;
3516
3517 if (!PyArg_ParseTuple(args, ":get_current_size"))
3518 return NULL;
3519 CHECK_CURSOR_NOT_CLOSED(self);
3520 CLEAR_DBT(key);
3521 CLEAR_DBT(data);
3522
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003523 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003524 getting the record size. */
3525 data.flags = DB_DBT_USERMEM;
3526 data.ulen = 0;
3527 MYDB_BEGIN_ALLOW_THREADS;
3528 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3529 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003530 if (err == DB_BUFFER_SMALL || !err) {
3531 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003532 retval = PyInt_FromLong((long)data.size);
3533 err = 0;
3534 }
3535
3536 FREE_DBT(key);
3537 FREE_DBT(data);
3538 RETURN_IF_ERR();
3539 return retval;
3540}
3541
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003542static PyObject*
3543DBC_set_both(DBCursorObject* self, PyObject* args)
3544{
3545 int flags=0;
3546 PyObject *keyobj, *dataobj;
3547
3548 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3549 return NULL;
3550
Gregory P. Smith7441e652003-11-03 21:35:31 +00003551 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003552 CHECK_CURSOR_NOT_CLOSED(self);
3553
3554 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3555 self->mydb->moduleFlags.cursorSetReturnsNone);
3556}
3557
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558
3559static PyObject*
3560DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3561{
3562 int err, irecno, flags=0;
3563 db_recno_t recno;
3564 DBT key, data;
3565 PyObject* retval;
3566 int dlen = -1;
3567 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003568 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569
3570 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3571 &irecno, &flags, &dlen, &doff))
3572 return NULL;
3573
3574 CHECK_CURSOR_NOT_CLOSED(self);
3575
3576 CLEAR_DBT(key);
3577 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003578 /* use allocated space so DB will be able to realloc room for the real
3579 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580 key.data = malloc(sizeof(db_recno_t));
3581 if (key.data == NULL) {
3582 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3583 return NULL;
3584 }
3585 key.size = sizeof(db_recno_t);
3586 key.ulen = key.size;
3587 memcpy(key.data, &recno, sizeof(db_recno_t));
3588 key.flags = DB_DBT_REALLOC;
3589
3590 CLEAR_DBT(data);
3591 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3592 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3593 data.flags = DB_DBT_MALLOC;
3594 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003595 if (!add_partial_dbt(&data, dlen, doff)) {
3596 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003597 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003598 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599
3600 MYDB_BEGIN_ALLOW_THREADS;
3601 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3602 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003603 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3604 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003605 Py_INCREF(Py_None);
3606 retval = Py_None;
3607 }
3608 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003609 retval = NULL;
3610 }
3611 else { /* Can only be used for BTrees, so no need to return int key */
3612 retval = Py_BuildValue("s#s#", key.data, key.size,
3613 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003614 FREE_DBT(data);
3615 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003616 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003617
3618 return retval;
3619}
3620
3621
3622static PyObject*
3623DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3624{
3625 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3626}
3627
3628
3629static PyObject*
3630DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3631{
3632 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3633}
3634
3635
3636static PyObject*
3637DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3638{
3639 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3640}
3641
3642
3643static PyObject*
3644DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3645{
3646 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3647}
3648
3649
3650static PyObject*
3651DBC_join_item(DBCursorObject* self, PyObject* args)
3652{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003653 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003654 DBT key, data;
3655 PyObject* retval;
3656
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003657 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003658 return NULL;
3659
3660 CHECK_CURSOR_NOT_CLOSED(self);
3661
3662 CLEAR_DBT(key);
3663 CLEAR_DBT(data);
3664 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3665 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3666 key.flags = DB_DBT_MALLOC;
3667 }
3668
3669 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003670 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003671 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003672 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3673 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003674 Py_INCREF(Py_None);
3675 retval = Py_None;
3676 }
3677 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003678 retval = NULL;
3679 }
3680 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003681 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 FREE_DBT(key);
3683 }
3684
3685 return retval;
3686}
3687
3688
3689
3690/* --------------------------------------------------------------------- */
3691/* DBEnv methods */
3692
3693
3694static PyObject*
3695DBEnv_close(DBEnvObject* self, PyObject* args)
3696{
3697 int err, flags = 0;
3698
3699 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3700 return NULL;
3701 if (!self->closed) { /* Don't close more than once */
3702 MYDB_BEGIN_ALLOW_THREADS;
3703 err = self->db_env->close(self->db_env, flags);
3704 MYDB_END_ALLOW_THREADS;
3705 /* after calling DBEnv->close, regardless of error, this DBEnv
3706 * may not be accessed again (BerkeleyDB docs). */
3707 self->closed = 1;
3708 self->db_env = NULL;
3709 RETURN_IF_ERR();
3710 }
3711 RETURN_NONE();
3712}
3713
3714
3715static PyObject*
3716DBEnv_open(DBEnvObject* self, PyObject* args)
3717{
3718 int err, flags=0, mode=0660;
3719 char *db_home;
3720
3721 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3722 return NULL;
3723
3724 CHECK_ENV_NOT_CLOSED(self);
3725
3726 MYDB_BEGIN_ALLOW_THREADS;
3727 err = self->db_env->open(self->db_env, db_home, flags, mode);
3728 MYDB_END_ALLOW_THREADS;
3729 RETURN_IF_ERR();
3730 self->closed = 0;
3731 self->flags = flags;
3732 RETURN_NONE();
3733}
3734
3735
3736static PyObject*
3737DBEnv_remove(DBEnvObject* self, PyObject* args)
3738{
3739 int err, flags=0;
3740 char *db_home;
3741
3742 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3743 return NULL;
3744 CHECK_ENV_NOT_CLOSED(self);
3745 MYDB_BEGIN_ALLOW_THREADS;
3746 err = self->db_env->remove(self->db_env, db_home, flags);
3747 MYDB_END_ALLOW_THREADS;
3748 RETURN_IF_ERR();
3749 RETURN_NONE();
3750}
3751
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003752#if (DBVER >= 41)
3753static PyObject*
3754DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3755{
3756 int err;
3757 u_int32_t flags=0;
3758 char *file = NULL;
3759 char *database = NULL;
3760 PyObject *txnobj = NULL;
3761 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003762 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003763 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003764
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003765 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003766 &file, &database, &txnobj, &flags)) {
3767 return NULL;
3768 }
3769 if (!checkTxnObj(txnobj, &txn)) {
3770 return NULL;
3771 }
3772 CHECK_ENV_NOT_CLOSED(self);
3773 MYDB_BEGIN_ALLOW_THREADS;
3774 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3775 MYDB_END_ALLOW_THREADS;
3776 RETURN_IF_ERR();
3777 RETURN_NONE();
3778}
3779
3780static PyObject*
3781DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3782{
3783 int err;
3784 u_int32_t flags=0;
3785 char *file = NULL;
3786 char *database = NULL;
3787 char *newname = NULL;
3788 PyObject *txnobj = NULL;
3789 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003790 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003791 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003792
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003793 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003794 &file, &database, &newname, &txnobj, &flags)) {
3795 return NULL;
3796 }
3797 if (!checkTxnObj(txnobj, &txn)) {
3798 return NULL;
3799 }
3800 CHECK_ENV_NOT_CLOSED(self);
3801 MYDB_BEGIN_ALLOW_THREADS;
3802 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3803 flags);
3804 MYDB_END_ALLOW_THREADS;
3805 RETURN_IF_ERR();
3806 RETURN_NONE();
3807}
3808
3809static PyObject*
3810DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3811{
3812 int err;
3813 u_int32_t flags=0;
3814 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003815 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003816
3817 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3818 &passwd, &flags)) {
3819 return NULL;
3820 }
3821
3822 MYDB_BEGIN_ALLOW_THREADS;
3823 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3824 MYDB_END_ALLOW_THREADS;
3825
3826 RETURN_IF_ERR();
3827 RETURN_NONE();
3828}
3829#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003830
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003831#if (DBVER >= 40)
3832static PyObject*
3833DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3834{
3835 int err;
3836 u_int32_t flags=0;
3837 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003838 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003839
3840 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3841 &timeout, &flags)) {
3842 return NULL;
3843 }
3844
3845 MYDB_BEGIN_ALLOW_THREADS;
3846 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3847 MYDB_END_ALLOW_THREADS;
3848
3849 RETURN_IF_ERR();
3850 RETURN_NONE();
3851}
3852#endif /* DBVER >= 40 */
3853
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003854static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003855DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3856{
3857 int err;
3858 long shm_key = 0;
3859
3860 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3861 return NULL;
3862 CHECK_ENV_NOT_CLOSED(self);
3863
3864 err = self->db_env->set_shm_key(self->db_env, shm_key);
3865 RETURN_IF_ERR();
3866 RETURN_NONE();
3867}
3868
3869static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003870DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3871{
3872 int err, gbytes=0, bytes=0, ncache=0;
3873
3874 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3875 &gbytes, &bytes, &ncache))
3876 return NULL;
3877 CHECK_ENV_NOT_CLOSED(self);
3878
3879 MYDB_BEGIN_ALLOW_THREADS;
3880 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3881 MYDB_END_ALLOW_THREADS;
3882 RETURN_IF_ERR();
3883 RETURN_NONE();
3884}
3885
3886
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003887static PyObject*
3888DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3889{
3890 int err, flags=0, onoff=0;
3891
3892 if (!PyArg_ParseTuple(args, "ii:set_flags",
3893 &flags, &onoff))
3894 return NULL;
3895 CHECK_ENV_NOT_CLOSED(self);
3896
3897 MYDB_BEGIN_ALLOW_THREADS;
3898 err = self->db_env->set_flags(self->db_env, flags, onoff);
3899 MYDB_END_ALLOW_THREADS;
3900 RETURN_IF_ERR();
3901 RETURN_NONE();
3902}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003903
3904
3905static PyObject*
3906DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3907{
3908 int err;
3909 char *dir;
3910
3911 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3912 return NULL;
3913 CHECK_ENV_NOT_CLOSED(self);
3914
3915 MYDB_BEGIN_ALLOW_THREADS;
3916 err = self->db_env->set_data_dir(self->db_env, dir);
3917 MYDB_END_ALLOW_THREADS;
3918 RETURN_IF_ERR();
3919 RETURN_NONE();
3920}
3921
3922
3923static PyObject*
3924DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3925{
3926 int err, lg_bsize;
3927
3928 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3929 return NULL;
3930 CHECK_ENV_NOT_CLOSED(self);
3931
3932 MYDB_BEGIN_ALLOW_THREADS;
3933 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3934 MYDB_END_ALLOW_THREADS;
3935 RETURN_IF_ERR();
3936 RETURN_NONE();
3937}
3938
3939
3940static PyObject*
3941DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3942{
3943 int err;
3944 char *dir;
3945
3946 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3947 return NULL;
3948 CHECK_ENV_NOT_CLOSED(self);
3949
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_lg_dir(self->db_env, dir);
3952 MYDB_END_ALLOW_THREADS;
3953 RETURN_IF_ERR();
3954 RETURN_NONE();
3955}
3956
3957static PyObject*
3958DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3959{
3960 int err, lg_max;
3961
3962 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3963 return NULL;
3964 CHECK_ENV_NOT_CLOSED(self);
3965
3966 MYDB_BEGIN_ALLOW_THREADS;
3967 err = self->db_env->set_lg_max(self->db_env, lg_max);
3968 MYDB_END_ALLOW_THREADS;
3969 RETURN_IF_ERR();
3970 RETURN_NONE();
3971}
3972
3973
Neal Norwitz84562352005-10-20 04:30:15 +00003974#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003975static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003976DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3977{
3978 int err, lg_max;
3979
3980 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3986 MYDB_END_ALLOW_THREADS;
3987 RETURN_IF_ERR();
3988 RETURN_NONE();
3989}
Neal Norwitz84562352005-10-20 04:30:15 +00003990#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00003991
3992
3993static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003994DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3995{
3996 int err, lk_detect;
3997
3998 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3999 return NULL;
4000 CHECK_ENV_NOT_CLOSED(self);
4001
4002 MYDB_BEGIN_ALLOW_THREADS;
4003 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4004 MYDB_END_ALLOW_THREADS;
4005 RETURN_IF_ERR();
4006 RETURN_NONE();
4007}
4008
4009
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004010#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004011static PyObject*
4012DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4013{
4014 int err, max;
4015
4016 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4017 return NULL;
4018 CHECK_ENV_NOT_CLOSED(self);
4019
4020 MYDB_BEGIN_ALLOW_THREADS;
4021 err = self->db_env->set_lk_max(self->db_env, max);
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004026#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004027
4028
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004029
4030static PyObject*
4031DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4032{
4033 int err, max;
4034
4035 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4036 return NULL;
4037 CHECK_ENV_NOT_CLOSED(self);
4038
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->set_lk_max_locks(self->db_env, max);
4041 MYDB_END_ALLOW_THREADS;
4042 RETURN_IF_ERR();
4043 RETURN_NONE();
4044}
4045
4046
4047static PyObject*
4048DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4049{
4050 int err, max;
4051
4052 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4053 return NULL;
4054 CHECK_ENV_NOT_CLOSED(self);
4055
4056 MYDB_BEGIN_ALLOW_THREADS;
4057 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4058 MYDB_END_ALLOW_THREADS;
4059 RETURN_IF_ERR();
4060 RETURN_NONE();
4061}
4062
4063
4064static PyObject*
4065DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4066{
4067 int err, max;
4068
4069 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4070 return NULL;
4071 CHECK_ENV_NOT_CLOSED(self);
4072
4073 MYDB_BEGIN_ALLOW_THREADS;
4074 err = self->db_env->set_lk_max_objects(self->db_env, max);
4075 MYDB_END_ALLOW_THREADS;
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004080
4081static PyObject*
4082DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4083{
4084 int err, mp_mmapsize;
4085
4086 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4087 return NULL;
4088 CHECK_ENV_NOT_CLOSED(self);
4089
4090 MYDB_BEGIN_ALLOW_THREADS;
4091 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4092 MYDB_END_ALLOW_THREADS;
4093 RETURN_IF_ERR();
4094 RETURN_NONE();
4095}
4096
4097
4098static PyObject*
4099DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4100{
4101 int err;
4102 char *dir;
4103
4104 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4105 return NULL;
4106 CHECK_ENV_NOT_CLOSED(self);
4107
4108 MYDB_BEGIN_ALLOW_THREADS;
4109 err = self->db_env->set_tmp_dir(self->db_env, dir);
4110 MYDB_END_ALLOW_THREADS;
4111 RETURN_IF_ERR();
4112 RETURN_NONE();
4113}
4114
4115
4116static PyObject*
4117DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4118{
4119 int flags = 0;
4120 PyObject* txnobj = NULL;
4121 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004122 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004123
4124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4125 &txnobj, &flags))
4126 return NULL;
4127
4128 if (!checkTxnObj(txnobj, &txn))
4129 return NULL;
4130 CHECK_ENV_NOT_CLOSED(self);
4131
4132 return (PyObject*)newDBTxnObject(self, txn, flags);
4133}
4134
4135
4136static PyObject*
4137DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4138{
4139 int err, kbyte=0, min=0, flags=0;
4140
4141 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4144
4145 MYDB_BEGIN_ALLOW_THREADS;
4146#if (DBVER >= 40)
4147 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4148#else
4149 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4150#endif
4151 MYDB_END_ALLOW_THREADS;
4152 RETURN_IF_ERR();
4153 RETURN_NONE();
4154}
4155
4156
4157static PyObject*
4158DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4159{
4160 int err, max;
4161
4162 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4163 return NULL;
4164 CHECK_ENV_NOT_CLOSED(self);
4165
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004166 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004167 RETURN_IF_ERR();
4168 RETURN_NONE();
4169}
4170
4171
4172static PyObject*
4173DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4174{
4175 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004176 long stamp;
4177 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004178
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004179 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004180 return NULL;
4181 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004182 timestamp = (time_t)stamp;
4183 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004184 RETURN_IF_ERR();
4185 RETURN_NONE();
4186}
4187
4188
4189static PyObject*
4190DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4191{
4192 int err, atype, flags=0;
4193 int aborted = 0;
4194
4195 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4196 return NULL;
4197 CHECK_ENV_NOT_CLOSED(self);
4198
4199 MYDB_BEGIN_ALLOW_THREADS;
4200#if (DBVER >= 40)
4201 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4202#else
4203 err = lock_detect(self->db_env, flags, atype, &aborted);
4204#endif
4205 MYDB_END_ALLOW_THREADS;
4206 RETURN_IF_ERR();
4207 return PyInt_FromLong(aborted);
4208}
4209
4210
4211static PyObject*
4212DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4213{
4214 int flags=0;
4215 int locker, lock_mode;
4216 DBT obj;
4217 PyObject* objobj;
4218
4219 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4220 return NULL;
4221
4222
4223 if (!make_dbt(objobj, &obj))
4224 return NULL;
4225
4226 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4227}
4228
4229
4230static PyObject*
4231DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4232{
4233 int err;
4234 u_int32_t theID;
4235
4236 if (!PyArg_ParseTuple(args, ":lock_id"))
4237 return NULL;
4238
4239 CHECK_ENV_NOT_CLOSED(self);
4240 MYDB_BEGIN_ALLOW_THREADS;
4241#if (DBVER >= 40)
4242 err = self->db_env->lock_id(self->db_env, &theID);
4243#else
4244 err = lock_id(self->db_env, &theID);
4245#endif
4246 MYDB_END_ALLOW_THREADS;
4247 RETURN_IF_ERR();
4248
4249 return PyInt_FromLong((long)theID);
4250}
4251
4252
4253static PyObject*
4254DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4255{
4256 int err;
4257 DBLockObject* dblockobj;
4258
4259 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4260 return NULL;
4261
4262 CHECK_ENV_NOT_CLOSED(self);
4263 MYDB_BEGIN_ALLOW_THREADS;
4264#if (DBVER >= 40)
4265 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4266#else
4267 err = lock_put(self->db_env, &dblockobj->lock);
4268#endif
4269 MYDB_END_ALLOW_THREADS;
4270 RETURN_IF_ERR();
4271 RETURN_NONE();
4272}
4273
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004274#if (DBVER >= 44)
4275static PyObject*
4276DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4277{
4278 int err;
4279 char *file;
4280 u_int32_t flags = 0;
4281 static char* kwnames[] = { "file", "flags", NULL};
4282
4283 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4284 &file, &flags))
4285 return NULL;
4286 CHECK_ENV_NOT_CLOSED(self);
4287
4288 MYDB_BEGIN_ALLOW_THREADS;
4289 err = self->db_env->lsn_reset(self->db_env, file, flags);
4290 MYDB_END_ALLOW_THREADS;
4291 RETURN_IF_ERR();
4292 RETURN_NONE();
4293}
4294#endif /* DBVER >= 4.4 */
4295
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004296#if (DBVER >= 40)
4297static PyObject*
4298DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4299{
4300 int err;
4301 DB_LOG_STAT* statp = NULL;
4302 PyObject* d = NULL;
4303 u_int32_t flags = 0;
4304
4305 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4306 return NULL;
4307 CHECK_ENV_NOT_CLOSED(self);
4308
4309 MYDB_BEGIN_ALLOW_THREADS;
4310 err = self->db_env->log_stat(self->db_env, &statp, flags);
4311 MYDB_END_ALLOW_THREADS;
4312 RETURN_IF_ERR();
4313
4314 /* Turn the stat structure into a dictionary */
4315 d = PyDict_New();
4316 if (d == NULL) {
4317 if (statp)
4318 free(statp);
4319 return NULL;
4320 }
4321
4322#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4323
4324 MAKE_ENTRY(magic);
4325 MAKE_ENTRY(version);
4326 MAKE_ENTRY(mode);
4327 MAKE_ENTRY(lg_bsize);
4328#if (DBVER >= 44)
4329 MAKE_ENTRY(lg_size);
4330 MAKE_ENTRY(record);
4331#endif
4332#if (DBVER <= 40)
4333 MAKE_ENTRY(lg_max);
4334#endif
4335 MAKE_ENTRY(w_mbytes);
4336 MAKE_ENTRY(w_bytes);
4337 MAKE_ENTRY(wc_mbytes);
4338 MAKE_ENTRY(wc_bytes);
4339 MAKE_ENTRY(wcount);
4340 MAKE_ENTRY(wcount_fill);
4341#if (DBVER >= 44)
4342 MAKE_ENTRY(rcount);
4343#endif
4344 MAKE_ENTRY(scount);
4345 MAKE_ENTRY(cur_file);
4346 MAKE_ENTRY(cur_offset);
4347 MAKE_ENTRY(disk_file);
4348 MAKE_ENTRY(disk_offset);
4349 MAKE_ENTRY(maxcommitperflush);
4350 MAKE_ENTRY(mincommitperflush);
4351 MAKE_ENTRY(regsize);
4352 MAKE_ENTRY(region_wait);
4353 MAKE_ENTRY(region_nowait);
4354
4355#undef MAKE_ENTRY
4356 free(statp);
4357 return d;
4358} /* DBEnv_log_stat */
4359#endif /* DBVER >= 4.0 for log_stat method */
4360
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004361
4362static PyObject*
4363DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4364{
4365 int err;
4366 DB_LOCK_STAT* sp;
4367 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004368 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004369
4370 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4371 return NULL;
4372 CHECK_ENV_NOT_CLOSED(self);
4373
4374 MYDB_BEGIN_ALLOW_THREADS;
4375#if (DBVER >= 40)
4376 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4377#else
4378#if (DBVER >= 33)
4379 err = lock_stat(self->db_env, &sp);
4380#else
4381 err = lock_stat(self->db_env, &sp, NULL);
4382#endif
4383#endif
4384 MYDB_END_ALLOW_THREADS;
4385 RETURN_IF_ERR();
4386
4387 /* Turn the stat structure into a dictionary */
4388 d = PyDict_New();
4389 if (d == NULL) {
4390 free(sp);
4391 return NULL;
4392 }
4393
4394#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4395
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004396#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004397 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004398#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004399 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004400 MAKE_ENTRY(maxlocks);
4401 MAKE_ENTRY(maxlockers);
4402 MAKE_ENTRY(maxobjects);
4403 MAKE_ENTRY(nlocks);
4404 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004405 MAKE_ENTRY(nlockers);
4406 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004407 MAKE_ENTRY(nobjects);
4408 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004409 MAKE_ENTRY(nrequests);
4410 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004411#if (DBVER < 44)
4412 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004413 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004414#else
4415 MAKE_ENTRY(lock_nowait);
4416 MAKE_ENTRY(lock_wait);
4417#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004418 MAKE_ENTRY(ndeadlocks);
4419 MAKE_ENTRY(regsize);
4420 MAKE_ENTRY(region_wait);
4421 MAKE_ENTRY(region_nowait);
4422
4423#undef MAKE_ENTRY
4424 free(sp);
4425 return d;
4426}
4427
4428
4429static PyObject*
4430DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4431{
4432 int flags=0;
4433 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004434 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004435 PyObject* list;
4436 PyObject* item = NULL;
4437
4438 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4439 return NULL;
4440
4441 CHECK_ENV_NOT_CLOSED(self);
4442 MYDB_BEGIN_ALLOW_THREADS;
4443#if (DBVER >= 40)
4444 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4445#elif (DBVER == 33)
4446 err = log_archive(self->db_env, &log_list, flags);
4447#else
4448 err = log_archive(self->db_env, &log_list, flags, NULL);
4449#endif
4450 MYDB_END_ALLOW_THREADS;
4451 RETURN_IF_ERR();
4452
Gregory P. Smithbad47452006-06-05 00:33:35 +00004453 list = PyList_New(0);
4454 if (list == NULL) {
4455 if (log_list)
4456 free(log_list);
4457 return NULL;
4458 }
4459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004460 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004461 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004462 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4463 item = PyString_FromString (*log_list);
4464 if (item == NULL) {
4465 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004466 list = NULL;
4467 break;
4468 }
4469 PyList_Append(list, item);
4470 Py_DECREF(item);
4471 }
4472 free(log_list_start);
4473 }
4474 return list;
4475}
4476
4477
4478static PyObject*
4479DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4480{
4481 int err;
4482 DB_TXN_STAT* sp;
4483 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004484 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004485
4486 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4487 return NULL;
4488 CHECK_ENV_NOT_CLOSED(self);
4489
4490 MYDB_BEGIN_ALLOW_THREADS;
4491#if (DBVER >= 40)
4492 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4493#elif (DBVER == 33)
4494 err = txn_stat(self->db_env, &sp);
4495#else
4496 err = txn_stat(self->db_env, &sp, NULL);
4497#endif
4498 MYDB_END_ALLOW_THREADS;
4499 RETURN_IF_ERR();
4500
4501 /* Turn the stat structure into a dictionary */
4502 d = PyDict_New();
4503 if (d == NULL) {
4504 free(sp);
4505 return NULL;
4506 }
4507
4508#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004509#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004511 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004512 MAKE_ENTRY(last_txnid);
4513 MAKE_ENTRY(maxtxns);
4514 MAKE_ENTRY(nactive);
4515 MAKE_ENTRY(maxnactive);
4516 MAKE_ENTRY(nbegins);
4517 MAKE_ENTRY(naborts);
4518 MAKE_ENTRY(ncommits);
4519 MAKE_ENTRY(regsize);
4520 MAKE_ENTRY(region_wait);
4521 MAKE_ENTRY(region_nowait);
4522
4523#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004524#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004525 free(sp);
4526 return d;
4527}
4528
4529
4530static PyObject*
4531DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4532{
4533 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004534 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004535
4536 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4537 return NULL;
4538 CHECK_ENV_NOT_CLOSED(self);
4539
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004540 if (self->moduleFlags.getReturnsNone)
4541 ++oldValue;
4542 if (self->moduleFlags.cursorSetReturnsNone)
4543 ++oldValue;
4544 self->moduleFlags.getReturnsNone = (flags >= 1);
4545 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546 return PyInt_FromLong(oldValue);
4547}
4548
4549
4550/* --------------------------------------------------------------------- */
4551/* DBTxn methods */
4552
4553
4554static PyObject*
4555DBTxn_commit(DBTxnObject* self, PyObject* args)
4556{
4557 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004558 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559
4560 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4561 return NULL;
4562
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004563 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004564 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4565 "after txn_commit or txn_abort");
4566 PyErr_SetObject(DBError, t);
4567 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004568 return NULL;
4569 }
4570 txn = self->txn;
4571 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004572 MYDB_BEGIN_ALLOW_THREADS;
4573#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004574 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004575#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004576 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004577#endif
4578 MYDB_END_ALLOW_THREADS;
4579 RETURN_IF_ERR();
4580 RETURN_NONE();
4581}
4582
4583static PyObject*
4584DBTxn_prepare(DBTxnObject* self, PyObject* args)
4585{
4586#if (DBVER >= 33)
4587 int err;
4588 char* gid=NULL;
4589 int gid_size=0;
4590
4591 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4592 return NULL;
4593
4594 if (gid_size != DB_XIDDATASIZE) {
4595 PyErr_SetString(PyExc_TypeError,
4596 "gid must be DB_XIDDATASIZE bytes long");
4597 return NULL;
4598 }
4599
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004600 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004601 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4602 "after txn_commit or txn_abort");
4603 PyErr_SetObject(DBError, t);
4604 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004605 return NULL;
4606 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607 MYDB_BEGIN_ALLOW_THREADS;
4608#if (DBVER >= 40)
4609 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4610#else
4611 err = txn_prepare(self->txn, (u_int8_t*)gid);
4612#endif
4613 MYDB_END_ALLOW_THREADS;
4614 RETURN_IF_ERR();
4615 RETURN_NONE();
4616#else
4617 int err;
4618
4619 if (!PyArg_ParseTuple(args, ":prepare"))
4620 return NULL;
4621
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004622 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004623 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4624 "after txn_commit or txn_abort");
4625 PyErr_SetObject(DBError, t);
4626 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004627 return NULL;
4628 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004629 MYDB_BEGIN_ALLOW_THREADS;
4630 err = txn_prepare(self->txn);
4631 MYDB_END_ALLOW_THREADS;
4632 RETURN_IF_ERR();
4633 RETURN_NONE();
4634#endif
4635}
4636
4637
4638static PyObject*
4639DBTxn_abort(DBTxnObject* self, PyObject* args)
4640{
4641 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004642 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004643
4644 if (!PyArg_ParseTuple(args, ":abort"))
4645 return NULL;
4646
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004647 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004648 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4649 "after txn_commit or txn_abort");
4650 PyErr_SetObject(DBError, t);
4651 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004652 return NULL;
4653 }
4654 txn = self->txn;
4655 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004656 MYDB_BEGIN_ALLOW_THREADS;
4657#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004658 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004659#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004660 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661#endif
4662 MYDB_END_ALLOW_THREADS;
4663 RETURN_IF_ERR();
4664 RETURN_NONE();
4665}
4666
4667
4668static PyObject*
4669DBTxn_id(DBTxnObject* self, PyObject* args)
4670{
4671 int id;
4672
4673 if (!PyArg_ParseTuple(args, ":id"))
4674 return NULL;
4675
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004676 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004677 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4678 "after txn_commit or txn_abort");
4679 PyErr_SetObject(DBError, t);
4680 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004681 return NULL;
4682 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683 MYDB_BEGIN_ALLOW_THREADS;
4684#if (DBVER >= 40)
4685 id = self->txn->id(self->txn);
4686#else
4687 id = txn_id(self->txn);
4688#endif
4689 MYDB_END_ALLOW_THREADS;
4690 return PyInt_FromLong(id);
4691}
4692
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004693#if (DBVER >= 43)
4694/* --------------------------------------------------------------------- */
4695/* DBSequence methods */
4696
4697
4698static PyObject*
4699DBSequence_close(DBSequenceObject* self, PyObject* args)
4700{
4701 int err, flags=0;
4702 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4703 return NULL;
4704 CHECK_SEQUENCE_NOT_CLOSED(self)
4705
4706 MYDB_BEGIN_ALLOW_THREADS
4707 err = self->sequence->close(self->sequence, flags);
4708 self->sequence = NULL;
4709 MYDB_END_ALLOW_THREADS
4710
4711 RETURN_IF_ERR();
4712
4713 RETURN_NONE();
4714}
4715
4716static PyObject*
4717DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4718{
4719 int err, flags = 0;
4720 int delta = 1;
4721 db_seq_t value;
4722 PyObject *txnobj = NULL;
4723 DB_TXN *txn = NULL;
4724 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4725 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4726 return NULL;
4727 CHECK_SEQUENCE_NOT_CLOSED(self)
4728
4729 if (!checkTxnObj(txnobj, &txn))
4730 return NULL;
4731
4732 MYDB_BEGIN_ALLOW_THREADS
4733 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4734 MYDB_END_ALLOW_THREADS
4735
4736 RETURN_IF_ERR();
4737 return PyLong_FromLongLong(value);
4738
4739}
4740
4741static PyObject*
4742DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4743{
4744 if (!PyArg_ParseTuple(args,":get_dbp"))
4745 return NULL;
4746 CHECK_SEQUENCE_NOT_CLOSED(self)
4747 Py_INCREF(self->mydb);
4748 return (PyObject* )self->mydb;
4749}
4750
4751static PyObject*
4752DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4753{
4754 int err;
4755 DBT key;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004756 PyObject *retval;
4757 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004758 CHECK_SEQUENCE_NOT_CLOSED(self)
4759 MYDB_BEGIN_ALLOW_THREADS
4760 err = self->sequence->get_key(self->sequence, &key);
4761 MYDB_END_ALLOW_THREADS
4762
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004763 if (!err)
4764 retval = PyString_FromStringAndSize(key.data, key.size);
4765
4766 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004767 RETURN_IF_ERR();
4768
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004769 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004770}
4771
4772static PyObject*
4773DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4774{
4775 int err;
4776 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004777 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004778 return NULL;
4779 CHECK_SEQUENCE_NOT_CLOSED(self)
4780
4781 MYDB_BEGIN_ALLOW_THREADS
4782 err = self->sequence->initial_value(self->sequence, value);
4783 MYDB_END_ALLOW_THREADS
4784
4785 RETURN_IF_ERR();
4786
4787 RETURN_NONE();
4788}
4789
4790static PyObject*
4791DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4792{
4793 int err, flags = 0;
4794 PyObject* keyobj;
4795 PyObject *txnobj = NULL;
4796 DB_TXN *txn = NULL;
4797 DBT key;
4798
4799 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004801 return NULL;
4802
4803 if (!checkTxnObj(txnobj, &txn))
4804 return NULL;
4805
4806 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4807 return NULL;
4808
4809 MYDB_BEGIN_ALLOW_THREADS
4810 err = self->sequence->open(self->sequence, txn, &key, flags);
4811 MYDB_END_ALLOW_THREADS
4812
4813 CLEAR_DBT(key);
4814 RETURN_IF_ERR();
4815
4816 RETURN_NONE();
4817}
4818
4819static PyObject*
4820DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4821{
4822 int err, flags = 0;
4823 PyObject *txnobj = NULL;
4824 DB_TXN *txn = NULL;
4825
4826 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004827 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004828 return NULL;
4829
4830 if (!checkTxnObj(txnobj, &txn))
4831 return NULL;
4832
4833 CHECK_SEQUENCE_NOT_CLOSED(self)
4834
4835 MYDB_BEGIN_ALLOW_THREADS
4836 err = self->sequence->remove(self->sequence, txn, flags);
4837 MYDB_END_ALLOW_THREADS
4838
4839 RETURN_IF_ERR();
4840 RETURN_NONE();
4841}
4842
4843static PyObject*
4844DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4845{
4846 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004847 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004848 return NULL;
4849 CHECK_SEQUENCE_NOT_CLOSED(self)
4850
4851 MYDB_BEGIN_ALLOW_THREADS
4852 err = self->sequence->set_cachesize(self->sequence, size);
4853 MYDB_END_ALLOW_THREADS
4854
4855 RETURN_IF_ERR();
4856 RETURN_NONE();
4857}
4858
4859static PyObject*
4860DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4861{
4862 int err, size;
4863 if (!PyArg_ParseTuple(args,":get_cachesize"))
4864 return NULL;
4865 CHECK_SEQUENCE_NOT_CLOSED(self)
4866
4867 MYDB_BEGIN_ALLOW_THREADS
4868 err = self->sequence->get_cachesize(self->sequence, &size);
4869 MYDB_END_ALLOW_THREADS
4870
4871 RETURN_IF_ERR();
4872 return PyInt_FromLong(size);
4873}
4874
4875static PyObject*
4876DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4877{
4878 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004879 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004880 return NULL;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882
4883 MYDB_BEGIN_ALLOW_THREADS
4884 err = self->sequence->set_flags(self->sequence, flags);
4885 MYDB_END_ALLOW_THREADS
4886
4887 RETURN_IF_ERR();
4888 RETURN_NONE();
4889
4890}
4891
4892static PyObject*
4893DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4894{
4895 unsigned int flags;
4896 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004897 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004898 return NULL;
4899 CHECK_SEQUENCE_NOT_CLOSED(self)
4900
4901 MYDB_BEGIN_ALLOW_THREADS
4902 err = self->sequence->get_flags(self->sequence, &flags);
4903 MYDB_END_ALLOW_THREADS
4904
4905 RETURN_IF_ERR();
4906 return PyInt_FromLong((int)flags);
4907}
4908
4909static PyObject*
4910DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4911{
4912 int err;
4913 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004914 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004915 return NULL;
4916 CHECK_SEQUENCE_NOT_CLOSED(self)
4917
4918 MYDB_BEGIN_ALLOW_THREADS
4919 err = self->sequence->set_range(self->sequence, min, max);
4920 MYDB_END_ALLOW_THREADS
4921
4922 RETURN_IF_ERR();
4923 RETURN_NONE();
4924}
4925
4926static PyObject*
4927DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4928{
4929 int err;
4930 db_seq_t min, max;
4931 if (!PyArg_ParseTuple(args,":get_range"))
4932 return NULL;
4933 CHECK_SEQUENCE_NOT_CLOSED(self)
4934
4935 MYDB_BEGIN_ALLOW_THREADS
4936 err = self->sequence->get_range(self->sequence, &min, &max);
4937 MYDB_END_ALLOW_THREADS
4938
4939 RETURN_IF_ERR();
4940 return Py_BuildValue("(LL)", min, max);
4941}
4942
4943static PyObject*
4944DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4945{
4946 int err, flags = 0;
4947 DB_SEQUENCE_STAT* sp = NULL;
4948 PyObject* dict_stat;
4949 static char* kwnames[] = {"flags", NULL };
4950 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4951 return NULL;
4952 CHECK_SEQUENCE_NOT_CLOSED(self);
4953
4954 MYDB_BEGIN_ALLOW_THREADS;
4955 err = self->sequence->stat(self->sequence, &sp, flags);
4956 MYDB_END_ALLOW_THREADS;
4957 RETURN_IF_ERR();
4958
4959 if ((dict_stat = PyDict_New()) == NULL) {
4960 free(sp);
4961 return NULL;
4962 }
4963
4964
4965#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4966#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4967
4968 MAKE_INT_ENTRY(wait);
4969 MAKE_INT_ENTRY(nowait);
4970 MAKE_LONG_LONG_ENTRY(current);
4971 MAKE_LONG_LONG_ENTRY(value);
4972 MAKE_LONG_LONG_ENTRY(last_value);
4973 MAKE_LONG_LONG_ENTRY(min);
4974 MAKE_LONG_LONG_ENTRY(max);
4975 MAKE_INT_ENTRY(cache_size);
4976 MAKE_INT_ENTRY(flags);
4977
4978#undef MAKE_INT_ENTRY
4979#undef MAKE_LONG_LONG_ENTRY
4980
4981 free(sp);
4982 return dict_stat;
4983}
4984#endif
4985
4986
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004987/* --------------------------------------------------------------------- */
4988/* Method definition tables and type objects */
4989
4990static PyMethodDef DB_methods[] = {
4991 {"append", (PyCFunction)DB_append, METH_VARARGS},
4992#if (DBVER >= 33)
4993 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4994#endif
4995 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004996 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4997 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004998 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4999 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5000 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5001 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005002#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005003 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005004#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005005 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5006 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5007 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5008 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5009 {"join", (PyCFunction)DB_join, METH_VARARGS},
5010 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5011 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5012 {"items", (PyCFunction)DB_items, METH_VARARGS},
5013 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5014 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5015 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5016 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5017 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5018 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005019#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005020 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005021#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005022 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005023#if (DBVER >= 41)
5024 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5025#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005026 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5027 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5028 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5029 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5030 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5031 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5032 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5033 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5034 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005035 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005036 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005037 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5038#if (DBVER >= 33)
5039 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5040#endif
5041 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5042 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5043 {"values", (PyCFunction)DB_values, METH_VARARGS},
5044 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5045 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5046 {NULL, NULL} /* sentinel */
5047};
5048
5049
5050static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005051 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005052 (binaryfunc)DB_subscript, /*mp_subscript*/
5053 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5054};
5055
5056
5057static PyMethodDef DBCursor_methods[] = {
5058 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5059 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5060 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5061 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5062 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5063 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5064 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005065#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005066 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005067#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005068 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5069 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5070 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5071 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5072 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5073 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5074 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5075 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005076 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005077 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005078 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5079 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5080 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5081 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5082 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5083 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5084 {NULL, NULL} /* sentinel */
5085};
5086
5087
5088static PyMethodDef DBEnv_methods[] = {
5089 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5090 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5091 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005092#if (DBVER >= 41)
5093 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5094 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5095 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5096#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005097#if (DBVER >= 40)
5098 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5099#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005100 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005101 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5102 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005103 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005104 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5105 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5106 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005107#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005108 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005109#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005110 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005111#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005112 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005113#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005114 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5115 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5116 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005117 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5118 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5119 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5120 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5121 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5122 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005123 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005124 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5125 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5126 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5127 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5128 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5129 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005130#if (DBVER >= 40)
5131 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5132#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005133#if (DBVER >= 44)
5134 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5135#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005136 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5137 {NULL, NULL} /* sentinel */
5138};
5139
5140
5141static PyMethodDef DBTxn_methods[] = {
5142 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5143 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5144 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5145 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5146 {NULL, NULL} /* sentinel */
5147};
5148
5149
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005150#if (DBVER >= 43)
5151static PyMethodDef DBSequence_methods[] = {
5152 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5153 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5154 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5155 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005156 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5157 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5158 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5159 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5160 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5161 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5162 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5163 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5164 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5165 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5166 {NULL, NULL} /* sentinel */
5167};
5168#endif
5169
5170
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005171static PyObject*
5172DB_getattr(DBObject* self, char *name)
5173{
5174 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5175}
5176
5177
5178static PyObject*
5179DBEnv_getattr(DBEnvObject* self, char *name)
5180{
5181 if (!strcmp(name, "db_home")) {
5182 CHECK_ENV_NOT_CLOSED(self);
5183 if (self->db_env->db_home == NULL) {
5184 RETURN_NONE();
5185 }
5186 return PyString_FromString(self->db_env->db_home);
5187 }
5188
5189 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5190}
5191
5192
5193static PyObject*
5194DBCursor_getattr(DBCursorObject* self, char *name)
5195{
5196 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5197}
5198
5199static PyObject*
5200DBTxn_getattr(DBTxnObject* self, char *name)
5201{
5202 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5203}
5204
5205static PyObject*
5206DBLock_getattr(DBLockObject* self, char *name)
5207{
5208 return NULL;
5209}
5210
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005211#if (DBVER >= 43)
5212static PyObject*
5213DBSequence_getattr(DBSequenceObject* self, char *name)
5214{
5215 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5216}
5217#endif
5218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005219statichere PyTypeObject DB_Type = {
5220 PyObject_HEAD_INIT(NULL)
5221 0, /*ob_size*/
5222 "DB", /*tp_name*/
5223 sizeof(DBObject), /*tp_basicsize*/
5224 0, /*tp_itemsize*/
5225 /* methods */
5226 (destructor)DB_dealloc, /*tp_dealloc*/
5227 0, /*tp_print*/
5228 (getattrfunc)DB_getattr, /*tp_getattr*/
5229 0, /*tp_setattr*/
5230 0, /*tp_compare*/
5231 0, /*tp_repr*/
5232 0, /*tp_as_number*/
5233 0, /*tp_as_sequence*/
5234 &DB_mapping,/*tp_as_mapping*/
5235 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005236 0, /* tp_call */
5237 0, /* tp_str */
5238 0, /* tp_getattro */
5239 0, /* tp_setattro */
5240 0, /* tp_as_buffer */
5241 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5242 0, /* tp_doc */
5243 0, /* tp_traverse */
5244 0, /* tp_clear */
5245 0, /* tp_richcompare */
5246 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005247};
5248
5249
5250statichere PyTypeObject DBCursor_Type = {
5251 PyObject_HEAD_INIT(NULL)
5252 0, /*ob_size*/
5253 "DBCursor", /*tp_name*/
5254 sizeof(DBCursorObject), /*tp_basicsize*/
5255 0, /*tp_itemsize*/
5256 /* methods */
5257 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5258 0, /*tp_print*/
5259 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5260 0, /*tp_setattr*/
5261 0, /*tp_compare*/
5262 0, /*tp_repr*/
5263 0, /*tp_as_number*/
5264 0, /*tp_as_sequence*/
5265 0, /*tp_as_mapping*/
5266 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005267 0, /* tp_call */
5268 0, /* tp_str */
5269 0, /* tp_getattro */
5270 0, /* tp_setattro */
5271 0, /* tp_as_buffer */
5272 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5273 0, /* tp_doc */
5274 0, /* tp_traverse */
5275 0, /* tp_clear */
5276 0, /* tp_richcompare */
5277 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005278};
5279
5280
5281statichere PyTypeObject DBEnv_Type = {
5282 PyObject_HEAD_INIT(NULL)
5283 0, /*ob_size*/
5284 "DBEnv", /*tp_name*/
5285 sizeof(DBEnvObject), /*tp_basicsize*/
5286 0, /*tp_itemsize*/
5287 /* methods */
5288 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5289 0, /*tp_print*/
5290 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5291 0, /*tp_setattr*/
5292 0, /*tp_compare*/
5293 0, /*tp_repr*/
5294 0, /*tp_as_number*/
5295 0, /*tp_as_sequence*/
5296 0, /*tp_as_mapping*/
5297 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005298 0, /* tp_call */
5299 0, /* tp_str */
5300 0, /* tp_getattro */
5301 0, /* tp_setattro */
5302 0, /* tp_as_buffer */
5303 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5304 0, /* tp_doc */
5305 0, /* tp_traverse */
5306 0, /* tp_clear */
5307 0, /* tp_richcompare */
5308 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005309};
5310
5311statichere PyTypeObject DBTxn_Type = {
5312 PyObject_HEAD_INIT(NULL)
5313 0, /*ob_size*/
5314 "DBTxn", /*tp_name*/
5315 sizeof(DBTxnObject), /*tp_basicsize*/
5316 0, /*tp_itemsize*/
5317 /* methods */
5318 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5319 0, /*tp_print*/
5320 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5321 0, /*tp_setattr*/
5322 0, /*tp_compare*/
5323 0, /*tp_repr*/
5324 0, /*tp_as_number*/
5325 0, /*tp_as_sequence*/
5326 0, /*tp_as_mapping*/
5327 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005328 0, /* tp_call */
5329 0, /* tp_str */
5330 0, /* tp_getattro */
5331 0, /* tp_setattro */
5332 0, /* tp_as_buffer */
5333 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5334 0, /* tp_doc */
5335 0, /* tp_traverse */
5336 0, /* tp_clear */
5337 0, /* tp_richcompare */
5338 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005339};
5340
5341
5342statichere PyTypeObject DBLock_Type = {
5343 PyObject_HEAD_INIT(NULL)
5344 0, /*ob_size*/
5345 "DBLock", /*tp_name*/
5346 sizeof(DBLockObject), /*tp_basicsize*/
5347 0, /*tp_itemsize*/
5348 /* methods */
5349 (destructor)DBLock_dealloc, /*tp_dealloc*/
5350 0, /*tp_print*/
5351 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5352 0, /*tp_setattr*/
5353 0, /*tp_compare*/
5354 0, /*tp_repr*/
5355 0, /*tp_as_number*/
5356 0, /*tp_as_sequence*/
5357 0, /*tp_as_mapping*/
5358 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005359 0, /* tp_call */
5360 0, /* tp_str */
5361 0, /* tp_getattro */
5362 0, /* tp_setattro */
5363 0, /* tp_as_buffer */
5364 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5365 0, /* tp_doc */
5366 0, /* tp_traverse */
5367 0, /* tp_clear */
5368 0, /* tp_richcompare */
5369 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005370};
5371
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005372#if (DBVER >= 43)
5373statichere PyTypeObject DBSequence_Type = {
5374 PyObject_HEAD_INIT(NULL)
5375 0, /*ob_size*/
5376 "DBSequence", /*tp_name*/
5377 sizeof(DBSequenceObject), /*tp_basicsize*/
5378 0, /*tp_itemsize*/
5379 /* methods */
5380 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5381 0, /*tp_print*/
5382 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5383 0, /*tp_setattr*/
5384 0, /*tp_compare*/
5385 0, /*tp_repr*/
5386 0, /*tp_as_number*/
5387 0, /*tp_as_sequence*/
5388 0, /*tp_as_mapping*/
5389 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005390 0, /* tp_call */
5391 0, /* tp_str */
5392 0, /* tp_getattro */
5393 0, /* tp_setattro */
5394 0, /* tp_as_buffer */
5395 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5396 0, /* tp_doc */
5397 0, /* tp_traverse */
5398 0, /* tp_clear */
5399 0, /* tp_richcompare */
5400 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005401};
5402#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005403
5404/* --------------------------------------------------------------------- */
5405/* Module-level functions */
5406
5407static PyObject*
5408DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5409{
5410 PyObject* dbenvobj = NULL;
5411 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005412 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005413
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5415 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005416 return NULL;
5417 if (dbenvobj == Py_None)
5418 dbenvobj = NULL;
5419 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5420 makeTypeError("DBEnv", dbenvobj);
5421 return NULL;
5422 }
5423
5424 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5425}
5426
5427
5428static PyObject*
5429DBEnv_construct(PyObject* self, PyObject* args)
5430{
5431 int flags = 0;
5432 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5433 return (PyObject* )newDBEnvObject(flags);
5434}
5435
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005436#if (DBVER >= 43)
5437static PyObject*
5438DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5439{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005440 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005441 int flags = 0;
5442 static char* kwnames[] = { "db", "flags", NULL};
5443
5444 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5445 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005446 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005447 makeTypeError("DB", dbobj);
5448 return NULL;
5449 }
5450 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5451}
5452#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005453
5454static char bsddb_version_doc[] =
5455"Returns a tuple of major, minor, and patch release numbers of the\n\
5456underlying DB library.";
5457
5458static PyObject*
5459bsddb_version(PyObject* self, PyObject* args)
5460{
5461 int major, minor, patch;
5462
5463 if (!PyArg_ParseTuple(args, ":version"))
5464 return NULL;
5465 db_version(&major, &minor, &patch);
5466 return Py_BuildValue("(iii)", major, minor, patch);
5467}
5468
5469
5470/* List of functions defined in the module */
5471
5472static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005473 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5474 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5475#if (DBVER >= 43)
5476 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5477#endif
5478 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005479 {NULL, NULL} /* sentinel */
5480};
5481
Gregory P. Smith39250532007-10-09 06:02:21 +00005482/* API structure */
5483static BSDDB_api bsddb_api;
5484
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005485
5486/* --------------------------------------------------------------------- */
5487/* Module initialization */
5488
5489
5490/* Convenience routine to export an integer value.
5491 * Errors are silently ignored, for better or for worse...
5492 */
5493#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5494
Gregory P. Smith41631e82003-09-21 00:08:14 +00005495#define MODULE_NAME_MAX_LEN 11
5496static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005497
5498DL_EXPORT(void) init_bsddb(void)
5499{
5500 PyObject* m;
5501 PyObject* d;
5502 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5503 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5504 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005505 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005506
5507 /* Initialize the type of the new type objects here; doing it here
5508 is required for portability to Windows without requiring C++. */
Martin v. Löwis68192102007-07-21 06:55:02 +00005509 Py_Type(&DB_Type) = &PyType_Type;
5510 Py_Type(&DBCursor_Type) = &PyType_Type;
5511 Py_Type(&DBEnv_Type) = &PyType_Type;
5512 Py_Type(&DBTxn_Type) = &PyType_Type;
5513 Py_Type(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005514#if (DBVER >= 43)
Martin v. Löwis68192102007-07-21 06:55:02 +00005515 Py_Type(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005516#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005517
5518
Mark Hammonda69d4092003-04-22 23:13:27 +00005519#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005520 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005521 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005522#endif
5523
5524 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005525 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005526 if (m == NULL)
5527 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005528
5529 /* Add some symbolic constants to the module */
5530 d = PyModule_GetDict(m);
5531 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5532 PyDict_SetItemString(d, "cvsid", cvsid_s);
5533 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5534 Py_DECREF(pybsddb_version_s);
5535 pybsddb_version_s = NULL;
5536 Py_DECREF(cvsid_s);
5537 cvsid_s = NULL;
5538 Py_DECREF(db_version_s);
5539 db_version_s = NULL;
5540
5541 ADD_INT(d, DB_VERSION_MAJOR);
5542 ADD_INT(d, DB_VERSION_MINOR);
5543 ADD_INT(d, DB_VERSION_PATCH);
5544
5545 ADD_INT(d, DB_MAX_PAGES);
5546 ADD_INT(d, DB_MAX_RECORDS);
5547
Gregory P. Smith41631e82003-09-21 00:08:14 +00005548#if (DBVER >= 42)
5549 ADD_INT(d, DB_RPCCLIENT);
5550#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005551 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005552 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5553 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5554#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005555 ADD_INT(d, DB_XA_CREATE);
5556
5557 ADD_INT(d, DB_CREATE);
5558 ADD_INT(d, DB_NOMMAP);
5559 ADD_INT(d, DB_THREAD);
5560
5561 ADD_INT(d, DB_FORCE);
5562 ADD_INT(d, DB_INIT_CDB);
5563 ADD_INT(d, DB_INIT_LOCK);
5564 ADD_INT(d, DB_INIT_LOG);
5565 ADD_INT(d, DB_INIT_MPOOL);
5566 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005567 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005568
5569 ADD_INT(d, DB_RECOVER);
5570 ADD_INT(d, DB_RECOVER_FATAL);
5571 ADD_INT(d, DB_TXN_NOSYNC);
5572 ADD_INT(d, DB_USE_ENVIRON);
5573 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5574
5575 ADD_INT(d, DB_LOCKDOWN);
5576 ADD_INT(d, DB_PRIVATE);
5577 ADD_INT(d, DB_SYSTEM_MEM);
5578
5579 ADD_INT(d, DB_TXN_SYNC);
5580 ADD_INT(d, DB_TXN_NOWAIT);
5581
5582 ADD_INT(d, DB_EXCL);
5583 ADD_INT(d, DB_FCNTL_LOCKING);
5584 ADD_INT(d, DB_ODDFILESIZE);
5585 ADD_INT(d, DB_RDWRMASTER);
5586 ADD_INT(d, DB_RDONLY);
5587 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005588 ADD_INT(d, DB_EXTENT);
5589 ADD_INT(d, DB_CDB_ALLDB);
5590 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005591 ADD_INT(d, DB_UPGRADE);
5592
5593 ADD_INT(d, DB_AGGRESSIVE);
5594 ADD_INT(d, DB_NOORDERCHK);
5595 ADD_INT(d, DB_ORDERCHKONLY);
5596 ADD_INT(d, DB_PR_PAGE);
5597#if ! (DBVER >= 33)
5598 ADD_INT(d, DB_VRFY_FLAGMASK);
5599 ADD_INT(d, DB_PR_HEADERS);
5600#endif
5601 ADD_INT(d, DB_PR_RECOVERYTEST);
5602 ADD_INT(d, DB_SALVAGE);
5603
5604 ADD_INT(d, DB_LOCK_NORUN);
5605 ADD_INT(d, DB_LOCK_DEFAULT);
5606 ADD_INT(d, DB_LOCK_OLDEST);
5607 ADD_INT(d, DB_LOCK_RANDOM);
5608 ADD_INT(d, DB_LOCK_YOUNGEST);
5609#if (DBVER >= 33)
5610 ADD_INT(d, DB_LOCK_MAXLOCKS);
5611 ADD_INT(d, DB_LOCK_MINLOCKS);
5612 ADD_INT(d, DB_LOCK_MINWRITE);
5613#endif
5614
5615
5616#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005617 /* docs say to use zero instead */
5618 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005619#else
5620 ADD_INT(d, DB_LOCK_CONFLICT);
5621#endif
5622
5623 ADD_INT(d, DB_LOCK_DUMP);
5624 ADD_INT(d, DB_LOCK_GET);
5625 ADD_INT(d, DB_LOCK_INHERIT);
5626 ADD_INT(d, DB_LOCK_PUT);
5627 ADD_INT(d, DB_LOCK_PUT_ALL);
5628 ADD_INT(d, DB_LOCK_PUT_OBJ);
5629
5630 ADD_INT(d, DB_LOCK_NG);
5631 ADD_INT(d, DB_LOCK_READ);
5632 ADD_INT(d, DB_LOCK_WRITE);
5633 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005634 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005635 ADD_INT(d, DB_LOCK_IWRITE);
5636 ADD_INT(d, DB_LOCK_IREAD);
5637 ADD_INT(d, DB_LOCK_IWR);
5638#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005639#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005640 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005641#else
5642 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5643#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644 ADD_INT(d, DB_LOCK_WWRITE);
5645#endif
5646
5647 ADD_INT(d, DB_LOCK_RECORD);
5648 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005650#if (DBVER >= 33)
5651 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5652#endif
5653
5654 ADD_INT(d, DB_LOCK_NOWAIT);
5655 ADD_INT(d, DB_LOCK_RECORD);
5656 ADD_INT(d, DB_LOCK_UPGRADE);
5657
5658#if (DBVER >= 33)
5659 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005660#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005661 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005662#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005663 ADD_INT(d, DB_LSTAT_FREE);
5664 ADD_INT(d, DB_LSTAT_HELD);
5665#if (DBVER == 33)
5666 ADD_INT(d, DB_LSTAT_NOGRANT);
5667#endif
5668 ADD_INT(d, DB_LSTAT_PENDING);
5669 ADD_INT(d, DB_LSTAT_WAITING);
5670#endif
5671
5672 ADD_INT(d, DB_ARCH_ABS);
5673 ADD_INT(d, DB_ARCH_DATA);
5674 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005675#if (DBVER >= 42)
5676 ADD_INT(d, DB_ARCH_REMOVE);
5677#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678
5679 ADD_INT(d, DB_BTREE);
5680 ADD_INT(d, DB_HASH);
5681 ADD_INT(d, DB_RECNO);
5682 ADD_INT(d, DB_QUEUE);
5683 ADD_INT(d, DB_UNKNOWN);
5684
5685 ADD_INT(d, DB_DUP);
5686 ADD_INT(d, DB_DUPSORT);
5687 ADD_INT(d, DB_RECNUM);
5688 ADD_INT(d, DB_RENUMBER);
5689 ADD_INT(d, DB_REVSPLITOFF);
5690 ADD_INT(d, DB_SNAPSHOT);
5691
5692 ADD_INT(d, DB_JOIN_NOSORT);
5693
5694 ADD_INT(d, DB_AFTER);
5695 ADD_INT(d, DB_APPEND);
5696 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005697#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005698 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005699#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005700#if (DBVER >= 41)
5701 _addIntToDict(d, "DB_CHECKPOINT", 0);
5702#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005703 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005704 ADD_INT(d, DB_CURLSN);
5705#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005706#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005707 ADD_INT(d, DB_COMMIT);
5708#endif
5709 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005710 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711 ADD_INT(d, DB_CURRENT);
5712#if (DBVER >= 33)
5713 ADD_INT(d, DB_FAST_STAT);
5714#endif
5715 ADD_INT(d, DB_FIRST);
5716 ADD_INT(d, DB_FLUSH);
5717 ADD_INT(d, DB_GET_BOTH);
5718 ADD_INT(d, DB_GET_RECNO);
5719 ADD_INT(d, DB_JOIN_ITEM);
5720 ADD_INT(d, DB_KEYFIRST);
5721 ADD_INT(d, DB_KEYLAST);
5722 ADD_INT(d, DB_LAST);
5723 ADD_INT(d, DB_NEXT);
5724 ADD_INT(d, DB_NEXT_DUP);
5725 ADD_INT(d, DB_NEXT_NODUP);
5726 ADD_INT(d, DB_NODUPDATA);
5727 ADD_INT(d, DB_NOOVERWRITE);
5728 ADD_INT(d, DB_NOSYNC);
5729 ADD_INT(d, DB_POSITION);
5730 ADD_INT(d, DB_PREV);
5731 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005732#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005733 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005734#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005735 ADD_INT(d, DB_SET);
5736 ADD_INT(d, DB_SET_RANGE);
5737 ADD_INT(d, DB_SET_RECNO);
5738 ADD_INT(d, DB_WRITECURSOR);
5739
5740 ADD_INT(d, DB_OPFLAGS_MASK);
5741 ADD_INT(d, DB_RMW);
5742#if (DBVER >= 33)
5743 ADD_INT(d, DB_DIRTY_READ);
5744 ADD_INT(d, DB_MULTIPLE);
5745 ADD_INT(d, DB_MULTIPLE_KEY);
5746#endif
5747
Gregory P. Smith29602d22006-01-24 09:46:48 +00005748#if (DBVER >= 44)
5749 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5750 ADD_INT(d, DB_READ_COMMITTED);
5751#endif
5752
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005753#if (DBVER >= 33)
5754 ADD_INT(d, DB_DONOTINDEX);
5755#endif
5756
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005757#if (DBVER >= 41)
5758 _addIntToDict(d, "DB_INCOMPLETE", 0);
5759#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005760 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005761#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005762 ADD_INT(d, DB_KEYEMPTY);
5763 ADD_INT(d, DB_KEYEXIST);
5764 ADD_INT(d, DB_LOCK_DEADLOCK);
5765 ADD_INT(d, DB_LOCK_NOTGRANTED);
5766 ADD_INT(d, DB_NOSERVER);
5767 ADD_INT(d, DB_NOSERVER_HOME);
5768 ADD_INT(d, DB_NOSERVER_ID);
5769 ADD_INT(d, DB_NOTFOUND);
5770 ADD_INT(d, DB_OLD_VERSION);
5771 ADD_INT(d, DB_RUNRECOVERY);
5772 ADD_INT(d, DB_VERIFY_BAD);
5773#if (DBVER >= 33)
5774 ADD_INT(d, DB_PAGE_NOTFOUND);
5775 ADD_INT(d, DB_SECONDARY_BAD);
5776#endif
5777#if (DBVER >= 40)
5778 ADD_INT(d, DB_STAT_CLEAR);
5779 ADD_INT(d, DB_REGION_INIT);
5780 ADD_INT(d, DB_NOLOCKING);
5781 ADD_INT(d, DB_YIELDCPU);
5782 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5783 ADD_INT(d, DB_NOPANIC);
5784#endif
5785
Gregory P. Smith41631e82003-09-21 00:08:14 +00005786#if (DBVER >= 42)
5787 ADD_INT(d, DB_TIME_NOTGRANTED);
5788 ADD_INT(d, DB_TXN_NOT_DURABLE);
5789 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5790 ADD_INT(d, DB_LOG_AUTOREMOVE);
5791 ADD_INT(d, DB_DIRECT_LOG);
5792 ADD_INT(d, DB_DIRECT_DB);
5793 ADD_INT(d, DB_INIT_REP);
5794 ADD_INT(d, DB_ENCRYPT);
5795 ADD_INT(d, DB_CHKSUM);
5796#endif
5797
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005798#if (DBVER >= 43)
5799 ADD_INT(d, DB_LOG_INMEMORY);
5800 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005801 ADD_INT(d, DB_SEQ_DEC);
5802 ADD_INT(d, DB_SEQ_INC);
5803 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005804#endif
5805
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005806#if (DBVER >= 41)
5807 ADD_INT(d, DB_ENCRYPT_AES);
5808 ADD_INT(d, DB_AUTO_COMMIT);
5809#else
5810 /* allow berkeleydb 4.1 aware apps to run on older versions */
5811 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5812#endif
5813
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005814 ADD_INT(d, EINVAL);
5815 ADD_INT(d, EACCES);
5816 ADD_INT(d, ENOSPC);
5817 ADD_INT(d, ENOMEM);
5818 ADD_INT(d, EAGAIN);
5819 ADD_INT(d, EBUSY);
5820 ADD_INT(d, EEXIST);
5821 ADD_INT(d, ENOENT);
5822 ADD_INT(d, EPERM);
5823
Barry Warsaw1baa9822003-03-31 19:51:29 +00005824#if (DBVER >= 40)
5825 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5826 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005828
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005829 /* The exception name must be correct for pickled exception *
5830 * objects to unpickle properly. */
5831#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5832#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5833#else
5834#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5835#endif
5836
5837 /* All the rest of the exceptions derive only from DBError */
5838#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5839 PyDict_SetItemString(d, #name, name)
5840
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005841 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005842 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5843 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005844
Gregory P. Smithe9477062005-06-04 06:46:59 +00005845 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5846 * from both DBError and KeyError, since the API only supports
5847 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005848 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005849 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5850 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005851 Py_file_input, d, d);
5852 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005853 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005854 PyDict_DelItemString(d, "KeyError");
5855
5856
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857#if !INCOMPLETE_IS_WARNING
5858 MAKE_EX(DBIncompleteError);
5859#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005860 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005861 MAKE_EX(DBKeyEmptyError);
5862 MAKE_EX(DBKeyExistError);
5863 MAKE_EX(DBLockDeadlockError);
5864 MAKE_EX(DBLockNotGrantedError);
5865 MAKE_EX(DBOldVersionError);
5866 MAKE_EX(DBRunRecoveryError);
5867 MAKE_EX(DBVerifyBadError);
5868 MAKE_EX(DBNoServerError);
5869 MAKE_EX(DBNoServerHomeError);
5870 MAKE_EX(DBNoServerIDError);
5871#if (DBVER >= 33)
5872 MAKE_EX(DBPageNotFoundError);
5873 MAKE_EX(DBSecondaryBadError);
5874#endif
5875
5876 MAKE_EX(DBInvalidArgError);
5877 MAKE_EX(DBAccessError);
5878 MAKE_EX(DBNoSpaceError);
5879 MAKE_EX(DBNoMemoryError);
5880 MAKE_EX(DBAgainError);
5881 MAKE_EX(DBBusyError);
5882 MAKE_EX(DBFileExistsError);
5883 MAKE_EX(DBNoSuchFileError);
5884 MAKE_EX(DBPermissionsError);
5885
5886#undef MAKE_EX
5887
Gregory P. Smith39250532007-10-09 06:02:21 +00005888 /* Initiliase the C API structure and add it to the module */
5889 bsddb_api.db_type = &DB_Type;
5890 bsddb_api.dbcursor_type = &DBCursor_Type;
5891 bsddb_api.dbenv_type = &DBEnv_Type;
5892 bsddb_api.dbtxn_type = &DBTxn_Type;
5893 bsddb_api.dblock_type = &DBLock_Type;
5894 bsddb_api.dbsequence_type = &DBSequence_Type;
5895 bsddb_api.makeDBError = makeDBError;
5896
5897 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5898 PyDict_SetItemString(d, "api", py_api);
5899 Py_DECREF(py_api);
5900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005901 /* Check for errors */
5902 if (PyErr_Occurred()) {
5903 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005904 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005905 }
5906}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005907
5908/* allow this module to be named _pybsddb so that it can be installed
5909 * and imported on top of python >= 2.3 that includes its own older
5910 * copy of the library named _bsddb without importing the old version. */
5911DL_EXPORT(void) init_pybsddb(void)
5912{
5913 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5914 init_bsddb();
5915}