blob: 7d05b24ed1d32268cbc59c010cf3830e73e37de2 [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
Gregory P. Smithfc006692007-11-05 09:06:28 +0000206#ifndef Py_Type
207/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000208#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000209#endif
210
Christian Heimese93237d2007-12-19 02:37:44 +0000211#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
212#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
213#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
214#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
215#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000216#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000217#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000218#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000219
220
221/* --------------------------------------------------------------------- */
222/* Utility macros and functions */
223
224#define RETURN_IF_ERR() \
225 if (makeDBError(err)) { \
226 return NULL; \
227 }
228
229#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
230
Gregory P. Smithe2767172003-11-02 08:06:29 +0000231#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
232 if ((nonNull) == NULL) { \
233 PyObject *errTuple = NULL; \
234 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
235 PyErr_SetObject((pyErrObj), errTuple); \
236 Py_DECREF(errTuple); \
237 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000238 }
239
Gregory P. Smithe2767172003-11-02 08:06:29 +0000240#define CHECK_DB_NOT_CLOSED(dbobj) \
241 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
242
243#define CHECK_ENV_NOT_CLOSED(env) \
244 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245
246#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000247 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000249#if (DBVER >= 43)
250#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
251 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
252#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253
254#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
255 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
256
257#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
258
259#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000260 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000261
262
263static int makeDBError(int err);
264
265
266/* Return the access method type of the DBObject */
267static int _DB_get_type(DBObject* self)
268{
269#if (DBVER >= 33)
270 DBTYPE type;
271 int err;
272 err = self->db->get_type(self->db, &type);
273 if (makeDBError(err)) {
274 return -1;
275 }
276 return type;
277#else
278 return self->db->get_type(self->db);
279#endif
280}
281
282
283/* Create a DBT structure (containing key and data values) from Python
284 strings. Returns 1 on success, 0 on an error. */
285static int make_dbt(PyObject* obj, DBT* dbt)
286{
287 CLEAR_DBT(*dbt);
288 if (obj == Py_None) {
289 /* no need to do anything, the structure has already been zeroed */
290 }
291 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
292 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000293 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000294 return 0;
295 }
296 return 1;
297}
298
299
300/* Recno and Queue DBs can have integer keys. This function figures out
301 what's been given, verifies that it's allowed, and then makes the DBT.
302
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000303 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000304static int
305make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000306{
307 db_recno_t recno;
308 int type;
309
310 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000311 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000312 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000313 if (type == -1)
314 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000315 if (type == DB_RECNO || type == DB_QUEUE) {
316 PyErr_SetString(
317 PyExc_TypeError,
318 "None keys not allowed for Recno and Queue DB's");
319 return 0;
320 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000321 /* no need to do anything, the structure has already been zeroed */
322 }
323
324 else if (PyString_Check(keyobj)) {
325 /* verify access method type */
326 type = _DB_get_type(self);
327 if (type == -1)
328 return 0;
329 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000330 PyErr_SetString(
331 PyExc_TypeError,
332 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000333 return 0;
334 }
335
Gregory P. Smith10bed542007-10-09 06:50:43 +0000336 /*
337 * NOTE(gps): I don't like doing a data copy here, it seems
338 * wasteful. But without a clean way to tell FREE_DBT if it
339 * should free key->data or not we have to. Other places in
340 * the code check for DB_THREAD and forceably set DBT_MALLOC
341 * when we otherwise would leave flags 0 to indicate that.
342 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000343 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000344 if (key->data == NULL) {
345 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
346 return 0;
347 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000348 memcpy(key->data, PyString_AS_STRING(keyobj),
349 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000350 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 key->size = PyString_GET_SIZE(keyobj);
352 }
353
354 else if (PyInt_Check(keyobj)) {
355 /* verify access method type */
356 type = _DB_get_type(self);
357 if (type == -1)
358 return 0;
359 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000360 /* if BTREE then an Integer key is allowed with the
361 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362 *pflags |= DB_SET_RECNO;
363 }
364 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000365 PyErr_SetString(
366 PyExc_TypeError,
367 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000368 return 0;
369 }
370
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000371 /* Make a key out of the requested recno, use allocated space so DB
372 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000373 recno = PyInt_AS_LONG(keyobj);
374 key->data = malloc(sizeof(db_recno_t));
375 if (key->data == NULL) {
376 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
377 return 0;
378 }
379 key->ulen = key->size = sizeof(db_recno_t);
380 memcpy(key->data, &recno, sizeof(db_recno_t));
381 key->flags = DB_DBT_REALLOC;
382 }
383 else {
384 PyErr_Format(PyExc_TypeError,
385 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000386 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000387 return 0;
388 }
389
390 return 1;
391}
392
393
394/* Add partial record access to an existing DBT data struct.
395 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
396 and the data storage/retrieval will be done using dlen and doff. */
397static int add_partial_dbt(DBT* d, int dlen, int doff) {
398 /* if neither were set we do nothing (-1 is the default value) */
399 if ((dlen == -1) && (doff == -1)) {
400 return 1;
401 }
402
403 if ((dlen < 0) || (doff < 0)) {
404 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
405 return 0;
406 }
407
408 d->flags = d->flags | DB_DBT_PARTIAL;
409 d->dlen = (unsigned int) dlen;
410 d->doff = (unsigned int) doff;
411 return 1;
412}
413
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000414/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
415/* TODO: make this use the native libc strlcpy() when available (BSD) */
416unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
417{
418 unsigned int srclen, copylen;
419
420 srclen = strlen(src);
421 if (n <= 0)
422 return srclen;
423 copylen = (srclen > n-1) ? n-1 : srclen;
424 /* populate dest[0] thru dest[copylen-1] */
425 memcpy(dest, src, copylen);
426 /* guarantee null termination */
427 dest[copylen] = 0;
428
429 return srclen;
430}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000432/* Callback used to save away more information about errors from the DB
433 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000434static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000435#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000436static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000437#else
438static void _db_errorCallback(const DB_ENV *db_env,
439 const char* prefix, const char* msg)
440#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000441{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000442 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000443}
444
445
446/* make a nice exception object to raise for errors. */
447static int makeDBError(int err)
448{
449 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000450 PyObject *errObj = NULL;
451 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000452 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000453 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454
455 switch (err) {
456 case 0: /* successful, no error */ break;
457
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000458#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000459 case DB_INCOMPLETE:
460#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000461 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
462 /* Ensure that bytes_left never goes negative */
463 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
464 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
465 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000466 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000467 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000468 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000469 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000470 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000471
472#else /* do an exception instead */
473 errObj = DBIncompleteError;
474#endif
475 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000476#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000477
478 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
479 case DB_KEYEXIST: errObj = DBKeyExistError; break;
480 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
481 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
482 case DB_NOTFOUND: errObj = DBNotFoundError; break;
483 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
484 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
485 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
486 case DB_NOSERVER: errObj = DBNoServerError; break;
487 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
488 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
489#if (DBVER >= 33)
490 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
491 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
492#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000493 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000494
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000495#if (DBVER >= 43)
496 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
497 case ENOMEM: errObj = PyExc_MemoryError; break;
498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000499 case EINVAL: errObj = DBInvalidArgError; break;
500 case EACCES: errObj = DBAccessError; break;
501 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000502 case EAGAIN: errObj = DBAgainError; break;
503 case EBUSY : errObj = DBBusyError; break;
504 case EEXIST: errObj = DBFileExistsError; break;
505 case ENOENT: errObj = DBNoSuchFileError; break;
506 case EPERM : errObj = DBPermissionsError; break;
507
508 default: errObj = DBError; break;
509 }
510
511 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000512 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
513 /* Ensure that bytes_left never goes negative */
514 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
515 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
516 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000517 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000518 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000520 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000521
522 errTuple = Py_BuildValue("(is)", err, errTxt);
523 PyErr_SetObject(errObj, errTuple);
524 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000525 }
526
527 return ((errObj != NULL) || exceptionRaised);
528}
529
530
531
532/* set a type exception */
533static void makeTypeError(char* expected, PyObject* found)
534{
535 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000536 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537}
538
539
540/* verify that an obj is either None or a DBTxn, and set the txn pointer */
541static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
542{
543 if (txnobj == Py_None || txnobj == NULL) {
544 *txn = NULL;
545 return 1;
546 }
547 if (DBTxnObject_Check(txnobj)) {
548 *txn = ((DBTxnObject*)txnobj)->txn;
549 return 1;
550 }
551 else
552 makeTypeError("DBTxn", txnobj);
553 return 0;
554}
555
556
557/* Delete a key from a database
558 Returns 0 on success, -1 on an error. */
559static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
560{
561 int err;
562
563 MYDB_BEGIN_ALLOW_THREADS;
564 err = self->db->del(self->db, txn, key, 0);
565 MYDB_END_ALLOW_THREADS;
566 if (makeDBError(err)) {
567 return -1;
568 }
569 self->haveStat = 0;
570 return 0;
571}
572
573
574/* Store a key into a database
575 Returns 0 on success, -1 on an error. */
576static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
577{
578 int err;
579
580 MYDB_BEGIN_ALLOW_THREADS;
581 err = self->db->put(self->db, txn, key, data, flags);
582 MYDB_END_ALLOW_THREADS;
583 if (makeDBError(err)) {
584 return -1;
585 }
586 self->haveStat = 0;
587 return 0;
588}
589
590/* Get a key/data pair from a cursor */
591static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
592 PyObject *args, PyObject *kwargs, char *format)
593{
594 int err;
595 PyObject* retval = NULL;
596 DBT key, data;
597 int dlen = -1;
598 int doff = -1;
599 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000600 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000601
602 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
603 &flags, &dlen, &doff))
604 return NULL;
605
606 CHECK_CURSOR_NOT_CLOSED(self);
607
608 flags |= extra_flags;
609 CLEAR_DBT(key);
610 CLEAR_DBT(data);
611 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
612 /* Tell BerkeleyDB to malloc the return value (thread safe) */
613 data.flags = DB_DBT_MALLOC;
614 key.flags = DB_DBT_MALLOC;
615 }
616 if (!add_partial_dbt(&data, dlen, doff))
617 return NULL;
618
619 MYDB_BEGIN_ALLOW_THREADS;
620 err = self->dbc->c_get(self->dbc, &key, &data, flags);
621 MYDB_END_ALLOW_THREADS;
622
Gregory P. Smithe9477062005-06-04 06:46:59 +0000623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
624 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000625 Py_INCREF(Py_None);
626 retval = Py_None;
627 }
628 else if (makeDBError(err)) {
629 retval = NULL;
630 }
631 else { /* otherwise, success! */
632
633 /* if Recno or Queue, return the key as an Int */
634 switch (_DB_get_type(self->mydb)) {
635 case -1:
636 retval = NULL;
637 break;
638
639 case DB_RECNO:
640 case DB_QUEUE:
641 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
642 data.data, data.size);
643 break;
644 case DB_HASH:
645 case DB_BTREE:
646 default:
647 retval = Py_BuildValue("s#s#", key.data, key.size,
648 data.data, data.size);
649 break;
650 }
651 }
652 if (!err) {
653 FREE_DBT(key);
654 FREE_DBT(data);
655 }
656 return retval;
657}
658
659
660/* add an integer to a dictionary using the given name as a key */
661static void _addIntToDict(PyObject* dict, char *name, int value)
662{
663 PyObject* v = PyInt_FromLong((long) value);
664 if (!v || PyDict_SetItemString(dict, name, v))
665 PyErr_Clear();
666
667 Py_XDECREF(v);
668}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000669
670/* The same, when the value is a time_t */
671static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
672{
673 PyObject* v;
674 /* if the value fits in regular int, use that. */
675#ifdef HAVE_LONG_LONG
676 if (sizeof(time_t) > sizeof(long))
677 v = PyLong_FromLongLong((PY_LONG_LONG) value);
678 else
679#endif
680 v = PyInt_FromLong((long) value);
681 if (!v || PyDict_SetItemString(dict, name, v))
682 PyErr_Clear();
683
684 Py_XDECREF(v);
685}
686
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000687#if (DBVER >= 43)
688/* add an db_seq_t to a dictionary using the given name as a key */
689static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
690{
691 PyObject* v = PyLong_FromLongLong(value);
692 if (!v || PyDict_SetItemString(dict, name, v))
693 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000694
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000695 Py_XDECREF(v);
696}
697#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000698
699
700
701/* --------------------------------------------------------------------- */
702/* Allocators and deallocators */
703
704static DBObject*
705newDBObject(DBEnvObject* arg, int flags)
706{
707 DBObject* self;
708 DB_ENV* db_env = NULL;
709 int err;
710
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000712 if (self == NULL)
713 return NULL;
714
715 self->haveStat = 0;
716 self->flags = 0;
717 self->setflags = 0;
718 self->myenvobj = NULL;
719#if (DBVER >= 33)
720 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000721 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000722 self->primaryDBType = 0;
723#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000724 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000725
726 /* keep a reference to our python DBEnv object */
727 if (arg) {
728 Py_INCREF(arg);
729 self->myenvobj = arg;
730 db_env = arg->db_env;
731 }
732
733 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000734 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000736 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
737 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000738
739 MYDB_BEGIN_ALLOW_THREADS;
740 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000741 if (self->db != NULL) {
742 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000743#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000744 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000745#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000746 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000747 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000748 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
749 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000750 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000751 if (makeDBError(err)) {
752 if (self->myenvobj) {
753 Py_DECREF(self->myenvobj);
754 self->myenvobj = NULL;
755 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000756 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757 self = NULL;
758 }
759 return self;
760}
761
762
763static void
764DB_dealloc(DBObject* self)
765{
766 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000767 /* avoid closing a DB when its DBEnv has been closed out from under
768 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000770 (self->myenvobj && self->myenvobj->db_env))
771 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000772 MYDB_BEGIN_ALLOW_THREADS;
773 self->db->close(self->db, 0);
774 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000775 } else {
776 PyErr_Warn(PyExc_RuntimeWarning,
777 "DB could not be closed in destructor: DBEnv already closed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000778 }
779 self->db = NULL;
780 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000781 if (self->in_weakreflist != NULL) {
782 PyObject_ClearWeakRefs((PyObject *) self);
783 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000784 if (self->myenvobj) {
785 Py_DECREF(self->myenvobj);
786 self->myenvobj = NULL;
787 }
788#if (DBVER >= 33)
789 if (self->associateCallback != NULL) {
790 Py_DECREF(self->associateCallback);
791 self->associateCallback = NULL;
792 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000793 if (self->btCompareCallback != NULL) {
794 Py_DECREF(self->btCompareCallback);
795 self->btCompareCallback = NULL;
796 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000798 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799}
800
801
802static DBCursorObject*
803newDBCursorObject(DBC* dbc, DBObject* db)
804{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000805 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806 if (self == NULL)
807 return NULL;
808
809 self->dbc = dbc;
810 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000811 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812 Py_INCREF(self->mydb);
813 return self;
814}
815
816
817static void
818DBCursor_dealloc(DBCursorObject* self)
819{
820 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000821
Gregory P. Smitha703a212003-11-03 01:04:41 +0000822 if (self->in_weakreflist != NULL) {
823 PyObject_ClearWeakRefs((PyObject *) self);
824 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000825
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000827 /* If the underlying database has been closed, we don't
828 need to do anything. If the environment has been closed
829 we need to leak, as BerkeleyDB will crash trying to access
830 the environment. There was an exception when the
831 user closed the environment even though there still was
832 a database open. */
833 if (self->mydb->db && self->mydb->myenvobj &&
834 !self->mydb->myenvobj->closed)
Gregory P. Smitheeed5b72008-02-03 07:20:53 +0000835 /* test for: open db + no environment or non-closed environment */
836 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
837 !self->mydb->myenvobj->closed))) {
838 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000839 err = self->dbc->c_close(self->dbc);
Gregory P. Smitheeed5b72008-02-03 07:20:53 +0000840 MYDB_END_ALLOW_THREADS;
841 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 }
844 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000845 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846}
847
848
849static DBEnvObject*
850newDBEnvObject(int flags)
851{
852 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000853 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000854 if (self == NULL)
855 return NULL;
856
857 self->closed = 1;
858 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000859 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
860 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000861 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862
863 MYDB_BEGIN_ALLOW_THREADS;
864 err = db_env_create(&self->db_env, flags);
865 MYDB_END_ALLOW_THREADS;
866 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000867 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868 self = NULL;
869 }
870 else {
871 self->db_env->set_errcall(self->db_env, _db_errorCallback);
872 }
873 return self;
874}
875
876
877static void
878DBEnv_dealloc(DBEnvObject* self)
879{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000880 if (self->in_weakreflist != NULL) {
881 PyObject_ClearWeakRefs((PyObject *) self);
882 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000883
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000884 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 MYDB_BEGIN_ALLOW_THREADS;
886 self->db_env->close(self->db_env, 0);
887 MYDB_END_ALLOW_THREADS;
888 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000890}
891
892
893static DBTxnObject*
894newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
895{
896 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000897 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000898 if (self == NULL)
899 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000900 Py_INCREF(myenv);
901 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000902 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903
904 MYDB_BEGIN_ALLOW_THREADS;
905#if (DBVER >= 40)
906 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
907#else
908 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
909#endif
910 MYDB_END_ALLOW_THREADS;
911 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000912 Py_DECREF(self->env);
913 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000914 self = NULL;
915 }
916 return self;
917}
918
919
920static void
921DBTxn_dealloc(DBTxnObject* self)
922{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000923 if (self->in_weakreflist != NULL) {
924 PyObject_ClearWeakRefs((PyObject *) self);
925 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000926
Gregory P. Smith31c50652004-06-28 01:20:40 +0000927 if (self->txn) {
928 /* it hasn't been finalized, abort it! */
929 MYDB_BEGIN_ALLOW_THREADS;
930#if (DBVER >= 40)
931 self->txn->abort(self->txn);
932#else
933 txn_abort(self->txn);
934#endif
935 MYDB_END_ALLOW_THREADS;
936 PyErr_Warn(PyExc_RuntimeWarning,
937 "DBTxn aborted in destructor. No prior commit() or abort().");
938 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939
Neal Norwitz62a21122006-01-25 05:21:55 +0000940 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942}
943
944
945static DBLockObject*
946newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
947 db_lockmode_t lock_mode, int flags)
948{
949 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000950 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 if (self == NULL)
952 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954
955 MYDB_BEGIN_ALLOW_THREADS;
956#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000957 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
958 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000959#else
960 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
961#endif
962 MYDB_END_ALLOW_THREADS;
963 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000964 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 self = NULL;
966 }
967
968 return self;
969}
970
971
972static void
973DBLock_dealloc(DBLockObject* self)
974{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000975 if (self->in_weakreflist != NULL) {
976 PyObject_ClearWeakRefs((PyObject *) self);
977 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000978 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000981}
982
983
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000984#if (DBVER >= 43)
985static DBSequenceObject*
986newDBSequenceObject(DBObject* mydb, int flags)
987{
988 int err;
989 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
990 if (self == NULL)
991 return NULL;
992 Py_INCREF(mydb);
993 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000994 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000995
996
997 MYDB_BEGIN_ALLOW_THREADS;
998 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
999 MYDB_END_ALLOW_THREADS;
1000 if (makeDBError(err)) {
1001 Py_DECREF(self->mydb);
1002 PyObject_Del(self);
1003 self = NULL;
1004 }
1005
1006 return self;
1007}
1008
1009
1010static void
1011DBSequence_dealloc(DBSequenceObject* self)
1012{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001013 if (self->in_weakreflist != NULL) {
1014 PyObject_ClearWeakRefs((PyObject *) self);
1015 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001016
1017 Py_DECREF(self->mydb);
1018 PyObject_Del(self);
1019}
1020#endif
1021
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022/* --------------------------------------------------------------------- */
1023/* DB methods */
1024
1025static PyObject*
1026DB_append(DBObject* self, PyObject* args)
1027{
1028 PyObject* txnobj = NULL;
1029 PyObject* dataobj;
1030 db_recno_t recno;
1031 DBT key, data;
1032 DB_TXN *txn = NULL;
1033
Georg Brandl96a8c392006-05-29 21:04:52 +00001034 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001035 return NULL;
1036
1037 CHECK_DB_NOT_CLOSED(self);
1038
1039 /* make a dummy key out of a recno */
1040 recno = 0;
1041 CLEAR_DBT(key);
1042 key.data = &recno;
1043 key.size = sizeof(recno);
1044 key.ulen = key.size;
1045 key.flags = DB_DBT_USERMEM;
1046
1047 if (!make_dbt(dataobj, &data)) return NULL;
1048 if (!checkTxnObj(txnobj, &txn)) return NULL;
1049
1050 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1051 return NULL;
1052
1053 return PyInt_FromLong(recno);
1054}
1055
1056
1057#if (DBVER >= 33)
1058
1059static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001060_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1061 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062{
1063 int retval = DB_DONOTINDEX;
1064 DBObject* secondaryDB = (DBObject*)db->app_private;
1065 PyObject* callback = secondaryDB->associateCallback;
1066 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001068 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001069
1070
1071 if (callback != NULL) {
1072 MYDB_BEGIN_BLOCK_THREADS;
1073
Thomas Woutersb3153832006-03-08 01:47:19 +00001074 if (type == DB_RECNO || type == DB_QUEUE)
1075 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1076 priData->data, priData->size);
1077 else
1078 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1079 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001080 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001081 result = PyEval_CallObject(callback, args);
1082 }
1083 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001084 PyErr_Print();
1085 }
1086 else if (result == Py_None) {
1087 retval = DB_DONOTINDEX;
1088 }
1089 else if (PyInt_Check(result)) {
1090 retval = PyInt_AsLong(result);
1091 }
1092 else if (PyString_Check(result)) {
1093 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001094 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001095
1096 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001097 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001098 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1099 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001100 if (secKey->data) {
1101 memcpy(secKey->data, data, size);
1102 secKey->size = size;
1103 retval = 0;
1104 }
1105 else {
1106 PyErr_SetString(PyExc_MemoryError,
1107 "malloc failed in _db_associateCallback");
1108 PyErr_Print();
1109 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001110 }
1111 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001112 PyErr_SetString(
1113 PyExc_TypeError,
1114 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001115 PyErr_Print();
1116 }
1117
Thomas Woutersb3153832006-03-08 01:47:19 +00001118 Py_XDECREF(args);
1119 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001120
1121 MYDB_END_BLOCK_THREADS;
1122 }
1123 return retval;
1124}
1125
1126
1127static PyObject*
1128DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1129{
1130 int err, flags=0;
1131 DBObject* secondaryDB;
1132 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001133#if (DBVER >= 41)
1134 PyObject *txnobj = NULL;
1135 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001136 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001137 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001138#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001139 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001140#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001141
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001142#if (DBVER >= 41)
1143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1144 &secondaryDB, &callback, &flags,
1145 &txnobj)) {
1146#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001148 &secondaryDB, &callback, &flags)) {
1149#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001150 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001151 }
1152
1153#if (DBVER >= 41)
1154 if (!checkTxnObj(txnobj, &txn)) return NULL;
1155#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001156
1157 CHECK_DB_NOT_CLOSED(self);
1158 if (!DBObject_Check(secondaryDB)) {
1159 makeTypeError("DB", (PyObject*)secondaryDB);
1160 return NULL;
1161 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001162 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163 if (callback == Py_None) {
1164 callback = NULL;
1165 }
1166 else if (!PyCallable_Check(callback)) {
1167 makeTypeError("Callable", callback);
1168 return NULL;
1169 }
1170
1171 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001172 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001173 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174 secondaryDB->associateCallback = callback;
1175 secondaryDB->primaryDBType = _DB_get_type(self);
1176
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001177 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1178 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1179 * The global interepreter lock is not initialized until the first
1180 * thread is created using thread.start_new_thread() or fork() is
1181 * called. that would cause the ALLOW_THREADS here to segfault due
1182 * to a null pointer reference if no threads or child processes
1183 * have been created. This works around that and is a no-op if
1184 * threads have already been initialized.
1185 * (see pybsddb-users mailing list post on 2002-08-07)
1186 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001187#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001188 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001189#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001190 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001191#if (DBVER >= 41)
1192 err = self->db->associate(self->db,
1193 txn,
1194 secondaryDB->db,
1195 _db_associateCallback,
1196 flags);
1197#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198 err = self->db->associate(self->db,
1199 secondaryDB->db,
1200 _db_associateCallback,
1201 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001202#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203 MYDB_END_ALLOW_THREADS;
1204
1205 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001206 Py_XDECREF(secondaryDB->associateCallback);
1207 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001208 secondaryDB->primaryDBType = 0;
1209 }
1210
1211 RETURN_IF_ERR();
1212 RETURN_NONE();
1213}
1214
1215
1216#endif
1217
1218
1219static PyObject*
1220DB_close(DBObject* self, PyObject* args)
1221{
1222 int err, flags=0;
1223 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1224 return NULL;
1225 if (self->db != NULL) {
1226 if (self->myenvobj)
1227 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001229 self->db = NULL;
1230 RETURN_IF_ERR();
1231 }
1232 RETURN_NONE();
1233}
1234
1235
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236static PyObject*
1237_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1238{
1239 int err, flags=0, type;
1240 PyObject* txnobj = NULL;
1241 PyObject* retval = NULL;
1242 DBT key, data;
1243 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001244 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245
1246 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1247 &txnobj, &flags))
1248 return NULL;
1249
1250 CHECK_DB_NOT_CLOSED(self);
1251 type = _DB_get_type(self);
1252 if (type == -1)
1253 return NULL;
1254 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001255 PyErr_SetString(PyExc_TypeError,
1256 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001257 return NULL;
1258 }
1259 if (!checkTxnObj(txnobj, &txn))
1260 return NULL;
1261
1262 CLEAR_DBT(key);
1263 CLEAR_DBT(data);
1264 if (CHECK_DBFLAG(self, DB_THREAD)) {
1265 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1266 data.flags = DB_DBT_MALLOC;
1267 key.flags = DB_DBT_MALLOC;
1268 }
1269
1270 MYDB_BEGIN_ALLOW_THREADS;
1271 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1272 MYDB_END_ALLOW_THREADS;
1273
Gregory P. Smithe9477062005-06-04 06:46:59 +00001274 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1275 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 err = 0;
1277 Py_INCREF(Py_None);
1278 retval = Py_None;
1279 }
1280 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001281 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1282 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001283 FREE_DBT(key);
1284 FREE_DBT(data);
1285 }
1286
1287 RETURN_IF_ERR();
1288 return retval;
1289}
1290
1291static PyObject*
1292DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1293{
1294 return _DB_consume(self, args, kwargs, DB_CONSUME);
1295}
1296
1297static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001298DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1299 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300{
1301 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1302}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303
1304
1305static PyObject*
1306DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1307{
1308 int err, flags=0;
1309 DBC* dbc;
1310 PyObject* txnobj = NULL;
1311 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001312 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001313
1314 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1315 &txnobj, &flags))
1316 return NULL;
1317 CHECK_DB_NOT_CLOSED(self);
1318 if (!checkTxnObj(txnobj, &txn))
1319 return NULL;
1320
1321 MYDB_BEGIN_ALLOW_THREADS;
1322 err = self->db->cursor(self->db, txn, &dbc, flags);
1323 MYDB_END_ALLOW_THREADS;
1324 RETURN_IF_ERR();
1325 return (PyObject*) newDBCursorObject(dbc, self);
1326}
1327
1328
1329static PyObject*
1330DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1331{
1332 PyObject* txnobj = NULL;
1333 int flags = 0;
1334 PyObject* keyobj;
1335 DBT key;
1336 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001337 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338
1339 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1340 &keyobj, &txnobj, &flags))
1341 return NULL;
1342 CHECK_DB_NOT_CLOSED(self);
1343 if (!make_key_dbt(self, keyobj, &key, NULL))
1344 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001345 if (!checkTxnObj(txnobj, &txn)) {
1346 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001347 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001348 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001349
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001350 if (-1 == _DB_delete(self, txn, &key, 0)) {
1351 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001352 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001353 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001354
1355 FREE_DBT(key);
1356 RETURN_NONE();
1357}
1358
1359
1360static PyObject*
1361DB_fd(DBObject* self, PyObject* args)
1362{
1363 int err, the_fd;
1364
1365 if (!PyArg_ParseTuple(args,":fd"))
1366 return NULL;
1367 CHECK_DB_NOT_CLOSED(self);
1368
1369 MYDB_BEGIN_ALLOW_THREADS;
1370 err = self->db->fd(self->db, &the_fd);
1371 MYDB_END_ALLOW_THREADS;
1372 RETURN_IF_ERR();
1373 return PyInt_FromLong(the_fd);
1374}
1375
1376
1377static PyObject*
1378DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1379{
1380 int err, flags=0;
1381 PyObject* txnobj = NULL;
1382 PyObject* keyobj;
1383 PyObject* dfltobj = NULL;
1384 PyObject* retval = NULL;
1385 int dlen = -1;
1386 int doff = -1;
1387 DBT key, data;
1388 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001389 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001390 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391
1392 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001393 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1394 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001395 return NULL;
1396
1397 CHECK_DB_NOT_CLOSED(self);
1398 if (!make_key_dbt(self, keyobj, &key, &flags))
1399 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001400 if (!checkTxnObj(txnobj, &txn)) {
1401 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001403 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001404
1405 CLEAR_DBT(data);
1406 if (CHECK_DBFLAG(self, DB_THREAD)) {
1407 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1408 data.flags = DB_DBT_MALLOC;
1409 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001410 if (!add_partial_dbt(&data, dlen, doff)) {
1411 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001413 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414
1415 MYDB_BEGIN_ALLOW_THREADS;
1416 err = self->db->get(self->db, txn, &key, &data, flags);
1417 MYDB_END_ALLOW_THREADS;
1418
Gregory P. Smithe9477062005-06-04 06:46:59 +00001419 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001420 err = 0;
1421 Py_INCREF(dfltobj);
1422 retval = dfltobj;
1423 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001424 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1425 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001426 err = 0;
1427 Py_INCREF(Py_None);
1428 retval = Py_None;
1429 }
1430 else if (!err) {
1431 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001432 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1433 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434 else /* return just the data */
1435 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 FREE_DBT(data);
1437 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001438 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439
1440 RETURN_IF_ERR();
1441 return retval;
1442}
1443
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001444#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001445static PyObject*
1446DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1447{
1448 int err, flags=0;
1449 PyObject* txnobj = NULL;
1450 PyObject* keyobj;
1451 PyObject* dfltobj = NULL;
1452 PyObject* retval = NULL;
1453 int dlen = -1;
1454 int doff = -1;
1455 DBT key, pkey, data;
1456 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001457 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001458 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001459
1460 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1461 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1462 &doff))
1463 return NULL;
1464
1465 CHECK_DB_NOT_CLOSED(self);
1466 if (!make_key_dbt(self, keyobj, &key, &flags))
1467 return NULL;
1468 if (!checkTxnObj(txnobj, &txn)) {
1469 FREE_DBT(key);
1470 return NULL;
1471 }
1472
1473 CLEAR_DBT(data);
1474 if (CHECK_DBFLAG(self, DB_THREAD)) {
1475 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1476 data.flags = DB_DBT_MALLOC;
1477 }
1478 if (!add_partial_dbt(&data, dlen, doff)) {
1479 FREE_DBT(key);
1480 return NULL;
1481 }
1482
1483 CLEAR_DBT(pkey);
1484 pkey.flags = DB_DBT_MALLOC;
1485
1486 MYDB_BEGIN_ALLOW_THREADS;
1487 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1488 MYDB_END_ALLOW_THREADS;
1489
Gregory P. Smithe9477062005-06-04 06:46:59 +00001490 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001491 err = 0;
1492 Py_INCREF(dfltobj);
1493 retval = dfltobj;
1494 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001495 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1496 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001497 err = 0;
1498 Py_INCREF(Py_None);
1499 retval = Py_None;
1500 }
1501 else if (!err) {
1502 PyObject *pkeyObj;
1503 PyObject *dataObj;
1504 dataObj = PyString_FromStringAndSize(data.data, data.size);
1505
1506 if (self->primaryDBType == DB_RECNO ||
1507 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001508 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001509 else
1510 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1511
1512 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1513 {
1514 PyObject *keyObj;
1515 int type = _DB_get_type(self);
1516 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001517 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001518 else
1519 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001520#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001521 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001522#else
1523 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1524#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001525 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001526 }
1527 else /* return just the pkey and data */
1528 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001529#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001530 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001531#else
1532 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1533#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001534 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001535 Py_DECREF(dataObj);
1536 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001537 FREE_DBT(pkey);
1538 FREE_DBT(data);
1539 }
1540 FREE_DBT(key);
1541
1542 RETURN_IF_ERR();
1543 return retval;
1544}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001545#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001546
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001547
1548/* Return size of entry */
1549static PyObject*
1550DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1551{
1552 int err, flags=0;
1553 PyObject* txnobj = NULL;
1554 PyObject* keyobj;
1555 PyObject* retval = NULL;
1556 DBT key, data;
1557 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001558 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001559
1560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1561 &keyobj, &txnobj))
1562 return NULL;
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001568 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001569 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001570 CLEAR_DBT(data);
1571
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001572 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1573 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001574 data.flags = DB_DBT_USERMEM;
1575 data.ulen = 0;
1576 MYDB_BEGIN_ALLOW_THREADS;
1577 err = self->db->get(self->db, txn, &key, &data, flags);
1578 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001579 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001580 retval = PyInt_FromLong((long)data.size);
1581 err = 0;
1582 }
1583
1584 FREE_DBT(key);
1585 FREE_DBT(data);
1586 RETURN_IF_ERR();
1587 return retval;
1588}
1589
1590
1591static PyObject*
1592DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1593{
1594 int err, flags=0;
1595 PyObject* txnobj = NULL;
1596 PyObject* keyobj;
1597 PyObject* dataobj;
1598 PyObject* retval = NULL;
1599 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001600 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001601 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001602 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001603
1604
1605 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1606 &keyobj, &dataobj, &txnobj, &flags))
1607 return NULL;
1608
1609 CHECK_DB_NOT_CLOSED(self);
1610 if (!make_key_dbt(self, keyobj, &key, NULL))
1611 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001612 if ( !make_dbt(dataobj, &data) ||
1613 !checkTxnObj(txnobj, &txn) )
1614 {
1615 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001616 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001617 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001618
1619 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001620 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001621
1622 if (CHECK_DBFLAG(self, DB_THREAD)) {
1623 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001624 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001625 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001626 }
1627
1628 MYDB_BEGIN_ALLOW_THREADS;
1629 err = self->db->get(self->db, txn, &key, &data, flags);
1630 MYDB_END_ALLOW_THREADS;
1631
Gregory P. Smithe9477062005-06-04 06:46:59 +00001632 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1633 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634 err = 0;
1635 Py_INCREF(Py_None);
1636 retval = Py_None;
1637 }
1638 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001639 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001641
1642 /* Even though the flags require DB_DBT_MALLOC, data is not always
1643 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1644 if (data.data != orig_data)
1645 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001646 }
1647
1648 FREE_DBT(key);
1649 RETURN_IF_ERR();
1650 return retval;
1651}
1652
1653
1654static PyObject*
1655DB_get_byteswapped(DBObject* self, PyObject* args)
1656{
1657#if (DBVER >= 33)
1658 int err = 0;
1659#endif
1660 int retval = -1;
1661
1662 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1663 return NULL;
1664 CHECK_DB_NOT_CLOSED(self);
1665
1666#if (DBVER >= 33)
1667 MYDB_BEGIN_ALLOW_THREADS;
1668 err = self->db->get_byteswapped(self->db, &retval);
1669 MYDB_END_ALLOW_THREADS;
1670 RETURN_IF_ERR();
1671#else
1672 MYDB_BEGIN_ALLOW_THREADS;
1673 retval = self->db->get_byteswapped(self->db);
1674 MYDB_END_ALLOW_THREADS;
1675#endif
1676 return PyInt_FromLong(retval);
1677}
1678
1679
1680static PyObject*
1681DB_get_type(DBObject* self, PyObject* args)
1682{
1683 int type;
1684
1685 if (!PyArg_ParseTuple(args,":get_type"))
1686 return NULL;
1687 CHECK_DB_NOT_CLOSED(self);
1688
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001689 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 if (type == -1)
1691 return NULL;
1692 return PyInt_FromLong(type);
1693}
1694
1695
1696static PyObject*
1697DB_join(DBObject* self, PyObject* args)
1698{
1699 int err, flags=0;
1700 int length, x;
1701 PyObject* cursorsObj;
1702 DBC** cursors;
1703 DBC* dbc;
1704
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001705 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1706 return NULL;
1707
1708 CHECK_DB_NOT_CLOSED(self);
1709
1710 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001711 PyErr_SetString(PyExc_TypeError,
1712 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713 return NULL;
1714 }
1715
1716 length = PyObject_Length(cursorsObj);
1717 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001718 if (!cursors) {
1719 PyErr_NoMemory();
1720 return NULL;
1721 }
1722
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 cursors[length] = NULL;
1724 for (x=0; x<length; x++) {
1725 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001726 if (item == NULL) {
1727 free(cursors);
1728 return NULL;
1729 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001730 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001731 PyErr_SetString(PyExc_TypeError,
1732 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001733 free(cursors);
1734 return NULL;
1735 }
1736 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001737 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001738 }
1739
1740 MYDB_BEGIN_ALLOW_THREADS;
1741 err = self->db->join(self->db, cursors, &dbc, flags);
1742 MYDB_END_ALLOW_THREADS;
1743 free(cursors);
1744 RETURN_IF_ERR();
1745
Gregory P. Smith7441e652003-11-03 21:35:31 +00001746 /* FIXME: this is a buggy interface. The returned cursor
1747 contains internal references to the passed in cursors
1748 but does not hold python references to them or prevent
1749 them from being closed prematurely. This can cause
1750 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001751 return (PyObject*) newDBCursorObject(dbc, self);
1752}
1753
1754
1755static PyObject*
1756DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1757{
1758 int err, flags=0;
1759 PyObject* txnobj = NULL;
1760 PyObject* keyobj;
1761 DBT key;
1762 DB_TXN *txn = NULL;
1763 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001764 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001765
1766 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1767 &keyobj, &txnobj, &flags))
1768 return NULL;
1769 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001770 if (!make_dbt(keyobj, &key))
1771 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001772 return NULL;
1773 if (!checkTxnObj(txnobj, &txn))
1774 return NULL;
1775
1776 MYDB_BEGIN_ALLOW_THREADS;
1777 err = self->db->key_range(self->db, txn, &key, &range, flags);
1778 MYDB_END_ALLOW_THREADS;
1779
1780 RETURN_IF_ERR();
1781 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1782}
1783
1784
1785static PyObject*
1786DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1787{
1788 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1789 char* filename = NULL;
1790 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001791#if (DBVER >= 41)
1792 PyObject *txnobj = NULL;
1793 DB_TXN *txn = NULL;
1794 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001795 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001796 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1797 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001798 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001799 "filename", "dbtype", "flags", "mode", "txn", NULL};
1800#else
1801 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001802 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001803 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1804 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001805 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001806 "filename", "dbtype", "flags", "mode", NULL};
1807#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001809#if (DBVER >= 41)
1810 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1811 &filename, &dbname, &type, &flags, &mode,
1812 &txnobj))
1813#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001814 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001815 &filename, &dbname, &type, &flags,
1816 &mode))
1817#endif
1818 {
1819 PyErr_Clear();
1820 type = DB_UNKNOWN; flags = 0; mode = 0660;
1821 filename = NULL; dbname = NULL;
1822#if (DBVER >= 41)
1823 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1824 kwnames_basic,
1825 &filename, &type, &flags, &mode,
1826 &txnobj))
1827 return NULL;
1828#else
1829 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1830 kwnames_basic,
1831 &filename, &type, &flags, &mode))
1832 return NULL;
1833#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 }
1835
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001836#if (DBVER >= 41)
1837 if (!checkTxnObj(txnobj, &txn)) return NULL;
1838#endif
1839
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001840 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001841 PyObject *t = Py_BuildValue("(is)", 0,
1842 "Cannot call open() twice for DB object");
1843 PyErr_SetObject(DBError, t);
1844 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845 return NULL;
1846 }
1847
1848 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001849#if (DBVER >= 41)
1850 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1851#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001853#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 MYDB_END_ALLOW_THREADS;
1855 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001856 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001857 self->db = NULL;
1858 return NULL;
1859 }
1860
Gregory P. Smithfc006692007-11-05 09:06:28 +00001861#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00001862 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00001863#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00001864
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 self->flags = flags;
1866 RETURN_NONE();
1867}
1868
1869
1870static PyObject*
1871DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1872{
1873 int flags=0;
1874 PyObject* txnobj = NULL;
1875 int dlen = -1;
1876 int doff = -1;
1877 PyObject* keyobj, *dataobj, *retval;
1878 DBT key, data;
1879 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001880 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001881 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001882
1883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1884 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1885 return NULL;
1886
1887 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001888 if (!make_key_dbt(self, keyobj, &key, NULL))
1889 return NULL;
1890 if ( !make_dbt(dataobj, &data) ||
1891 !add_partial_dbt(&data, dlen, doff) ||
1892 !checkTxnObj(txnobj, &txn) )
1893 {
1894 FREE_DBT(key);
1895 return NULL;
1896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001897
1898 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1899 FREE_DBT(key);
1900 return NULL;
1901 }
1902
1903 if (flags & DB_APPEND)
1904 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1905 else {
1906 retval = Py_None;
1907 Py_INCREF(retval);
1908 }
1909 FREE_DBT(key);
1910 return retval;
1911}
1912
1913
1914
1915static PyObject*
1916DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1917{
1918 char* filename;
1919 char* database = NULL;
1920 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001921 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001922
1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1924 &filename, &database, &flags))
1925 return NULL;
1926 CHECK_DB_NOT_CLOSED(self);
1927
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001929 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 RETURN_IF_ERR();
1931 RETURN_NONE();
1932}
1933
1934
1935
1936static PyObject*
1937DB_rename(DBObject* self, PyObject* args)
1938{
1939 char* filename;
1940 char* database;
1941 char* newname;
1942 int err, flags=0;
1943
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001944 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1945 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1948
1949 MYDB_BEGIN_ALLOW_THREADS;
1950 err = self->db->rename(self->db, filename, database, newname, flags);
1951 MYDB_END_ALLOW_THREADS;
1952 RETURN_IF_ERR();
1953 RETURN_NONE();
1954}
1955
1956
1957static PyObject*
1958DB_set_bt_minkey(DBObject* self, PyObject* args)
1959{
1960 int err, minkey;
1961
1962 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1963 return NULL;
1964 CHECK_DB_NOT_CLOSED(self);
1965
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->set_bt_minkey(self->db, minkey);
1968 MYDB_END_ALLOW_THREADS;
1969 RETURN_IF_ERR();
1970 RETURN_NONE();
1971}
1972
Neal Norwitz84562352005-10-20 04:30:15 +00001973#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001974static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001975_default_cmp(const DBT *leftKey,
1976 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001977{
1978 int res;
1979 int lsize = leftKey->size, rsize = rightKey->size;
1980
Georg Brandlef1701f2006-03-07 14:57:48 +00001981 res = memcmp(leftKey->data, rightKey->data,
1982 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001983
1984 if (res == 0) {
1985 if (lsize < rsize) {
1986 res = -1;
1987 }
1988 else if (lsize > rsize) {
1989 res = 1;
1990 }
1991 }
1992 return res;
1993}
1994
1995static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001996_db_compareCallback(DB* db,
1997 const DBT *leftKey,
1998 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001999{
2000 int res = 0;
2001 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002002 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002003 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002004
2005 if (self == NULL || self->btCompareCallback == NULL) {
2006 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002007 PyErr_SetString(PyExc_TypeError,
2008 (self == 0
2009 ? "DB_bt_compare db is NULL."
2010 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002011 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002012 PyErr_Print();
2013 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002014 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002015 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002016 MYDB_BEGIN_BLOCK_THREADS;
2017
Thomas Woutersb3153832006-03-08 01:47:19 +00002018 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2019 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002020 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002021 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002022 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002023 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002024 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002025 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002026 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002027 PyErr_Print();
2028 res = _default_cmp(leftKey, rightKey);
2029 } else if (PyInt_Check(result)) {
2030 res = PyInt_AsLong(result);
2031 } else {
2032 PyErr_SetString(PyExc_TypeError,
2033 "DB_bt_compare callback MUST return an int.");
2034 /* we're in a callback within the DB code, we can't raise */
2035 PyErr_Print();
2036 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002037 }
2038
Thomas Woutersb3153832006-03-08 01:47:19 +00002039 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002040 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002041
2042 MYDB_END_BLOCK_THREADS;
2043 }
2044 return res;
2045}
2046
2047static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002048DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002049{
2050 int err;
2051 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002052 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002053
Georg Brandlef1701f2006-03-07 14:57:48 +00002054 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002055 return NULL;
2056
Georg Brandlef1701f2006-03-07 14:57:48 +00002057 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002058
Georg Brandlef1701f2006-03-07 14:57:48 +00002059 if (!PyCallable_Check(comparator)) {
2060 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002061 return NULL;
2062 }
2063
2064 /*
2065 * Perform a test call of the comparator function with two empty
2066 * string objects here. verify that it returns an int (0).
2067 * err if not.
2068 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002069 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002070 result = PyEval_CallObject(comparator, tuple);
2071 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002072 if (result == NULL)
2073 return NULL;
2074 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002075 PyErr_SetString(PyExc_TypeError,
2076 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002078 } else if (PyInt_AsLong(result) != 0) {
2079 PyErr_SetString(PyExc_TypeError,
2080 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081 return NULL;
2082 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002083 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002084
2085 /* We don't accept multiple set_bt_compare operations, in order to
2086 * simplify the code. This would have no real use, as one cannot
2087 * change the function once the db is opened anyway */
2088 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002089 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002090 return NULL;
2091 }
2092
Georg Brandlef1701f2006-03-07 14:57:48 +00002093 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002094 self->btCompareCallback = comparator;
2095
2096 /* This is to workaround a problem with un-initialized threads (see
2097 comment in DB_associate) */
2098#ifdef WITH_THREAD
2099 PyEval_InitThreads();
2100#endif
2101
Thomas Woutersb3153832006-03-08 01:47:19 +00002102 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103
2104 if (err) {
2105 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002106 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107 self->btCompareCallback = NULL;
2108 }
2109
Georg Brandlef1701f2006-03-07 14:57:48 +00002110 RETURN_IF_ERR();
2111 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002112}
Neal Norwitz84562352005-10-20 04:30:15 +00002113#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002115
2116static PyObject*
2117DB_set_cachesize(DBObject* self, PyObject* args)
2118{
2119 int err;
2120 int gbytes = 0, bytes = 0, ncache = 0;
2121
2122 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2123 &gbytes,&bytes,&ncache))
2124 return NULL;
2125 CHECK_DB_NOT_CLOSED(self);
2126
2127 MYDB_BEGIN_ALLOW_THREADS;
2128 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2129 MYDB_END_ALLOW_THREADS;
2130 RETURN_IF_ERR();
2131 RETURN_NONE();
2132}
2133
2134
2135static PyObject*
2136DB_set_flags(DBObject* self, PyObject* args)
2137{
2138 int err, flags;
2139
2140 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2141 return NULL;
2142 CHECK_DB_NOT_CLOSED(self);
2143
2144 MYDB_BEGIN_ALLOW_THREADS;
2145 err = self->db->set_flags(self->db, flags);
2146 MYDB_END_ALLOW_THREADS;
2147 RETURN_IF_ERR();
2148
2149 self->setflags |= flags;
2150 RETURN_NONE();
2151}
2152
2153
2154static PyObject*
2155DB_set_h_ffactor(DBObject* self, PyObject* args)
2156{
2157 int err, ffactor;
2158
2159 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2160 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2162
2163 MYDB_BEGIN_ALLOW_THREADS;
2164 err = self->db->set_h_ffactor(self->db, ffactor);
2165 MYDB_END_ALLOW_THREADS;
2166 RETURN_IF_ERR();
2167 RETURN_NONE();
2168}
2169
2170
2171static PyObject*
2172DB_set_h_nelem(DBObject* self, PyObject* args)
2173{
2174 int err, nelem;
2175
2176 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2177 return NULL;
2178 CHECK_DB_NOT_CLOSED(self);
2179
2180 MYDB_BEGIN_ALLOW_THREADS;
2181 err = self->db->set_h_nelem(self->db, nelem);
2182 MYDB_END_ALLOW_THREADS;
2183 RETURN_IF_ERR();
2184 RETURN_NONE();
2185}
2186
2187
2188static PyObject*
2189DB_set_lorder(DBObject* self, PyObject* args)
2190{
2191 int err, lorder;
2192
2193 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2194 return NULL;
2195 CHECK_DB_NOT_CLOSED(self);
2196
2197 MYDB_BEGIN_ALLOW_THREADS;
2198 err = self->db->set_lorder(self->db, lorder);
2199 MYDB_END_ALLOW_THREADS;
2200 RETURN_IF_ERR();
2201 RETURN_NONE();
2202}
2203
2204
2205static PyObject*
2206DB_set_pagesize(DBObject* self, PyObject* args)
2207{
2208 int err, pagesize;
2209
2210 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2211 return NULL;
2212 CHECK_DB_NOT_CLOSED(self);
2213
2214 MYDB_BEGIN_ALLOW_THREADS;
2215 err = self->db->set_pagesize(self->db, pagesize);
2216 MYDB_END_ALLOW_THREADS;
2217 RETURN_IF_ERR();
2218 RETURN_NONE();
2219}
2220
2221
2222static PyObject*
2223DB_set_re_delim(DBObject* self, PyObject* args)
2224{
2225 int err;
2226 char delim;
2227
2228 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2229 PyErr_Clear();
2230 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2231 return NULL;
2232 }
2233
2234 CHECK_DB_NOT_CLOSED(self);
2235
2236 MYDB_BEGIN_ALLOW_THREADS;
2237 err = self->db->set_re_delim(self->db, delim);
2238 MYDB_END_ALLOW_THREADS;
2239 RETURN_IF_ERR();
2240 RETURN_NONE();
2241}
2242
2243static PyObject*
2244DB_set_re_len(DBObject* self, PyObject* args)
2245{
2246 int err, len;
2247
2248 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2249 return NULL;
2250 CHECK_DB_NOT_CLOSED(self);
2251
2252 MYDB_BEGIN_ALLOW_THREADS;
2253 err = self->db->set_re_len(self->db, len);
2254 MYDB_END_ALLOW_THREADS;
2255 RETURN_IF_ERR();
2256 RETURN_NONE();
2257}
2258
2259
2260static PyObject*
2261DB_set_re_pad(DBObject* self, PyObject* args)
2262{
2263 int err;
2264 char pad;
2265
2266 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2267 PyErr_Clear();
2268 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2269 return NULL;
2270 }
2271 CHECK_DB_NOT_CLOSED(self);
2272
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_re_pad(self->db, pad);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2278}
2279
2280
2281static PyObject*
2282DB_set_re_source(DBObject* self, PyObject* args)
2283{
2284 int err;
2285 char *re_source;
2286
2287 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2288 return NULL;
2289 CHECK_DB_NOT_CLOSED(self);
2290
2291 MYDB_BEGIN_ALLOW_THREADS;
2292 err = self->db->set_re_source(self->db, re_source);
2293 MYDB_END_ALLOW_THREADS;
2294 RETURN_IF_ERR();
2295 RETURN_NONE();
2296}
2297
2298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002299static PyObject*
2300DB_set_q_extentsize(DBObject* self, PyObject* args)
2301{
2302 int err;
2303 int extentsize;
2304
2305 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2306 return NULL;
2307 CHECK_DB_NOT_CLOSED(self);
2308
2309 MYDB_BEGIN_ALLOW_THREADS;
2310 err = self->db->set_q_extentsize(self->db, extentsize);
2311 MYDB_END_ALLOW_THREADS;
2312 RETURN_IF_ERR();
2313 RETURN_NONE();
2314}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002315
2316static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002317DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002318{
2319 int err, flags = 0, type;
2320 void* sp;
2321 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002322#if (DBVER >= 43)
2323 PyObject* txnobj = NULL;
2324 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002325 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002326#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002327 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002328#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002329
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002330#if (DBVER >= 43)
2331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2332 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002333 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002334 if (!checkTxnObj(txnobj, &txn))
2335 return NULL;
2336#else
2337 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2338 return NULL;
2339#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002340 CHECK_DB_NOT_CLOSED(self);
2341
2342 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002343#if (DBVER >= 43)
2344 err = self->db->stat(self->db, txn, &sp, flags);
2345#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002346 err = self->db->stat(self->db, &sp, flags);
2347#else
2348 err = self->db->stat(self->db, &sp, NULL, flags);
2349#endif
2350 MYDB_END_ALLOW_THREADS;
2351 RETURN_IF_ERR();
2352
2353 self->haveStat = 1;
2354
2355 /* Turn the stat structure into a dictionary */
2356 type = _DB_get_type(self);
2357 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2358 free(sp);
2359 return NULL;
2360 }
2361
2362#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2363#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2364#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2365
2366 switch (type) {
2367 case DB_HASH:
2368 MAKE_HASH_ENTRY(magic);
2369 MAKE_HASH_ENTRY(version);
2370 MAKE_HASH_ENTRY(nkeys);
2371 MAKE_HASH_ENTRY(ndata);
2372 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002373#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002374 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002375#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002376 MAKE_HASH_ENTRY(ffactor);
2377 MAKE_HASH_ENTRY(buckets);
2378 MAKE_HASH_ENTRY(free);
2379 MAKE_HASH_ENTRY(bfree);
2380 MAKE_HASH_ENTRY(bigpages);
2381 MAKE_HASH_ENTRY(big_bfree);
2382 MAKE_HASH_ENTRY(overflows);
2383 MAKE_HASH_ENTRY(ovfl_free);
2384 MAKE_HASH_ENTRY(dup);
2385 MAKE_HASH_ENTRY(dup_free);
2386 break;
2387
2388 case DB_BTREE:
2389 case DB_RECNO:
2390 MAKE_BT_ENTRY(magic);
2391 MAKE_BT_ENTRY(version);
2392 MAKE_BT_ENTRY(nkeys);
2393 MAKE_BT_ENTRY(ndata);
2394 MAKE_BT_ENTRY(pagesize);
2395 MAKE_BT_ENTRY(minkey);
2396 MAKE_BT_ENTRY(re_len);
2397 MAKE_BT_ENTRY(re_pad);
2398 MAKE_BT_ENTRY(levels);
2399 MAKE_BT_ENTRY(int_pg);
2400 MAKE_BT_ENTRY(leaf_pg);
2401 MAKE_BT_ENTRY(dup_pg);
2402 MAKE_BT_ENTRY(over_pg);
2403 MAKE_BT_ENTRY(free);
2404 MAKE_BT_ENTRY(int_pgfree);
2405 MAKE_BT_ENTRY(leaf_pgfree);
2406 MAKE_BT_ENTRY(dup_pgfree);
2407 MAKE_BT_ENTRY(over_pgfree);
2408 break;
2409
2410 case DB_QUEUE:
2411 MAKE_QUEUE_ENTRY(magic);
2412 MAKE_QUEUE_ENTRY(version);
2413 MAKE_QUEUE_ENTRY(nkeys);
2414 MAKE_QUEUE_ENTRY(ndata);
2415 MAKE_QUEUE_ENTRY(pagesize);
2416 MAKE_QUEUE_ENTRY(pages);
2417 MAKE_QUEUE_ENTRY(re_len);
2418 MAKE_QUEUE_ENTRY(re_pad);
2419 MAKE_QUEUE_ENTRY(pgfree);
2420#if (DBVER == 31)
2421 MAKE_QUEUE_ENTRY(start);
2422#endif
2423 MAKE_QUEUE_ENTRY(first_recno);
2424 MAKE_QUEUE_ENTRY(cur_recno);
2425 break;
2426
2427 default:
2428 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2429 Py_DECREF(d);
2430 d = NULL;
2431 }
2432
2433#undef MAKE_HASH_ENTRY
2434#undef MAKE_BT_ENTRY
2435#undef MAKE_QUEUE_ENTRY
2436
2437 free(sp);
2438 return d;
2439}
2440
2441static PyObject*
2442DB_sync(DBObject* self, PyObject* args)
2443{
2444 int err;
2445 int flags = 0;
2446
2447 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2448 return NULL;
2449 CHECK_DB_NOT_CLOSED(self);
2450
2451 MYDB_BEGIN_ALLOW_THREADS;
2452 err = self->db->sync(self->db, flags);
2453 MYDB_END_ALLOW_THREADS;
2454 RETURN_IF_ERR();
2455 RETURN_NONE();
2456}
2457
2458
2459#if (DBVER >= 33)
2460static PyObject*
2461DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2462{
2463 int err, flags=0;
2464 u_int32_t count=0;
2465 PyObject* txnobj = NULL;
2466 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002467 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002468
2469 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2470 &txnobj, &flags))
2471 return NULL;
2472 CHECK_DB_NOT_CLOSED(self);
2473 if (!checkTxnObj(txnobj, &txn))
2474 return NULL;
2475
2476 MYDB_BEGIN_ALLOW_THREADS;
2477 err = self->db->truncate(self->db, txn, &count, flags);
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480 return PyInt_FromLong(count);
2481}
2482#endif
2483
2484
2485static PyObject*
2486DB_upgrade(DBObject* self, PyObject* args)
2487{
2488 int err, flags=0;
2489 char *filename;
2490
2491 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2492 return NULL;
2493 CHECK_DB_NOT_CLOSED(self);
2494
2495 MYDB_BEGIN_ALLOW_THREADS;
2496 err = self->db->upgrade(self->db, filename, flags);
2497 MYDB_END_ALLOW_THREADS;
2498 RETURN_IF_ERR();
2499 RETURN_NONE();
2500}
2501
2502
2503static PyObject*
2504DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2505{
2506 int err, flags=0;
2507 char* fileName;
2508 char* dbName=NULL;
2509 char* outFileName=NULL;
2510 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002511 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002512 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002513
2514 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2515 &fileName, &dbName, &outFileName, &flags))
2516 return NULL;
2517
2518 CHECK_DB_NOT_CLOSED(self);
2519 if (outFileName)
2520 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002521 /* XXX(nnorwitz): it should probably be an exception if outFile
2522 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002523
2524 MYDB_BEGIN_ALLOW_THREADS;
2525 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2526 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002527 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002528 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002529
2530 /* DB.verify acts as a DB handle destructor (like close); this was
2531 * documented in BerkeleyDB 4.2 but had the undocumented effect
2532 * of not being safe in prior versions while still requiring an explicit
2533 * DB.close call afterwards. Lets call close for the user to emulate
2534 * the safe 4.2 behaviour. */
2535#if (DBVER <= 41)
2536 self->db->close(self->db, 0);
2537#endif
2538 self->db = NULL;
2539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002540 RETURN_IF_ERR();
2541 RETURN_NONE();
2542}
2543
2544
2545static PyObject*
2546DB_set_get_returns_none(DBObject* self, PyObject* args)
2547{
2548 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002549 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002550
2551 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2552 return NULL;
2553 CHECK_DB_NOT_CLOSED(self);
2554
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002555 if (self->moduleFlags.getReturnsNone)
2556 ++oldValue;
2557 if (self->moduleFlags.cursorSetReturnsNone)
2558 ++oldValue;
2559 self->moduleFlags.getReturnsNone = (flags >= 1);
2560 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002561 return PyInt_FromLong(oldValue);
2562}
2563
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002564#if (DBVER >= 41)
2565static PyObject*
2566DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2567{
2568 int err;
2569 u_int32_t flags=0;
2570 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002571 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002572
2573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2574 &passwd, &flags)) {
2575 return NULL;
2576 }
2577
2578 MYDB_BEGIN_ALLOW_THREADS;
2579 err = self->db->set_encrypt(self->db, passwd, flags);
2580 MYDB_END_ALLOW_THREADS;
2581
2582 RETURN_IF_ERR();
2583 RETURN_NONE();
2584}
2585#endif /* DBVER >= 41 */
2586
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587
2588/*-------------------------------------------------------------- */
2589/* Mapping and Dictionary-like access routines */
2590
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002591Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002592{
2593 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002594 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002595 int flags = 0;
2596 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002597 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002598
2599 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002600 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2601 PyErr_SetObject(DBError, t);
2602 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002603 return -1;
2604 }
2605
2606 if (self->haveStat) { /* Has the stat function been called recently? If
2607 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002608 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002609 }
2610
2611 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002612redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002613#if (DBVER >= 43)
2614 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2615#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 err = self->db->stat(self->db, &sp, flags);
2617#else
2618 err = self->db->stat(self->db, &sp, NULL, flags);
2619#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002620
2621 /* All the stat structures have matching fields upto the ndata field,
2622 so we can use any of them for the type cast */
2623 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2624
2625 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2626 * redo a full stat to make sure.
2627 * Fixes SF python bug 1493322, pybsddb bug 1184012
2628 */
2629 if (size == 0 && (flags & DB_FAST_STAT)) {
2630 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002631 if (!err)
2632 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002633 goto redo_stat_for_length;
2634 }
2635
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636 MYDB_END_ALLOW_THREADS;
2637
2638 if (err)
2639 return -1;
2640
2641 self->haveStat = 1;
2642
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002643 free(sp);
2644 return size;
2645}
2646
2647
2648PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2649{
2650 int err;
2651 PyObject* retval;
2652 DBT key;
2653 DBT data;
2654
2655 CHECK_DB_NOT_CLOSED(self);
2656 if (!make_key_dbt(self, keyobj, &key, NULL))
2657 return NULL;
2658
2659 CLEAR_DBT(data);
2660 if (CHECK_DBFLAG(self, DB_THREAD)) {
2661 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2662 data.flags = DB_DBT_MALLOC;
2663 }
2664 MYDB_BEGIN_ALLOW_THREADS;
2665 err = self->db->get(self->db, NULL, &key, &data, 0);
2666 MYDB_END_ALLOW_THREADS;
2667 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2668 PyErr_SetObject(PyExc_KeyError, keyobj);
2669 retval = NULL;
2670 }
2671 else if (makeDBError(err)) {
2672 retval = NULL;
2673 }
2674 else {
2675 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2676 FREE_DBT(data);
2677 }
2678
2679 FREE_DBT(key);
2680 return retval;
2681}
2682
2683
2684static int
2685DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2686{
2687 DBT key, data;
2688 int retval;
2689 int flags = 0;
2690
2691 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002692 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError, t);
2694 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695 return -1;
2696 }
2697
2698 if (!make_key_dbt(self, keyobj, &key, NULL))
2699 return -1;
2700
2701 if (dataobj != NULL) {
2702 if (!make_dbt(dataobj, &data))
2703 retval = -1;
2704 else {
2705 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002706 /* dictionaries shouldn't have duplicate keys */
2707 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002708 retval = _DB_put(self, NULL, &key, &data, flags);
2709
2710 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002711 /* try deleting any old record that matches and then PUT it
2712 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002713 _DB_delete(self, NULL, &key, 0);
2714 PyErr_Clear();
2715 retval = _DB_put(self, NULL, &key, &data, flags);
2716 }
2717 }
2718 }
2719 else {
2720 /* dataobj == NULL, so delete the key */
2721 retval = _DB_delete(self, NULL, &key, 0);
2722 }
2723 FREE_DBT(key);
2724 return retval;
2725}
2726
2727
2728static PyObject*
2729DB_has_key(DBObject* self, PyObject* args)
2730{
2731 int err;
2732 PyObject* keyobj;
2733 DBT key, data;
2734 PyObject* txnobj = NULL;
2735 DB_TXN *txn = NULL;
2736
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002737 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002738 return NULL;
2739 CHECK_DB_NOT_CLOSED(self);
2740 if (!make_key_dbt(self, keyobj, &key, NULL))
2741 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002742 if (!checkTxnObj(txnobj, &txn)) {
2743 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002745 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002747 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002748 it has a record but can't allocate a buffer for the data. This saves
2749 having to deal with data we won't be using.
2750 */
2751 CLEAR_DBT(data);
2752 data.flags = DB_DBT_USERMEM;
2753
2754 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002755 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002756 MYDB_END_ALLOW_THREADS;
2757 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002758
2759 if (err == DB_BUFFER_SMALL || err == 0) {
2760 return PyInt_FromLong(1);
2761 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2762 return PyInt_FromLong(0);
2763 }
2764
2765 makeDBError(err);
2766 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002767}
2768
2769
2770#define _KEYS_LIST 1
2771#define _VALUES_LIST 2
2772#define _ITEMS_LIST 3
2773
2774static PyObject*
2775_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2776{
2777 int err, dbtype;
2778 DBT key;
2779 DBT data;
2780 DBC *cursor;
2781 PyObject* list;
2782 PyObject* item = NULL;
2783
2784 CHECK_DB_NOT_CLOSED(self);
2785 CLEAR_DBT(key);
2786 CLEAR_DBT(data);
2787
2788 dbtype = _DB_get_type(self);
2789 if (dbtype == -1)
2790 return NULL;
2791
2792 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002793 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002794 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002795
2796 /* get a cursor */
2797 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002798 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002800 if (makeDBError(err)) {
2801 Py_DECREF(list);
2802 return NULL;
2803 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804
2805 if (CHECK_DBFLAG(self, DB_THREAD)) {
2806 key.flags = DB_DBT_REALLOC;
2807 data.flags = DB_DBT_REALLOC;
2808 }
2809
2810 while (1) { /* use the cursor to traverse the DB, collecting items */
2811 MYDB_BEGIN_ALLOW_THREADS;
2812 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2813 MYDB_END_ALLOW_THREADS;
2814
2815 if (err) {
2816 /* for any error, break out of the loop */
2817 break;
2818 }
2819
2820 switch (type) {
2821 case _KEYS_LIST:
2822 switch(dbtype) {
2823 case DB_BTREE:
2824 case DB_HASH:
2825 default:
2826 item = PyString_FromStringAndSize((char*)key.data, key.size);
2827 break;
2828 case DB_RECNO:
2829 case DB_QUEUE:
2830 item = PyInt_FromLong(*((db_recno_t*)key.data));
2831 break;
2832 }
2833 break;
2834
2835 case _VALUES_LIST:
2836 item = PyString_FromStringAndSize((char*)data.data, data.size);
2837 break;
2838
2839 case _ITEMS_LIST:
2840 switch(dbtype) {
2841 case DB_BTREE:
2842 case DB_HASH:
2843 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002844 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2845 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 break;
2847 case DB_RECNO:
2848 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002849 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2850 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 break;
2852 }
2853 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002854 default:
2855 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2856 item = NULL;
2857 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 }
2859 if (item == NULL) {
2860 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 list = NULL;
2862 goto done;
2863 }
2864 PyList_Append(list, item);
2865 Py_DECREF(item);
2866 }
2867
Gregory P. Smithe9477062005-06-04 06:46:59 +00002868 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2869 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002870 Py_DECREF(list);
2871 list = NULL;
2872 }
2873
2874 done:
2875 FREE_DBT(key);
2876 FREE_DBT(data);
2877 MYDB_BEGIN_ALLOW_THREADS;
2878 cursor->c_close(cursor);
2879 MYDB_END_ALLOW_THREADS;
2880 return list;
2881}
2882
2883
2884static PyObject*
2885DB_keys(DBObject* self, PyObject* args)
2886{
2887 PyObject* txnobj = NULL;
2888 DB_TXN *txn = NULL;
2889
Georg Brandl96a8c392006-05-29 21:04:52 +00002890 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002891 return NULL;
2892 if (!checkTxnObj(txnobj, &txn))
2893 return NULL;
2894 return _DB_make_list(self, txn, _KEYS_LIST);
2895}
2896
2897
2898static PyObject*
2899DB_items(DBObject* self, PyObject* args)
2900{
2901 PyObject* txnobj = NULL;
2902 DB_TXN *txn = NULL;
2903
Georg Brandl96a8c392006-05-29 21:04:52 +00002904 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 return NULL;
2906 if (!checkTxnObj(txnobj, &txn))
2907 return NULL;
2908 return _DB_make_list(self, txn, _ITEMS_LIST);
2909}
2910
2911
2912static PyObject*
2913DB_values(DBObject* self, PyObject* args)
2914{
2915 PyObject* txnobj = NULL;
2916 DB_TXN *txn = NULL;
2917
Georg Brandl96a8c392006-05-29 21:04:52 +00002918 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919 return NULL;
2920 if (!checkTxnObj(txnobj, &txn))
2921 return NULL;
2922 return _DB_make_list(self, txn, _VALUES_LIST);
2923}
2924
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925/* --------------------------------------------------------------------- */
2926/* DBCursor methods */
2927
2928
2929static PyObject*
2930DBC_close(DBCursorObject* self, PyObject* args)
2931{
2932 int err = 0;
2933
2934 if (!PyArg_ParseTuple(args, ":close"))
2935 return NULL;
2936
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 if (self->dbc != NULL) {
2938 MYDB_BEGIN_ALLOW_THREADS;
2939 err = self->dbc->c_close(self->dbc);
2940 self->dbc = NULL;
2941 MYDB_END_ALLOW_THREADS;
2942 }
2943 RETURN_IF_ERR();
2944 RETURN_NONE();
2945}
2946
2947
2948static PyObject*
2949DBC_count(DBCursorObject* self, PyObject* args)
2950{
2951 int err = 0;
2952 db_recno_t count;
2953 int flags = 0;
2954
2955 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2956 return NULL;
2957
2958 CHECK_CURSOR_NOT_CLOSED(self);
2959
2960 MYDB_BEGIN_ALLOW_THREADS;
2961 err = self->dbc->c_count(self->dbc, &count, flags);
2962 MYDB_END_ALLOW_THREADS;
2963 RETURN_IF_ERR();
2964
2965 return PyInt_FromLong(count);
2966}
2967
2968
2969static PyObject*
2970DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2971{
2972 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2973}
2974
2975
2976static PyObject*
2977DBC_delete(DBCursorObject* self, PyObject* args)
2978{
2979 int err, flags=0;
2980
2981 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2982 return NULL;
2983
2984 CHECK_CURSOR_NOT_CLOSED(self);
2985
2986 MYDB_BEGIN_ALLOW_THREADS;
2987 err = self->dbc->c_del(self->dbc, flags);
2988 MYDB_END_ALLOW_THREADS;
2989 RETURN_IF_ERR();
2990
2991 self->mydb->haveStat = 0;
2992 RETURN_NONE();
2993}
2994
2995
2996static PyObject*
2997DBC_dup(DBCursorObject* self, PyObject* args)
2998{
2999 int err, flags =0;
3000 DBC* dbc = NULL;
3001
3002 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3003 return NULL;
3004
3005 CHECK_CURSOR_NOT_CLOSED(self);
3006
3007 MYDB_BEGIN_ALLOW_THREADS;
3008 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3009 MYDB_END_ALLOW_THREADS;
3010 RETURN_IF_ERR();
3011
3012 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3013}
3014
3015static PyObject*
3016DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3017{
3018 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3019}
3020
3021
3022static PyObject*
3023DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3024{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003025 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003026 PyObject* keyobj = NULL;
3027 PyObject* dataobj = NULL;
3028 PyObject* retval = NULL;
3029 int dlen = -1;
3030 int doff = -1;
3031 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003032 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003033 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034
3035 CLEAR_DBT(key);
3036 CLEAR_DBT(data);
3037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003038 &flags, &dlen, &doff))
3039 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003040 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3042 &kwnames[1],
3043 &keyobj, &flags, &dlen, &doff))
3044 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3047 kwnames, &keyobj, &dataobj,
3048 &flags, &dlen, &doff))
3049 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 return NULL;
3051 }
3052 }
3053 }
3054
3055 CHECK_CURSOR_NOT_CLOSED(self);
3056
3057 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3058 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003059 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3060 (!add_partial_dbt(&data, dlen, doff)) )
3061 {
3062 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003063 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003064 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003065
3066 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3067 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003068 if (!(key.flags & DB_DBT_REALLOC)) {
3069 key.flags |= DB_DBT_MALLOC;
3070 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 }
3072
3073 MYDB_BEGIN_ALLOW_THREADS;
3074 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3075 MYDB_END_ALLOW_THREADS;
3076
Gregory P. Smithe9477062005-06-04 06:46:59 +00003077 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3078 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 Py_INCREF(Py_None);
3080 retval = Py_None;
3081 }
3082 else if (makeDBError(err)) {
3083 retval = NULL;
3084 }
3085 else {
3086 switch (_DB_get_type(self->mydb)) {
3087 case -1:
3088 retval = NULL;
3089 break;
3090 case DB_BTREE:
3091 case DB_HASH:
3092 default:
3093 retval = Py_BuildValue("s#s#", key.data, key.size,
3094 data.data, data.size);
3095 break;
3096 case DB_RECNO:
3097 case DB_QUEUE:
3098 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3099 data.data, data.size);
3100 break;
3101 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 FREE_DBT(data);
3103 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003104 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003105 return retval;
3106}
3107
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003108#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003109static PyObject*
3110DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3111{
3112 int err, flags=0;
3113 PyObject* keyobj = NULL;
3114 PyObject* dataobj = NULL;
3115 PyObject* retval = NULL;
3116 int dlen = -1;
3117 int doff = -1;
3118 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003119 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3120 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003121
3122 CLEAR_DBT(key);
3123 CLEAR_DBT(data);
3124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3125 &flags, &dlen, &doff))
3126 {
3127 PyErr_Clear();
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003129 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003130 &keyobj, &flags, &dlen, &doff))
3131 {
3132 PyErr_Clear();
3133 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3134 kwnames, &keyobj, &dataobj,
3135 &flags, &dlen, &doff))
3136 {
3137 return NULL;
3138 }
3139 }
3140 }
3141
3142 CHECK_CURSOR_NOT_CLOSED(self);
3143
3144 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3145 return NULL;
3146 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3147 (!add_partial_dbt(&data, dlen, doff)) ) {
3148 FREE_DBT(key);
3149 return NULL;
3150 }
3151
3152 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3153 data.flags = DB_DBT_MALLOC;
3154 if (!(key.flags & DB_DBT_REALLOC)) {
3155 key.flags |= DB_DBT_MALLOC;
3156 }
3157 }
3158
3159 CLEAR_DBT(pkey);
3160 pkey.flags = DB_DBT_MALLOC;
3161
3162 MYDB_BEGIN_ALLOW_THREADS;
3163 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3164 MYDB_END_ALLOW_THREADS;
3165
Gregory P. Smithe9477062005-06-04 06:46:59 +00003166 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3167 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003168 Py_INCREF(Py_None);
3169 retval = Py_None;
3170 }
3171 else if (makeDBError(err)) {
3172 retval = NULL;
3173 }
3174 else {
3175 PyObject *pkeyObj;
3176 PyObject *dataObj;
3177 dataObj = PyString_FromStringAndSize(data.data, data.size);
3178
3179 if (self->mydb->primaryDBType == DB_RECNO ||
3180 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003181 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003182 else
3183 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3184
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003185 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003186 {
3187 PyObject *keyObj;
3188 int type = _DB_get_type(self->mydb);
3189 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003190 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003191 else
3192 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003193#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003194 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003195#else
3196 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3197#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003198 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199 FREE_DBT(key);
3200 }
3201 else /* return just the pkey and data */
3202 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003203#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003204 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003205#else
3206 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3207#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003208 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003209 Py_DECREF(dataObj);
3210 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003211 FREE_DBT(pkey);
3212 FREE_DBT(data);
3213 }
3214 /* the only time REALLOC should be set is if we used an integer
3215 * key that make_key_dbt malloc'd for us. always free these. */
3216 if (key.flags & DB_DBT_REALLOC) {
3217 FREE_DBT(key);
3218 }
3219 return retval;
3220}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003221#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003222
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003223
3224static PyObject*
3225DBC_get_recno(DBCursorObject* self, PyObject* args)
3226{
3227 int err;
3228 db_recno_t recno;
3229 DBT key;
3230 DBT data;
3231
3232 if (!PyArg_ParseTuple(args, ":get_recno"))
3233 return NULL;
3234
3235 CHECK_CURSOR_NOT_CLOSED(self);
3236
3237 CLEAR_DBT(key);
3238 CLEAR_DBT(data);
3239 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3240 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3241 data.flags = DB_DBT_MALLOC;
3242 key.flags = DB_DBT_MALLOC;
3243 }
3244
3245 MYDB_BEGIN_ALLOW_THREADS;
3246 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3247 MYDB_END_ALLOW_THREADS;
3248 RETURN_IF_ERR();
3249
3250 recno = *((db_recno_t*)data.data);
3251 FREE_DBT(key);
3252 FREE_DBT(data);
3253 return PyInt_FromLong(recno);
3254}
3255
3256
3257static PyObject*
3258DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3259{
3260 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3261}
3262
3263
3264static PyObject*
3265DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3266{
3267 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3268}
3269
3270
3271static PyObject*
3272DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3273{
3274 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3275}
3276
3277
3278static PyObject*
3279DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3280{
3281 int err, flags = 0;
3282 PyObject* keyobj, *dataobj;
3283 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003284 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003285 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003286 int dlen = -1;
3287 int doff = -1;
3288
3289 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3290 &keyobj, &dataobj, &flags, &dlen, &doff))
3291 return NULL;
3292
3293 CHECK_CURSOR_NOT_CLOSED(self);
3294
3295 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3296 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003297 if (!make_dbt(dataobj, &data) ||
3298 !add_partial_dbt(&data, dlen, doff) )
3299 {
3300 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003301 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003302 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303
3304 MYDB_BEGIN_ALLOW_THREADS;
3305 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3306 MYDB_END_ALLOW_THREADS;
3307 FREE_DBT(key);
3308 RETURN_IF_ERR();
3309 self->mydb->haveStat = 0;
3310 RETURN_NONE();
3311}
3312
3313
3314static PyObject*
3315DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3316{
3317 int err, flags = 0;
3318 DBT key, data;
3319 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003320 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003321 int dlen = -1;
3322 int doff = -1;
3323
3324 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3325 &keyobj, &flags, &dlen, &doff))
3326 return NULL;
3327
3328 CHECK_CURSOR_NOT_CLOSED(self);
3329
3330 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3331 return NULL;
3332
3333 CLEAR_DBT(data);
3334 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3335 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3336 data.flags = DB_DBT_MALLOC;
3337 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003338 if (!add_partial_dbt(&data, dlen, doff)) {
3339 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003340 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003341 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342
3343 MYDB_BEGIN_ALLOW_THREADS;
3344 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3345 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003346 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3347 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003348 Py_INCREF(Py_None);
3349 retval = Py_None;
3350 }
3351 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003352 retval = NULL;
3353 }
3354 else {
3355 switch (_DB_get_type(self->mydb)) {
3356 case -1:
3357 retval = NULL;
3358 break;
3359 case DB_BTREE:
3360 case DB_HASH:
3361 default:
3362 retval = Py_BuildValue("s#s#", key.data, key.size,
3363 data.data, data.size);
3364 break;
3365 case DB_RECNO:
3366 case DB_QUEUE:
3367 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3368 data.data, data.size);
3369 break;
3370 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003371 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003372 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003374 /* the only time REALLOC should be set is if we used an integer
3375 * key that make_key_dbt malloc'd for us. always free these. */
3376 if (key.flags & DB_DBT_REALLOC) {
3377 FREE_DBT(key);
3378 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379
3380 return retval;
3381}
3382
3383
3384static PyObject*
3385DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3386{
3387 int err, flags = 0;
3388 DBT key, data;
3389 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003390 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 int dlen = -1;
3392 int doff = -1;
3393
3394 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3395 &keyobj, &flags, &dlen, &doff))
3396 return NULL;
3397
3398 CHECK_CURSOR_NOT_CLOSED(self);
3399
3400 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3401 return NULL;
3402
3403 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003404 if (!add_partial_dbt(&data, dlen, doff)) {
3405 FREE_DBT(key);
3406 return NULL;
3407 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3409 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003410 data.flags |= DB_DBT_MALLOC;
3411 /* only BTREE databases will return anything in the key */
3412 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3413 key.flags |= DB_DBT_MALLOC;
3414 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003416 MYDB_BEGIN_ALLOW_THREADS;
3417 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3418 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003419 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3420 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003421 Py_INCREF(Py_None);
3422 retval = Py_None;
3423 }
3424 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003425 retval = NULL;
3426 }
3427 else {
3428 switch (_DB_get_type(self->mydb)) {
3429 case -1:
3430 retval = NULL;
3431 break;
3432 case DB_BTREE:
3433 case DB_HASH:
3434 default:
3435 retval = Py_BuildValue("s#s#", key.data, key.size,
3436 data.data, data.size);
3437 break;
3438 case DB_RECNO:
3439 case DB_QUEUE:
3440 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3441 data.data, data.size);
3442 break;
3443 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003444 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 FREE_DBT(data);
3446 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003447 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003448 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 if (key.flags & DB_DBT_REALLOC) {
3450 FREE_DBT(key);
3451 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452
3453 return retval;
3454}
3455
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003456static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003457_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3458 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003460 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003462 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463
Gregory P. Smith7441e652003-11-03 21:35:31 +00003464 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3466 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003467 if (!make_dbt(dataobj, &data)) {
3468 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003470 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471
3472 MYDB_BEGIN_ALLOW_THREADS;
3473 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3474 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003475 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003476 Py_INCREF(Py_None);
3477 retval = Py_None;
3478 }
3479 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 retval = NULL;
3481 }
3482 else {
3483 switch (_DB_get_type(self->mydb)) {
3484 case -1:
3485 retval = NULL;
3486 break;
3487 case DB_BTREE:
3488 case DB_HASH:
3489 default:
3490 retval = Py_BuildValue("s#s#", key.data, key.size,
3491 data.data, data.size);
3492 break;
3493 case DB_RECNO:
3494 case DB_QUEUE:
3495 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3496 data.data, data.size);
3497 break;
3498 }
3499 }
3500
3501 FREE_DBT(key);
3502 return retval;
3503}
3504
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003505static PyObject*
3506DBC_get_both(DBCursorObject* self, PyObject* args)
3507{
3508 int flags=0;
3509 PyObject *keyobj, *dataobj;
3510
3511 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3512 return NULL;
3513
Gregory P. Smith7441e652003-11-03 21:35:31 +00003514 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003515 CHECK_CURSOR_NOT_CLOSED(self);
3516
3517 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3518 self->mydb->moduleFlags.getReturnsNone);
3519}
3520
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003521/* Return size of entry */
3522static PyObject*
3523DBC_get_current_size(DBCursorObject* self, PyObject* args)
3524{
3525 int err, flags=DB_CURRENT;
3526 PyObject* retval = NULL;
3527 DBT key, data;
3528
3529 if (!PyArg_ParseTuple(args, ":get_current_size"))
3530 return NULL;
3531 CHECK_CURSOR_NOT_CLOSED(self);
3532 CLEAR_DBT(key);
3533 CLEAR_DBT(data);
3534
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003535 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003536 getting the record size. */
3537 data.flags = DB_DBT_USERMEM;
3538 data.ulen = 0;
3539 MYDB_BEGIN_ALLOW_THREADS;
3540 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3541 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003542 if (err == DB_BUFFER_SMALL || !err) {
3543 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003544 retval = PyInt_FromLong((long)data.size);
3545 err = 0;
3546 }
3547
3548 FREE_DBT(key);
3549 FREE_DBT(data);
3550 RETURN_IF_ERR();
3551 return retval;
3552}
3553
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003554static PyObject*
3555DBC_set_both(DBCursorObject* self, PyObject* args)
3556{
3557 int flags=0;
3558 PyObject *keyobj, *dataobj;
3559
3560 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3561 return NULL;
3562
Gregory P. Smith7441e652003-11-03 21:35:31 +00003563 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003564 CHECK_CURSOR_NOT_CLOSED(self);
3565
3566 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3567 self->mydb->moduleFlags.cursorSetReturnsNone);
3568}
3569
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570
3571static PyObject*
3572DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3573{
3574 int err, irecno, flags=0;
3575 db_recno_t recno;
3576 DBT key, data;
3577 PyObject* retval;
3578 int dlen = -1;
3579 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003580 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581
3582 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3583 &irecno, &flags, &dlen, &doff))
3584 return NULL;
3585
3586 CHECK_CURSOR_NOT_CLOSED(self);
3587
3588 CLEAR_DBT(key);
3589 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003590 /* use allocated space so DB will be able to realloc room for the real
3591 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 key.data = malloc(sizeof(db_recno_t));
3593 if (key.data == NULL) {
3594 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3595 return NULL;
3596 }
3597 key.size = sizeof(db_recno_t);
3598 key.ulen = key.size;
3599 memcpy(key.data, &recno, sizeof(db_recno_t));
3600 key.flags = DB_DBT_REALLOC;
3601
3602 CLEAR_DBT(data);
3603 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3604 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3605 data.flags = DB_DBT_MALLOC;
3606 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003607 if (!add_partial_dbt(&data, dlen, doff)) {
3608 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003609 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611
3612 MYDB_BEGIN_ALLOW_THREADS;
3613 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3614 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003615 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3616 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003617 Py_INCREF(Py_None);
3618 retval = Py_None;
3619 }
3620 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003621 retval = NULL;
3622 }
3623 else { /* Can only be used for BTrees, so no need to return int key */
3624 retval = Py_BuildValue("s#s#", key.data, key.size,
3625 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003626 FREE_DBT(data);
3627 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003628 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003629
3630 return retval;
3631}
3632
3633
3634static PyObject*
3635DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3636{
3637 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3638}
3639
3640
3641static PyObject*
3642DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3643{
3644 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3645}
3646
3647
3648static PyObject*
3649DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3650{
3651 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3652}
3653
3654
3655static PyObject*
3656DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3657{
3658 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3659}
3660
3661
3662static PyObject*
3663DBC_join_item(DBCursorObject* self, PyObject* args)
3664{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003666 DBT key, data;
3667 PyObject* retval;
3668
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670 return NULL;
3671
3672 CHECK_CURSOR_NOT_CLOSED(self);
3673
3674 CLEAR_DBT(key);
3675 CLEAR_DBT(data);
3676 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3677 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3678 key.flags = DB_DBT_MALLOC;
3679 }
3680
3681 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003682 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003684 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3685 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003686 Py_INCREF(Py_None);
3687 retval = Py_None;
3688 }
3689 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 retval = NULL;
3691 }
3692 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003693 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694 FREE_DBT(key);
3695 }
3696
3697 return retval;
3698}
3699
3700
3701
3702/* --------------------------------------------------------------------- */
3703/* DBEnv methods */
3704
3705
3706static PyObject*
3707DBEnv_close(DBEnvObject* self, PyObject* args)
3708{
3709 int err, flags = 0;
3710
3711 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3712 return NULL;
3713 if (!self->closed) { /* Don't close more than once */
3714 MYDB_BEGIN_ALLOW_THREADS;
3715 err = self->db_env->close(self->db_env, flags);
3716 MYDB_END_ALLOW_THREADS;
3717 /* after calling DBEnv->close, regardless of error, this DBEnv
3718 * may not be accessed again (BerkeleyDB docs). */
3719 self->closed = 1;
3720 self->db_env = NULL;
3721 RETURN_IF_ERR();
3722 }
3723 RETURN_NONE();
3724}
3725
3726
3727static PyObject*
3728DBEnv_open(DBEnvObject* self, PyObject* args)
3729{
3730 int err, flags=0, mode=0660;
3731 char *db_home;
3732
3733 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3734 return NULL;
3735
3736 CHECK_ENV_NOT_CLOSED(self);
3737
3738 MYDB_BEGIN_ALLOW_THREADS;
3739 err = self->db_env->open(self->db_env, db_home, flags, mode);
3740 MYDB_END_ALLOW_THREADS;
3741 RETURN_IF_ERR();
3742 self->closed = 0;
3743 self->flags = flags;
3744 RETURN_NONE();
3745}
3746
3747
3748static PyObject*
3749DBEnv_remove(DBEnvObject* self, PyObject* args)
3750{
3751 int err, flags=0;
3752 char *db_home;
3753
3754 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3755 return NULL;
3756 CHECK_ENV_NOT_CLOSED(self);
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 err = self->db_env->remove(self->db_env, db_home, flags);
3759 MYDB_END_ALLOW_THREADS;
3760 RETURN_IF_ERR();
3761 RETURN_NONE();
3762}
3763
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003764#if (DBVER >= 41)
3765static PyObject*
3766DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3767{
3768 int err;
3769 u_int32_t flags=0;
3770 char *file = NULL;
3771 char *database = NULL;
3772 PyObject *txnobj = NULL;
3773 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003774 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003775 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003776
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003777 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003778 &file, &database, &txnobj, &flags)) {
3779 return NULL;
3780 }
3781 if (!checkTxnObj(txnobj, &txn)) {
3782 return NULL;
3783 }
3784 CHECK_ENV_NOT_CLOSED(self);
3785 MYDB_BEGIN_ALLOW_THREADS;
3786 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3790}
3791
3792static PyObject*
3793DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3794{
3795 int err;
3796 u_int32_t flags=0;
3797 char *file = NULL;
3798 char *database = NULL;
3799 char *newname = NULL;
3800 PyObject *txnobj = NULL;
3801 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003802 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003803 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003804
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003806 &file, &database, &newname, &txnobj, &flags)) {
3807 return NULL;
3808 }
3809 if (!checkTxnObj(txnobj, &txn)) {
3810 return NULL;
3811 }
3812 CHECK_ENV_NOT_CLOSED(self);
3813 MYDB_BEGIN_ALLOW_THREADS;
3814 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3815 flags);
3816 MYDB_END_ALLOW_THREADS;
3817 RETURN_IF_ERR();
3818 RETURN_NONE();
3819}
3820
3821static PyObject*
3822DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3823{
3824 int err;
3825 u_int32_t flags=0;
3826 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003827 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003828
3829 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3830 &passwd, &flags)) {
3831 return NULL;
3832 }
3833
3834 MYDB_BEGIN_ALLOW_THREADS;
3835 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3836 MYDB_END_ALLOW_THREADS;
3837
3838 RETURN_IF_ERR();
3839 RETURN_NONE();
3840}
3841#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003842
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003843#if (DBVER >= 40)
3844static PyObject*
3845DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3846{
3847 int err;
3848 u_int32_t flags=0;
3849 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003850 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003851
3852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3853 &timeout, &flags)) {
3854 return NULL;
3855 }
3856
3857 MYDB_BEGIN_ALLOW_THREADS;
3858 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3859 MYDB_END_ALLOW_THREADS;
3860
3861 RETURN_IF_ERR();
3862 RETURN_NONE();
3863}
3864#endif /* DBVER >= 40 */
3865
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003866static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003867DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3868{
3869 int err;
3870 long shm_key = 0;
3871
3872 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3873 return NULL;
3874 CHECK_ENV_NOT_CLOSED(self);
3875
3876 err = self->db_env->set_shm_key(self->db_env, shm_key);
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3879}
3880
3881static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003882DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3883{
3884 int err, gbytes=0, bytes=0, ncache=0;
3885
3886 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3887 &gbytes, &bytes, &ncache))
3888 return NULL;
3889 CHECK_ENV_NOT_CLOSED(self);
3890
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3896}
3897
3898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003899static PyObject*
3900DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3901{
3902 int err, flags=0, onoff=0;
3903
3904 if (!PyArg_ParseTuple(args, "ii:set_flags",
3905 &flags, &onoff))
3906 return NULL;
3907 CHECK_ENV_NOT_CLOSED(self);
3908
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->set_flags(self->db_env, flags, onoff);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3914}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003915
3916
3917static PyObject*
3918DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3919{
3920 int err;
3921 char *dir;
3922
3923 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3924 return NULL;
3925 CHECK_ENV_NOT_CLOSED(self);
3926
3927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = self->db_env->set_data_dir(self->db_env, dir);
3929 MYDB_END_ALLOW_THREADS;
3930 RETURN_IF_ERR();
3931 RETURN_NONE();
3932}
3933
3934
3935static PyObject*
3936DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3937{
3938 int err, lg_bsize;
3939
3940 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3941 return NULL;
3942 CHECK_ENV_NOT_CLOSED(self);
3943
3944 MYDB_BEGIN_ALLOW_THREADS;
3945 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3946 MYDB_END_ALLOW_THREADS;
3947 RETURN_IF_ERR();
3948 RETURN_NONE();
3949}
3950
3951
3952static PyObject*
3953DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3954{
3955 int err;
3956 char *dir;
3957
3958 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3959 return NULL;
3960 CHECK_ENV_NOT_CLOSED(self);
3961
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = self->db_env->set_lg_dir(self->db_env, dir);
3964 MYDB_END_ALLOW_THREADS;
3965 RETURN_IF_ERR();
3966 RETURN_NONE();
3967}
3968
3969static PyObject*
3970DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3971{
3972 int err, lg_max;
3973
3974 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3975 return NULL;
3976 CHECK_ENV_NOT_CLOSED(self);
3977
3978 MYDB_BEGIN_ALLOW_THREADS;
3979 err = self->db_env->set_lg_max(self->db_env, lg_max);
3980 MYDB_END_ALLOW_THREADS;
3981 RETURN_IF_ERR();
3982 RETURN_NONE();
3983}
3984
3985
Neal Norwitz84562352005-10-20 04:30:15 +00003986#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003987static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003988DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3989{
3990 int err, lg_max;
3991
3992 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3993 return NULL;
3994 CHECK_ENV_NOT_CLOSED(self);
3995
3996 MYDB_BEGIN_ALLOW_THREADS;
3997 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3998 MYDB_END_ALLOW_THREADS;
3999 RETURN_IF_ERR();
4000 RETURN_NONE();
4001}
Neal Norwitz84562352005-10-20 04:30:15 +00004002#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004003
4004
4005static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004006DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4007{
4008 int err, lk_detect;
4009
4010 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4011 return NULL;
4012 CHECK_ENV_NOT_CLOSED(self);
4013
4014 MYDB_BEGIN_ALLOW_THREADS;
4015 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4016 MYDB_END_ALLOW_THREADS;
4017 RETURN_IF_ERR();
4018 RETURN_NONE();
4019}
4020
4021
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004022#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004023static PyObject*
4024DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4025{
4026 int err, max;
4027
4028 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4029 return NULL;
4030 CHECK_ENV_NOT_CLOSED(self);
4031
4032 MYDB_BEGIN_ALLOW_THREADS;
4033 err = self->db_env->set_lk_max(self->db_env, max);
4034 MYDB_END_ALLOW_THREADS;
4035 RETURN_IF_ERR();
4036 RETURN_NONE();
4037}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004038#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004039
4040
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004041
4042static PyObject*
4043DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4044{
4045 int err, max;
4046
4047 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4048 return NULL;
4049 CHECK_ENV_NOT_CLOSED(self);
4050
4051 MYDB_BEGIN_ALLOW_THREADS;
4052 err = self->db_env->set_lk_max_locks(self->db_env, max);
4053 MYDB_END_ALLOW_THREADS;
4054 RETURN_IF_ERR();
4055 RETURN_NONE();
4056}
4057
4058
4059static PyObject*
4060DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4061{
4062 int err, max;
4063
4064 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4065 return NULL;
4066 CHECK_ENV_NOT_CLOSED(self);
4067
4068 MYDB_BEGIN_ALLOW_THREADS;
4069 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4070 MYDB_END_ALLOW_THREADS;
4071 RETURN_IF_ERR();
4072 RETURN_NONE();
4073}
4074
4075
4076static PyObject*
4077DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4078{
4079 int err, max;
4080
4081 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4082 return NULL;
4083 CHECK_ENV_NOT_CLOSED(self);
4084
4085 MYDB_BEGIN_ALLOW_THREADS;
4086 err = self->db_env->set_lk_max_objects(self->db_env, max);
4087 MYDB_END_ALLOW_THREADS;
4088 RETURN_IF_ERR();
4089 RETURN_NONE();
4090}
4091
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004092
4093static PyObject*
4094DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4095{
4096 int err, mp_mmapsize;
4097
4098 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4101
4102 MYDB_BEGIN_ALLOW_THREADS;
4103 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4104 MYDB_END_ALLOW_THREADS;
4105 RETURN_IF_ERR();
4106 RETURN_NONE();
4107}
4108
4109
4110static PyObject*
4111DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4112{
4113 int err;
4114 char *dir;
4115
4116 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4117 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4119
4120 MYDB_BEGIN_ALLOW_THREADS;
4121 err = self->db_env->set_tmp_dir(self->db_env, dir);
4122 MYDB_END_ALLOW_THREADS;
4123 RETURN_IF_ERR();
4124 RETURN_NONE();
4125}
4126
4127
4128static PyObject*
4129DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4130{
4131 int flags = 0;
4132 PyObject* txnobj = NULL;
4133 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004134 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004135
4136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4137 &txnobj, &flags))
4138 return NULL;
4139
4140 if (!checkTxnObj(txnobj, &txn))
4141 return NULL;
4142 CHECK_ENV_NOT_CLOSED(self);
4143
4144 return (PyObject*)newDBTxnObject(self, txn, flags);
4145}
4146
4147
4148static PyObject*
4149DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4150{
4151 int err, kbyte=0, min=0, flags=0;
4152
4153 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4154 return NULL;
4155 CHECK_ENV_NOT_CLOSED(self);
4156
4157 MYDB_BEGIN_ALLOW_THREADS;
4158#if (DBVER >= 40)
4159 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4160#else
4161 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4162#endif
4163 MYDB_END_ALLOW_THREADS;
4164 RETURN_IF_ERR();
4165 RETURN_NONE();
4166}
4167
4168
4169static PyObject*
4170DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4171{
4172 int err, max;
4173
4174 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004178 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004179 RETURN_IF_ERR();
4180 RETURN_NONE();
4181}
4182
4183
4184static PyObject*
4185DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4186{
4187 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004188 long stamp;
4189 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004190
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004191 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004194 timestamp = (time_t)stamp;
4195 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004196 RETURN_IF_ERR();
4197 RETURN_NONE();
4198}
4199
4200
4201static PyObject*
4202DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4203{
4204 int err, atype, flags=0;
4205 int aborted = 0;
4206
4207 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4210
4211 MYDB_BEGIN_ALLOW_THREADS;
4212#if (DBVER >= 40)
4213 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4214#else
4215 err = lock_detect(self->db_env, flags, atype, &aborted);
4216#endif
4217 MYDB_END_ALLOW_THREADS;
4218 RETURN_IF_ERR();
4219 return PyInt_FromLong(aborted);
4220}
4221
4222
4223static PyObject*
4224DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4225{
4226 int flags=0;
4227 int locker, lock_mode;
4228 DBT obj;
4229 PyObject* objobj;
4230
4231 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4232 return NULL;
4233
4234
4235 if (!make_dbt(objobj, &obj))
4236 return NULL;
4237
4238 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4239}
4240
4241
4242static PyObject*
4243DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4244{
4245 int err;
4246 u_int32_t theID;
4247
4248 if (!PyArg_ParseTuple(args, ":lock_id"))
4249 return NULL;
4250
4251 CHECK_ENV_NOT_CLOSED(self);
4252 MYDB_BEGIN_ALLOW_THREADS;
4253#if (DBVER >= 40)
4254 err = self->db_env->lock_id(self->db_env, &theID);
4255#else
4256 err = lock_id(self->db_env, &theID);
4257#endif
4258 MYDB_END_ALLOW_THREADS;
4259 RETURN_IF_ERR();
4260
4261 return PyInt_FromLong((long)theID);
4262}
4263
Gregory P. Smithac11e022007-11-05 02:56:31 +00004264#if (DBVER >= 40)
4265static PyObject*
4266DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4267{
4268 int err;
4269 u_int32_t theID;
4270
4271 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4272 return NULL;
4273
4274 CHECK_ENV_NOT_CLOSED(self);
4275 MYDB_BEGIN_ALLOW_THREADS;
4276 err = self->db_env->lock_id_free(self->db_env, theID);
4277 MYDB_END_ALLOW_THREADS;
4278 RETURN_IF_ERR();
4279 RETURN_NONE();
4280}
4281#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004282
4283static PyObject*
4284DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4285{
4286 int err;
4287 DBLockObject* dblockobj;
4288
4289 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4290 return NULL;
4291
4292 CHECK_ENV_NOT_CLOSED(self);
4293 MYDB_BEGIN_ALLOW_THREADS;
4294#if (DBVER >= 40)
4295 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4296#else
4297 err = lock_put(self->db_env, &dblockobj->lock);
4298#endif
4299 MYDB_END_ALLOW_THREADS;
4300 RETURN_IF_ERR();
4301 RETURN_NONE();
4302}
4303
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004304#if (DBVER >= 44)
4305static PyObject*
4306DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4307{
4308 int err;
4309 char *file;
4310 u_int32_t flags = 0;
4311 static char* kwnames[] = { "file", "flags", NULL};
4312
4313 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4314 &file, &flags))
4315 return NULL;
4316 CHECK_ENV_NOT_CLOSED(self);
4317
4318 MYDB_BEGIN_ALLOW_THREADS;
4319 err = self->db_env->lsn_reset(self->db_env, file, flags);
4320 MYDB_END_ALLOW_THREADS;
4321 RETURN_IF_ERR();
4322 RETURN_NONE();
4323}
4324#endif /* DBVER >= 4.4 */
4325
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004326#if (DBVER >= 40)
4327static PyObject*
4328DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4329{
4330 int err;
4331 DB_LOG_STAT* statp = NULL;
4332 PyObject* d = NULL;
4333 u_int32_t flags = 0;
4334
4335 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4336 return NULL;
4337 CHECK_ENV_NOT_CLOSED(self);
4338
4339 MYDB_BEGIN_ALLOW_THREADS;
4340 err = self->db_env->log_stat(self->db_env, &statp, flags);
4341 MYDB_END_ALLOW_THREADS;
4342 RETURN_IF_ERR();
4343
4344 /* Turn the stat structure into a dictionary */
4345 d = PyDict_New();
4346 if (d == NULL) {
4347 if (statp)
4348 free(statp);
4349 return NULL;
4350 }
4351
4352#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4353
4354 MAKE_ENTRY(magic);
4355 MAKE_ENTRY(version);
4356 MAKE_ENTRY(mode);
4357 MAKE_ENTRY(lg_bsize);
4358#if (DBVER >= 44)
4359 MAKE_ENTRY(lg_size);
4360 MAKE_ENTRY(record);
4361#endif
4362#if (DBVER <= 40)
4363 MAKE_ENTRY(lg_max);
4364#endif
4365 MAKE_ENTRY(w_mbytes);
4366 MAKE_ENTRY(w_bytes);
4367 MAKE_ENTRY(wc_mbytes);
4368 MAKE_ENTRY(wc_bytes);
4369 MAKE_ENTRY(wcount);
4370 MAKE_ENTRY(wcount_fill);
4371#if (DBVER >= 44)
4372 MAKE_ENTRY(rcount);
4373#endif
4374 MAKE_ENTRY(scount);
4375 MAKE_ENTRY(cur_file);
4376 MAKE_ENTRY(cur_offset);
4377 MAKE_ENTRY(disk_file);
4378 MAKE_ENTRY(disk_offset);
4379 MAKE_ENTRY(maxcommitperflush);
4380 MAKE_ENTRY(mincommitperflush);
4381 MAKE_ENTRY(regsize);
4382 MAKE_ENTRY(region_wait);
4383 MAKE_ENTRY(region_nowait);
4384
4385#undef MAKE_ENTRY
4386 free(statp);
4387 return d;
4388} /* DBEnv_log_stat */
4389#endif /* DBVER >= 4.0 for log_stat method */
4390
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004391
4392static PyObject*
4393DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4394{
4395 int err;
4396 DB_LOCK_STAT* sp;
4397 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004398 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004399
4400 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4401 return NULL;
4402 CHECK_ENV_NOT_CLOSED(self);
4403
4404 MYDB_BEGIN_ALLOW_THREADS;
4405#if (DBVER >= 40)
4406 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4407#else
4408#if (DBVER >= 33)
4409 err = lock_stat(self->db_env, &sp);
4410#else
4411 err = lock_stat(self->db_env, &sp, NULL);
4412#endif
4413#endif
4414 MYDB_END_ALLOW_THREADS;
4415 RETURN_IF_ERR();
4416
4417 /* Turn the stat structure into a dictionary */
4418 d = PyDict_New();
4419 if (d == NULL) {
4420 free(sp);
4421 return NULL;
4422 }
4423
4424#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4425
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004426#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004427 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004428#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004429 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004430 MAKE_ENTRY(maxlocks);
4431 MAKE_ENTRY(maxlockers);
4432 MAKE_ENTRY(maxobjects);
4433 MAKE_ENTRY(nlocks);
4434 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004435 MAKE_ENTRY(nlockers);
4436 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004437 MAKE_ENTRY(nobjects);
4438 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004439 MAKE_ENTRY(nrequests);
4440 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004441#if (DBVER < 44)
4442 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004443 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004444#else
4445 MAKE_ENTRY(lock_nowait);
4446 MAKE_ENTRY(lock_wait);
4447#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004448 MAKE_ENTRY(ndeadlocks);
4449 MAKE_ENTRY(regsize);
4450 MAKE_ENTRY(region_wait);
4451 MAKE_ENTRY(region_nowait);
4452
4453#undef MAKE_ENTRY
4454 free(sp);
4455 return d;
4456}
4457
4458
4459static PyObject*
4460DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4461{
4462 int flags=0;
4463 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004464 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004465 PyObject* list;
4466 PyObject* item = NULL;
4467
4468 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4469 return NULL;
4470
4471 CHECK_ENV_NOT_CLOSED(self);
4472 MYDB_BEGIN_ALLOW_THREADS;
4473#if (DBVER >= 40)
4474 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4475#elif (DBVER == 33)
4476 err = log_archive(self->db_env, &log_list, flags);
4477#else
4478 err = log_archive(self->db_env, &log_list, flags, NULL);
4479#endif
4480 MYDB_END_ALLOW_THREADS;
4481 RETURN_IF_ERR();
4482
Gregory P. Smithbad47452006-06-05 00:33:35 +00004483 list = PyList_New(0);
4484 if (list == NULL) {
4485 if (log_list)
4486 free(log_list);
4487 return NULL;
4488 }
4489
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004491 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4493 item = PyString_FromString (*log_list);
4494 if (item == NULL) {
4495 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004496 list = NULL;
4497 break;
4498 }
4499 PyList_Append(list, item);
4500 Py_DECREF(item);
4501 }
4502 free(log_list_start);
4503 }
4504 return list;
4505}
4506
4507
4508static PyObject*
4509DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4510{
4511 int err;
4512 DB_TXN_STAT* sp;
4513 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004514 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004515
4516 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4517 return NULL;
4518 CHECK_ENV_NOT_CLOSED(self);
4519
4520 MYDB_BEGIN_ALLOW_THREADS;
4521#if (DBVER >= 40)
4522 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4523#elif (DBVER == 33)
4524 err = txn_stat(self->db_env, &sp);
4525#else
4526 err = txn_stat(self->db_env, &sp, NULL);
4527#endif
4528 MYDB_END_ALLOW_THREADS;
4529 RETURN_IF_ERR();
4530
4531 /* Turn the stat structure into a dictionary */
4532 d = PyDict_New();
4533 if (d == NULL) {
4534 free(sp);
4535 return NULL;
4536 }
4537
4538#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004539#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004541 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004542 MAKE_ENTRY(last_txnid);
4543 MAKE_ENTRY(maxtxns);
4544 MAKE_ENTRY(nactive);
4545 MAKE_ENTRY(maxnactive);
4546 MAKE_ENTRY(nbegins);
4547 MAKE_ENTRY(naborts);
4548 MAKE_ENTRY(ncommits);
4549 MAKE_ENTRY(regsize);
4550 MAKE_ENTRY(region_wait);
4551 MAKE_ENTRY(region_nowait);
4552
4553#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004554#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004555 free(sp);
4556 return d;
4557}
4558
4559
4560static PyObject*
4561DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4562{
4563 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004564 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004565
4566 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4567 return NULL;
4568 CHECK_ENV_NOT_CLOSED(self);
4569
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004570 if (self->moduleFlags.getReturnsNone)
4571 ++oldValue;
4572 if (self->moduleFlags.cursorSetReturnsNone)
4573 ++oldValue;
4574 self->moduleFlags.getReturnsNone = (flags >= 1);
4575 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576 return PyInt_FromLong(oldValue);
4577}
4578
4579
4580/* --------------------------------------------------------------------- */
4581/* DBTxn methods */
4582
4583
4584static PyObject*
4585DBTxn_commit(DBTxnObject* self, PyObject* args)
4586{
4587 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004588 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589
4590 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4591 return NULL;
4592
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004593 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004594 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4595 "after txn_commit or txn_abort");
4596 PyErr_SetObject(DBError, t);
4597 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004598 return NULL;
4599 }
4600 txn = self->txn;
4601 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004602 MYDB_BEGIN_ALLOW_THREADS;
4603#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004604 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004606 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607#endif
4608 MYDB_END_ALLOW_THREADS;
4609 RETURN_IF_ERR();
4610 RETURN_NONE();
4611}
4612
4613static PyObject*
4614DBTxn_prepare(DBTxnObject* self, PyObject* args)
4615{
4616#if (DBVER >= 33)
4617 int err;
4618 char* gid=NULL;
4619 int gid_size=0;
4620
4621 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4622 return NULL;
4623
4624 if (gid_size != DB_XIDDATASIZE) {
4625 PyErr_SetString(PyExc_TypeError,
4626 "gid must be DB_XIDDATASIZE bytes long");
4627 return NULL;
4628 }
4629
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004630 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004631 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4632 "after txn_commit or txn_abort");
4633 PyErr_SetObject(DBError, t);
4634 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004635 return NULL;
4636 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004637 MYDB_BEGIN_ALLOW_THREADS;
4638#if (DBVER >= 40)
4639 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4640#else
4641 err = txn_prepare(self->txn, (u_int8_t*)gid);
4642#endif
4643 MYDB_END_ALLOW_THREADS;
4644 RETURN_IF_ERR();
4645 RETURN_NONE();
4646#else
4647 int err;
4648
4649 if (!PyArg_ParseTuple(args, ":prepare"))
4650 return NULL;
4651
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004652 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004653 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4654 "after txn_commit or txn_abort");
4655 PyErr_SetObject(DBError, t);
4656 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004657 return NULL;
4658 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004659 MYDB_BEGIN_ALLOW_THREADS;
4660 err = txn_prepare(self->txn);
4661 MYDB_END_ALLOW_THREADS;
4662 RETURN_IF_ERR();
4663 RETURN_NONE();
4664#endif
4665}
4666
4667
4668static PyObject*
4669DBTxn_abort(DBTxnObject* self, PyObject* args)
4670{
4671 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004672 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004673
4674 if (!PyArg_ParseTuple(args, ":abort"))
4675 return NULL;
4676
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004677 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004678 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4679 "after txn_commit or txn_abort");
4680 PyErr_SetObject(DBError, t);
4681 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004682 return NULL;
4683 }
4684 txn = self->txn;
4685 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004686 MYDB_BEGIN_ALLOW_THREADS;
4687#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004688 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004689#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004690 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691#endif
4692 MYDB_END_ALLOW_THREADS;
4693 RETURN_IF_ERR();
4694 RETURN_NONE();
4695}
4696
4697
4698static PyObject*
4699DBTxn_id(DBTxnObject* self, PyObject* args)
4700{
4701 int id;
4702
4703 if (!PyArg_ParseTuple(args, ":id"))
4704 return NULL;
4705
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004706 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004707 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4708 "after txn_commit or txn_abort");
4709 PyErr_SetObject(DBError, t);
4710 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004711 return NULL;
4712 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004713 MYDB_BEGIN_ALLOW_THREADS;
4714#if (DBVER >= 40)
4715 id = self->txn->id(self->txn);
4716#else
4717 id = txn_id(self->txn);
4718#endif
4719 MYDB_END_ALLOW_THREADS;
4720 return PyInt_FromLong(id);
4721}
4722
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004723#if (DBVER >= 43)
4724/* --------------------------------------------------------------------- */
4725/* DBSequence methods */
4726
4727
4728static PyObject*
4729DBSequence_close(DBSequenceObject* self, PyObject* args)
4730{
4731 int err, flags=0;
4732 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4733 return NULL;
4734 CHECK_SEQUENCE_NOT_CLOSED(self)
4735
4736 MYDB_BEGIN_ALLOW_THREADS
4737 err = self->sequence->close(self->sequence, flags);
4738 self->sequence = NULL;
4739 MYDB_END_ALLOW_THREADS
4740
4741 RETURN_IF_ERR();
4742
4743 RETURN_NONE();
4744}
4745
4746static PyObject*
4747DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4748{
4749 int err, flags = 0;
4750 int delta = 1;
4751 db_seq_t value;
4752 PyObject *txnobj = NULL;
4753 DB_TXN *txn = NULL;
4754 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4755 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4756 return NULL;
4757 CHECK_SEQUENCE_NOT_CLOSED(self)
4758
4759 if (!checkTxnObj(txnobj, &txn))
4760 return NULL;
4761
4762 MYDB_BEGIN_ALLOW_THREADS
4763 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4764 MYDB_END_ALLOW_THREADS
4765
4766 RETURN_IF_ERR();
4767 return PyLong_FromLongLong(value);
4768
4769}
4770
4771static PyObject*
4772DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4773{
4774 if (!PyArg_ParseTuple(args,":get_dbp"))
4775 return NULL;
4776 CHECK_SEQUENCE_NOT_CLOSED(self)
4777 Py_INCREF(self->mydb);
4778 return (PyObject* )self->mydb;
4779}
4780
4781static PyObject*
4782DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4783{
4784 int err;
4785 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00004786 PyObject *retval = NULL;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004787 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004788 CHECK_SEQUENCE_NOT_CLOSED(self)
4789 MYDB_BEGIN_ALLOW_THREADS
4790 err = self->sequence->get_key(self->sequence, &key);
4791 MYDB_END_ALLOW_THREADS
4792
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004793 if (!err)
4794 retval = PyString_FromStringAndSize(key.data, key.size);
4795
4796 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004797 RETURN_IF_ERR();
4798
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004799 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004800}
4801
4802static PyObject*
4803DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4804{
4805 int err;
4806 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004807 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004808 return NULL;
4809 CHECK_SEQUENCE_NOT_CLOSED(self)
4810
4811 MYDB_BEGIN_ALLOW_THREADS
4812 err = self->sequence->initial_value(self->sequence, value);
4813 MYDB_END_ALLOW_THREADS
4814
4815 RETURN_IF_ERR();
4816
4817 RETURN_NONE();
4818}
4819
4820static PyObject*
4821DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4822{
4823 int err, flags = 0;
4824 PyObject* keyobj;
4825 PyObject *txnobj = NULL;
4826 DB_TXN *txn = NULL;
4827 DBT key;
4828
4829 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004830 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004831 return NULL;
4832
4833 if (!checkTxnObj(txnobj, &txn))
4834 return NULL;
4835
4836 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4837 return NULL;
4838
4839 MYDB_BEGIN_ALLOW_THREADS
4840 err = self->sequence->open(self->sequence, txn, &key, flags);
4841 MYDB_END_ALLOW_THREADS
4842
4843 CLEAR_DBT(key);
4844 RETURN_IF_ERR();
4845
4846 RETURN_NONE();
4847}
4848
4849static PyObject*
4850DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4851{
4852 int err, flags = 0;
4853 PyObject *txnobj = NULL;
4854 DB_TXN *txn = NULL;
4855
4856 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004858 return NULL;
4859
4860 if (!checkTxnObj(txnobj, &txn))
4861 return NULL;
4862
4863 CHECK_SEQUENCE_NOT_CLOSED(self)
4864
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err = self->sequence->remove(self->sequence, txn, flags);
4867 MYDB_END_ALLOW_THREADS
4868
4869 RETURN_IF_ERR();
4870 RETURN_NONE();
4871}
4872
4873static PyObject*
4874DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4875{
4876 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004877 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004878 return NULL;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err = self->sequence->set_cachesize(self->sequence, size);
4883 MYDB_END_ALLOW_THREADS
4884
4885 RETURN_IF_ERR();
4886 RETURN_NONE();
4887}
4888
4889static PyObject*
4890DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4891{
4892 int err, size;
4893 if (!PyArg_ParseTuple(args,":get_cachesize"))
4894 return NULL;
4895 CHECK_SEQUENCE_NOT_CLOSED(self)
4896
4897 MYDB_BEGIN_ALLOW_THREADS
4898 err = self->sequence->get_cachesize(self->sequence, &size);
4899 MYDB_END_ALLOW_THREADS
4900
4901 RETURN_IF_ERR();
4902 return PyInt_FromLong(size);
4903}
4904
4905static PyObject*
4906DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4907{
4908 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004909 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004910 return NULL;
4911 CHECK_SEQUENCE_NOT_CLOSED(self)
4912
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err = self->sequence->set_flags(self->sequence, flags);
4915 MYDB_END_ALLOW_THREADS
4916
4917 RETURN_IF_ERR();
4918 RETURN_NONE();
4919
4920}
4921
4922static PyObject*
4923DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4924{
4925 unsigned int flags;
4926 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004927 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004928 return NULL;
4929 CHECK_SEQUENCE_NOT_CLOSED(self)
4930
4931 MYDB_BEGIN_ALLOW_THREADS
4932 err = self->sequence->get_flags(self->sequence, &flags);
4933 MYDB_END_ALLOW_THREADS
4934
4935 RETURN_IF_ERR();
4936 return PyInt_FromLong((int)flags);
4937}
4938
4939static PyObject*
4940DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4941{
4942 int err;
4943 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004944 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004945 return NULL;
4946 CHECK_SEQUENCE_NOT_CLOSED(self)
4947
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err = self->sequence->set_range(self->sequence, min, max);
4950 MYDB_END_ALLOW_THREADS
4951
4952 RETURN_IF_ERR();
4953 RETURN_NONE();
4954}
4955
4956static PyObject*
4957DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4958{
4959 int err;
4960 db_seq_t min, max;
4961 if (!PyArg_ParseTuple(args,":get_range"))
4962 return NULL;
4963 CHECK_SEQUENCE_NOT_CLOSED(self)
4964
4965 MYDB_BEGIN_ALLOW_THREADS
4966 err = self->sequence->get_range(self->sequence, &min, &max);
4967 MYDB_END_ALLOW_THREADS
4968
4969 RETURN_IF_ERR();
4970 return Py_BuildValue("(LL)", min, max);
4971}
4972
4973static PyObject*
4974DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4975{
4976 int err, flags = 0;
4977 DB_SEQUENCE_STAT* sp = NULL;
4978 PyObject* dict_stat;
4979 static char* kwnames[] = {"flags", NULL };
4980 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self);
4983
4984 MYDB_BEGIN_ALLOW_THREADS;
4985 err = self->sequence->stat(self->sequence, &sp, flags);
4986 MYDB_END_ALLOW_THREADS;
4987 RETURN_IF_ERR();
4988
4989 if ((dict_stat = PyDict_New()) == NULL) {
4990 free(sp);
4991 return NULL;
4992 }
4993
4994
4995#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4996#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4997
4998 MAKE_INT_ENTRY(wait);
4999 MAKE_INT_ENTRY(nowait);
5000 MAKE_LONG_LONG_ENTRY(current);
5001 MAKE_LONG_LONG_ENTRY(value);
5002 MAKE_LONG_LONG_ENTRY(last_value);
5003 MAKE_LONG_LONG_ENTRY(min);
5004 MAKE_LONG_LONG_ENTRY(max);
5005 MAKE_INT_ENTRY(cache_size);
5006 MAKE_INT_ENTRY(flags);
5007
5008#undef MAKE_INT_ENTRY
5009#undef MAKE_LONG_LONG_ENTRY
5010
5011 free(sp);
5012 return dict_stat;
5013}
5014#endif
5015
5016
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005017/* --------------------------------------------------------------------- */
5018/* Method definition tables and type objects */
5019
5020static PyMethodDef DB_methods[] = {
5021 {"append", (PyCFunction)DB_append, METH_VARARGS},
5022#if (DBVER >= 33)
5023 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5024#endif
5025 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005026 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5027 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005028 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5029 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5030 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5031 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005032#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005033 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005034#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005035 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5036 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5037 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5038 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5039 {"join", (PyCFunction)DB_join, METH_VARARGS},
5040 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5041 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5042 {"items", (PyCFunction)DB_items, METH_VARARGS},
5043 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5044 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5045 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5046 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5047 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5048 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005049#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005050 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005051#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005052 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005053#if (DBVER >= 41)
5054 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5055#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005056 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5057 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5058 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5059 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5060 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5061 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5062 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5063 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5064 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005065 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005066 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005067 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5068#if (DBVER >= 33)
5069 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5070#endif
5071 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5072 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5073 {"values", (PyCFunction)DB_values, METH_VARARGS},
5074 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5075 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5076 {NULL, NULL} /* sentinel */
5077};
5078
5079
5080static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005081 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005082 (binaryfunc)DB_subscript, /*mp_subscript*/
5083 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5084};
5085
5086
5087static PyMethodDef DBCursor_methods[] = {
5088 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5089 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5090 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5091 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5092 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5093 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5094 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005095#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005096 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005097#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005098 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5099 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5100 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5101 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5102 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5103 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5104 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5105 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005106 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005107 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005108 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5109 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5110 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5111 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5112 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5113 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5114 {NULL, NULL} /* sentinel */
5115};
5116
5117
5118static PyMethodDef DBEnv_methods[] = {
5119 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5120 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5121 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005122#if (DBVER >= 41)
5123 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5124 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5125 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5126#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005127#if (DBVER >= 40)
5128 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5129#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005130 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005131 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5132 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005133 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005134 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5135 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5136 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005137#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005138 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005139#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005140 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005141#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005142 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005143#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005144 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5145 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5146 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005147 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5148 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5149 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5150 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5151 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5152 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005153 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5155 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5156 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00005157#if (DBVER >= 40)
5158 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5159#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005160 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5161 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5162 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005163#if (DBVER >= 40)
5164 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5165#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005166#if (DBVER >= 44)
5167 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5168#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005169 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5170 {NULL, NULL} /* sentinel */
5171};
5172
5173
5174static PyMethodDef DBTxn_methods[] = {
5175 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5176 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5177 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5178 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5179 {NULL, NULL} /* sentinel */
5180};
5181
5182
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005183#if (DBVER >= 43)
5184static PyMethodDef DBSequence_methods[] = {
5185 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5186 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5187 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5188 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005189 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5190 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5191 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5192 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5193 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5194 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5195 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5196 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5197 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5198 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5199 {NULL, NULL} /* sentinel */
5200};
5201#endif
5202
5203
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005204static PyObject*
5205DB_getattr(DBObject* self, char *name)
5206{
5207 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5208}
5209
5210
5211static PyObject*
5212DBEnv_getattr(DBEnvObject* self, char *name)
5213{
5214 if (!strcmp(name, "db_home")) {
5215 CHECK_ENV_NOT_CLOSED(self);
5216 if (self->db_env->db_home == NULL) {
5217 RETURN_NONE();
5218 }
5219 return PyString_FromString(self->db_env->db_home);
5220 }
5221
5222 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5223}
5224
5225
5226static PyObject*
5227DBCursor_getattr(DBCursorObject* self, char *name)
5228{
5229 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5230}
5231
5232static PyObject*
5233DBTxn_getattr(DBTxnObject* self, char *name)
5234{
5235 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5236}
5237
5238static PyObject*
5239DBLock_getattr(DBLockObject* self, char *name)
5240{
5241 return NULL;
5242}
5243
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005244#if (DBVER >= 43)
5245static PyObject*
5246DBSequence_getattr(DBSequenceObject* self, char *name)
5247{
5248 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5249}
5250#endif
5251
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005252statichere PyTypeObject DB_Type = {
5253 PyObject_HEAD_INIT(NULL)
5254 0, /*ob_size*/
5255 "DB", /*tp_name*/
5256 sizeof(DBObject), /*tp_basicsize*/
5257 0, /*tp_itemsize*/
5258 /* methods */
5259 (destructor)DB_dealloc, /*tp_dealloc*/
5260 0, /*tp_print*/
5261 (getattrfunc)DB_getattr, /*tp_getattr*/
5262 0, /*tp_setattr*/
5263 0, /*tp_compare*/
5264 0, /*tp_repr*/
5265 0, /*tp_as_number*/
5266 0, /*tp_as_sequence*/
5267 &DB_mapping,/*tp_as_mapping*/
5268 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005269 0, /* tp_call */
5270 0, /* tp_str */
5271 0, /* tp_getattro */
5272 0, /* tp_setattro */
5273 0, /* tp_as_buffer */
5274 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5275 0, /* tp_doc */
5276 0, /* tp_traverse */
5277 0, /* tp_clear */
5278 0, /* tp_richcompare */
5279 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005280};
5281
5282
5283statichere PyTypeObject DBCursor_Type = {
5284 PyObject_HEAD_INIT(NULL)
5285 0, /*ob_size*/
5286 "DBCursor", /*tp_name*/
5287 sizeof(DBCursorObject), /*tp_basicsize*/
5288 0, /*tp_itemsize*/
5289 /* methods */
5290 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5291 0, /*tp_print*/
5292 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5293 0, /*tp_setattr*/
5294 0, /*tp_compare*/
5295 0, /*tp_repr*/
5296 0, /*tp_as_number*/
5297 0, /*tp_as_sequence*/
5298 0, /*tp_as_mapping*/
5299 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005300 0, /* tp_call */
5301 0, /* tp_str */
5302 0, /* tp_getattro */
5303 0, /* tp_setattro */
5304 0, /* tp_as_buffer */
5305 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5306 0, /* tp_doc */
5307 0, /* tp_traverse */
5308 0, /* tp_clear */
5309 0, /* tp_richcompare */
5310 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005311};
5312
5313
5314statichere PyTypeObject DBEnv_Type = {
5315 PyObject_HEAD_INIT(NULL)
5316 0, /*ob_size*/
5317 "DBEnv", /*tp_name*/
5318 sizeof(DBEnvObject), /*tp_basicsize*/
5319 0, /*tp_itemsize*/
5320 /* methods */
5321 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5322 0, /*tp_print*/
5323 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5324 0, /*tp_setattr*/
5325 0, /*tp_compare*/
5326 0, /*tp_repr*/
5327 0, /*tp_as_number*/
5328 0, /*tp_as_sequence*/
5329 0, /*tp_as_mapping*/
5330 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005331 0, /* tp_call */
5332 0, /* tp_str */
5333 0, /* tp_getattro */
5334 0, /* tp_setattro */
5335 0, /* tp_as_buffer */
5336 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5337 0, /* tp_doc */
5338 0, /* tp_traverse */
5339 0, /* tp_clear */
5340 0, /* tp_richcompare */
5341 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005342};
5343
5344statichere PyTypeObject DBTxn_Type = {
5345 PyObject_HEAD_INIT(NULL)
5346 0, /*ob_size*/
5347 "DBTxn", /*tp_name*/
5348 sizeof(DBTxnObject), /*tp_basicsize*/
5349 0, /*tp_itemsize*/
5350 /* methods */
5351 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5352 0, /*tp_print*/
5353 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5354 0, /*tp_setattr*/
5355 0, /*tp_compare*/
5356 0, /*tp_repr*/
5357 0, /*tp_as_number*/
5358 0, /*tp_as_sequence*/
5359 0, /*tp_as_mapping*/
5360 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005361 0, /* tp_call */
5362 0, /* tp_str */
5363 0, /* tp_getattro */
5364 0, /* tp_setattro */
5365 0, /* tp_as_buffer */
5366 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5367 0, /* tp_doc */
5368 0, /* tp_traverse */
5369 0, /* tp_clear */
5370 0, /* tp_richcompare */
5371 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005372};
5373
5374
5375statichere PyTypeObject DBLock_Type = {
5376 PyObject_HEAD_INIT(NULL)
5377 0, /*ob_size*/
5378 "DBLock", /*tp_name*/
5379 sizeof(DBLockObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DBLock_dealloc, /*tp_dealloc*/
5383 0, /*tp_print*/
5384 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5391 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005392 0, /* tp_call */
5393 0, /* tp_str */
5394 0, /* tp_getattro */
5395 0, /* tp_setattro */
5396 0, /* tp_as_buffer */
5397 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5398 0, /* tp_doc */
5399 0, /* tp_traverse */
5400 0, /* tp_clear */
5401 0, /* tp_richcompare */
5402 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005403};
5404
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005405#if (DBVER >= 43)
5406statichere PyTypeObject DBSequence_Type = {
5407 PyObject_HEAD_INIT(NULL)
5408 0, /*ob_size*/
5409 "DBSequence", /*tp_name*/
5410 sizeof(DBSequenceObject), /*tp_basicsize*/
5411 0, /*tp_itemsize*/
5412 /* methods */
5413 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5414 0, /*tp_print*/
5415 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5416 0, /*tp_setattr*/
5417 0, /*tp_compare*/
5418 0, /*tp_repr*/
5419 0, /*tp_as_number*/
5420 0, /*tp_as_sequence*/
5421 0, /*tp_as_mapping*/
5422 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005423 0, /* tp_call */
5424 0, /* tp_str */
5425 0, /* tp_getattro */
5426 0, /* tp_setattro */
5427 0, /* tp_as_buffer */
5428 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5429 0, /* tp_doc */
5430 0, /* tp_traverse */
5431 0, /* tp_clear */
5432 0, /* tp_richcompare */
5433 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005434};
5435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005436
5437/* --------------------------------------------------------------------- */
5438/* Module-level functions */
5439
5440static PyObject*
5441DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5442{
5443 PyObject* dbenvobj = NULL;
5444 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005445 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005446
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5448 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005449 return NULL;
5450 if (dbenvobj == Py_None)
5451 dbenvobj = NULL;
5452 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5453 makeTypeError("DBEnv", dbenvobj);
5454 return NULL;
5455 }
5456
5457 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5458}
5459
5460
5461static PyObject*
5462DBEnv_construct(PyObject* self, PyObject* args)
5463{
5464 int flags = 0;
5465 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5466 return (PyObject* )newDBEnvObject(flags);
5467}
5468
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005469#if (DBVER >= 43)
5470static PyObject*
5471DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5472{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005473 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005474 int flags = 0;
5475 static char* kwnames[] = { "db", "flags", NULL};
5476
5477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5478 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005479 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005480 makeTypeError("DB", dbobj);
5481 return NULL;
5482 }
5483 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5484}
5485#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005486
5487static char bsddb_version_doc[] =
5488"Returns a tuple of major, minor, and patch release numbers of the\n\
5489underlying DB library.";
5490
5491static PyObject*
5492bsddb_version(PyObject* self, PyObject* args)
5493{
5494 int major, minor, patch;
5495
5496 if (!PyArg_ParseTuple(args, ":version"))
5497 return NULL;
5498 db_version(&major, &minor, &patch);
5499 return Py_BuildValue("(iii)", major, minor, patch);
5500}
5501
5502
5503/* List of functions defined in the module */
5504
5505static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005506 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5507 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5508#if (DBVER >= 43)
5509 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5510#endif
5511 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005512 {NULL, NULL} /* sentinel */
5513};
5514
Gregory P. Smith39250532007-10-09 06:02:21 +00005515/* API structure */
5516static BSDDB_api bsddb_api;
5517
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005518
5519/* --------------------------------------------------------------------- */
5520/* Module initialization */
5521
5522
5523/* Convenience routine to export an integer value.
5524 * Errors are silently ignored, for better or for worse...
5525 */
5526#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5527
Gregory P. Smith41631e82003-09-21 00:08:14 +00005528#define MODULE_NAME_MAX_LEN 11
5529static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005530
5531DL_EXPORT(void) init_bsddb(void)
5532{
5533 PyObject* m;
5534 PyObject* d;
5535 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5536 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5537 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005538 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005539
5540 /* Initialize the type of the new type objects here; doing it here
5541 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00005542 Py_TYPE(&DB_Type) = &PyType_Type;
5543 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5544 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5545 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5546 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005547#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00005548 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005549#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005550
5551
Mark Hammonda69d4092003-04-22 23:13:27 +00005552#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005553 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005554 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005555#endif
5556
5557 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005558 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005559 if (m == NULL)
5560 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005561
5562 /* Add some symbolic constants to the module */
5563 d = PyModule_GetDict(m);
5564 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5565 PyDict_SetItemString(d, "cvsid", cvsid_s);
5566 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5567 Py_DECREF(pybsddb_version_s);
5568 pybsddb_version_s = NULL;
5569 Py_DECREF(cvsid_s);
5570 cvsid_s = NULL;
5571 Py_DECREF(db_version_s);
5572 db_version_s = NULL;
5573
5574 ADD_INT(d, DB_VERSION_MAJOR);
5575 ADD_INT(d, DB_VERSION_MINOR);
5576 ADD_INT(d, DB_VERSION_PATCH);
5577
5578 ADD_INT(d, DB_MAX_PAGES);
5579 ADD_INT(d, DB_MAX_RECORDS);
5580
Gregory P. Smith41631e82003-09-21 00:08:14 +00005581#if (DBVER >= 42)
5582 ADD_INT(d, DB_RPCCLIENT);
5583#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005584 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005585 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5586 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5587#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005588 ADD_INT(d, DB_XA_CREATE);
5589
5590 ADD_INT(d, DB_CREATE);
5591 ADD_INT(d, DB_NOMMAP);
5592 ADD_INT(d, DB_THREAD);
5593
5594 ADD_INT(d, DB_FORCE);
5595 ADD_INT(d, DB_INIT_CDB);
5596 ADD_INT(d, DB_INIT_LOCK);
5597 ADD_INT(d, DB_INIT_LOG);
5598 ADD_INT(d, DB_INIT_MPOOL);
5599 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005600 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005601
5602 ADD_INT(d, DB_RECOVER);
5603 ADD_INT(d, DB_RECOVER_FATAL);
5604 ADD_INT(d, DB_TXN_NOSYNC);
5605 ADD_INT(d, DB_USE_ENVIRON);
5606 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5607
5608 ADD_INT(d, DB_LOCKDOWN);
5609 ADD_INT(d, DB_PRIVATE);
5610 ADD_INT(d, DB_SYSTEM_MEM);
5611
5612 ADD_INT(d, DB_TXN_SYNC);
5613 ADD_INT(d, DB_TXN_NOWAIT);
5614
5615 ADD_INT(d, DB_EXCL);
5616 ADD_INT(d, DB_FCNTL_LOCKING);
5617 ADD_INT(d, DB_ODDFILESIZE);
5618 ADD_INT(d, DB_RDWRMASTER);
5619 ADD_INT(d, DB_RDONLY);
5620 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005621 ADD_INT(d, DB_EXTENT);
5622 ADD_INT(d, DB_CDB_ALLDB);
5623 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005624 ADD_INT(d, DB_UPGRADE);
5625
5626 ADD_INT(d, DB_AGGRESSIVE);
5627 ADD_INT(d, DB_NOORDERCHK);
5628 ADD_INT(d, DB_ORDERCHKONLY);
5629 ADD_INT(d, DB_PR_PAGE);
5630#if ! (DBVER >= 33)
5631 ADD_INT(d, DB_VRFY_FLAGMASK);
5632 ADD_INT(d, DB_PR_HEADERS);
5633#endif
5634 ADD_INT(d, DB_PR_RECOVERYTEST);
5635 ADD_INT(d, DB_SALVAGE);
5636
5637 ADD_INT(d, DB_LOCK_NORUN);
5638 ADD_INT(d, DB_LOCK_DEFAULT);
5639 ADD_INT(d, DB_LOCK_OLDEST);
5640 ADD_INT(d, DB_LOCK_RANDOM);
5641 ADD_INT(d, DB_LOCK_YOUNGEST);
5642#if (DBVER >= 33)
5643 ADD_INT(d, DB_LOCK_MAXLOCKS);
5644 ADD_INT(d, DB_LOCK_MINLOCKS);
5645 ADD_INT(d, DB_LOCK_MINWRITE);
5646#endif
5647
5648
5649#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005650 /* docs say to use zero instead */
5651 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005652#else
5653 ADD_INT(d, DB_LOCK_CONFLICT);
5654#endif
5655
5656 ADD_INT(d, DB_LOCK_DUMP);
5657 ADD_INT(d, DB_LOCK_GET);
5658 ADD_INT(d, DB_LOCK_INHERIT);
5659 ADD_INT(d, DB_LOCK_PUT);
5660 ADD_INT(d, DB_LOCK_PUT_ALL);
5661 ADD_INT(d, DB_LOCK_PUT_OBJ);
5662
5663 ADD_INT(d, DB_LOCK_NG);
5664 ADD_INT(d, DB_LOCK_READ);
5665 ADD_INT(d, DB_LOCK_WRITE);
5666 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005667 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005668 ADD_INT(d, DB_LOCK_IWRITE);
5669 ADD_INT(d, DB_LOCK_IREAD);
5670 ADD_INT(d, DB_LOCK_IWR);
5671#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005672#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005674#else
5675 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5676#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005677 ADD_INT(d, DB_LOCK_WWRITE);
5678#endif
5679
5680 ADD_INT(d, DB_LOCK_RECORD);
5681 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005683#if (DBVER >= 33)
5684 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5685#endif
5686
5687 ADD_INT(d, DB_LOCK_NOWAIT);
5688 ADD_INT(d, DB_LOCK_RECORD);
5689 ADD_INT(d, DB_LOCK_UPGRADE);
5690
5691#if (DBVER >= 33)
5692 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005693#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005694 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005695#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005696 ADD_INT(d, DB_LSTAT_FREE);
5697 ADD_INT(d, DB_LSTAT_HELD);
5698#if (DBVER == 33)
5699 ADD_INT(d, DB_LSTAT_NOGRANT);
5700#endif
5701 ADD_INT(d, DB_LSTAT_PENDING);
5702 ADD_INT(d, DB_LSTAT_WAITING);
5703#endif
5704
5705 ADD_INT(d, DB_ARCH_ABS);
5706 ADD_INT(d, DB_ARCH_DATA);
5707 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005708#if (DBVER >= 42)
5709 ADD_INT(d, DB_ARCH_REMOVE);
5710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005711
5712 ADD_INT(d, DB_BTREE);
5713 ADD_INT(d, DB_HASH);
5714 ADD_INT(d, DB_RECNO);
5715 ADD_INT(d, DB_QUEUE);
5716 ADD_INT(d, DB_UNKNOWN);
5717
5718 ADD_INT(d, DB_DUP);
5719 ADD_INT(d, DB_DUPSORT);
5720 ADD_INT(d, DB_RECNUM);
5721 ADD_INT(d, DB_RENUMBER);
5722 ADD_INT(d, DB_REVSPLITOFF);
5723 ADD_INT(d, DB_SNAPSHOT);
5724
5725 ADD_INT(d, DB_JOIN_NOSORT);
5726
5727 ADD_INT(d, DB_AFTER);
5728 ADD_INT(d, DB_APPEND);
5729 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005730#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005731 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005732#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005733#if (DBVER >= 41)
5734 _addIntToDict(d, "DB_CHECKPOINT", 0);
5735#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005736 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005737 ADD_INT(d, DB_CURLSN);
5738#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005739#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005740 ADD_INT(d, DB_COMMIT);
5741#endif
5742 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005743 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005744 ADD_INT(d, DB_CURRENT);
5745#if (DBVER >= 33)
5746 ADD_INT(d, DB_FAST_STAT);
5747#endif
5748 ADD_INT(d, DB_FIRST);
5749 ADD_INT(d, DB_FLUSH);
5750 ADD_INT(d, DB_GET_BOTH);
5751 ADD_INT(d, DB_GET_RECNO);
5752 ADD_INT(d, DB_JOIN_ITEM);
5753 ADD_INT(d, DB_KEYFIRST);
5754 ADD_INT(d, DB_KEYLAST);
5755 ADD_INT(d, DB_LAST);
5756 ADD_INT(d, DB_NEXT);
5757 ADD_INT(d, DB_NEXT_DUP);
5758 ADD_INT(d, DB_NEXT_NODUP);
5759 ADD_INT(d, DB_NODUPDATA);
5760 ADD_INT(d, DB_NOOVERWRITE);
5761 ADD_INT(d, DB_NOSYNC);
5762 ADD_INT(d, DB_POSITION);
5763 ADD_INT(d, DB_PREV);
5764 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005765#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005766 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005767#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005768 ADD_INT(d, DB_SET);
5769 ADD_INT(d, DB_SET_RANGE);
5770 ADD_INT(d, DB_SET_RECNO);
5771 ADD_INT(d, DB_WRITECURSOR);
5772
5773 ADD_INT(d, DB_OPFLAGS_MASK);
5774 ADD_INT(d, DB_RMW);
5775#if (DBVER >= 33)
5776 ADD_INT(d, DB_DIRTY_READ);
5777 ADD_INT(d, DB_MULTIPLE);
5778 ADD_INT(d, DB_MULTIPLE_KEY);
5779#endif
5780
Gregory P. Smith29602d22006-01-24 09:46:48 +00005781#if (DBVER >= 44)
5782 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5783 ADD_INT(d, DB_READ_COMMITTED);
5784#endif
5785
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005786#if (DBVER >= 33)
5787 ADD_INT(d, DB_DONOTINDEX);
5788#endif
5789
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005790#if (DBVER >= 41)
5791 _addIntToDict(d, "DB_INCOMPLETE", 0);
5792#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005793 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005794#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005795 ADD_INT(d, DB_KEYEMPTY);
5796 ADD_INT(d, DB_KEYEXIST);
5797 ADD_INT(d, DB_LOCK_DEADLOCK);
5798 ADD_INT(d, DB_LOCK_NOTGRANTED);
5799 ADD_INT(d, DB_NOSERVER);
5800 ADD_INT(d, DB_NOSERVER_HOME);
5801 ADD_INT(d, DB_NOSERVER_ID);
5802 ADD_INT(d, DB_NOTFOUND);
5803 ADD_INT(d, DB_OLD_VERSION);
5804 ADD_INT(d, DB_RUNRECOVERY);
5805 ADD_INT(d, DB_VERIFY_BAD);
5806#if (DBVER >= 33)
5807 ADD_INT(d, DB_PAGE_NOTFOUND);
5808 ADD_INT(d, DB_SECONDARY_BAD);
5809#endif
5810#if (DBVER >= 40)
5811 ADD_INT(d, DB_STAT_CLEAR);
5812 ADD_INT(d, DB_REGION_INIT);
5813 ADD_INT(d, DB_NOLOCKING);
5814 ADD_INT(d, DB_YIELDCPU);
5815 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5816 ADD_INT(d, DB_NOPANIC);
5817#endif
5818
Gregory P. Smithaae141a2007-11-01 21:08:14 +00005819#ifdef DB_REGISTER
5820 ADD_INT(d, DB_REGISTER);
5821#endif
5822
Gregory P. Smith41631e82003-09-21 00:08:14 +00005823#if (DBVER >= 42)
5824 ADD_INT(d, DB_TIME_NOTGRANTED);
5825 ADD_INT(d, DB_TXN_NOT_DURABLE);
5826 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5827 ADD_INT(d, DB_LOG_AUTOREMOVE);
5828 ADD_INT(d, DB_DIRECT_LOG);
5829 ADD_INT(d, DB_DIRECT_DB);
5830 ADD_INT(d, DB_INIT_REP);
5831 ADD_INT(d, DB_ENCRYPT);
5832 ADD_INT(d, DB_CHKSUM);
5833#endif
5834
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005835#if (DBVER >= 43)
5836 ADD_INT(d, DB_LOG_INMEMORY);
5837 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005838 ADD_INT(d, DB_SEQ_DEC);
5839 ADD_INT(d, DB_SEQ_INC);
5840 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005841#endif
5842
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005843#if (DBVER >= 41)
5844 ADD_INT(d, DB_ENCRYPT_AES);
5845 ADD_INT(d, DB_AUTO_COMMIT);
5846#else
5847 /* allow berkeleydb 4.1 aware apps to run on older versions */
5848 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5849#endif
5850
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005851 ADD_INT(d, EINVAL);
5852 ADD_INT(d, EACCES);
5853 ADD_INT(d, ENOSPC);
5854 ADD_INT(d, ENOMEM);
5855 ADD_INT(d, EAGAIN);
5856 ADD_INT(d, EBUSY);
5857 ADD_INT(d, EEXIST);
5858 ADD_INT(d, ENOENT);
5859 ADD_INT(d, EPERM);
5860
Barry Warsaw1baa9822003-03-31 19:51:29 +00005861#if (DBVER >= 40)
5862 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5863 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5864#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005865
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005866 /* The exception name must be correct for pickled exception *
5867 * objects to unpickle properly. */
5868#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5869#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5870#else
5871#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5872#endif
5873
5874 /* All the rest of the exceptions derive only from DBError */
5875#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5876 PyDict_SetItemString(d, #name, name)
5877
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005878 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005879 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5880 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881
Gregory P. Smithe9477062005-06-04 06:46:59 +00005882 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5883 * from both DBError and KeyError, since the API only supports
5884 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005885 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005886 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5887 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005888 Py_file_input, d, d);
5889 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005890 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005891 PyDict_DelItemString(d, "KeyError");
5892
5893
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005894#if !INCOMPLETE_IS_WARNING
5895 MAKE_EX(DBIncompleteError);
5896#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005897 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005898 MAKE_EX(DBKeyEmptyError);
5899 MAKE_EX(DBKeyExistError);
5900 MAKE_EX(DBLockDeadlockError);
5901 MAKE_EX(DBLockNotGrantedError);
5902 MAKE_EX(DBOldVersionError);
5903 MAKE_EX(DBRunRecoveryError);
5904 MAKE_EX(DBVerifyBadError);
5905 MAKE_EX(DBNoServerError);
5906 MAKE_EX(DBNoServerHomeError);
5907 MAKE_EX(DBNoServerIDError);
5908#if (DBVER >= 33)
5909 MAKE_EX(DBPageNotFoundError);
5910 MAKE_EX(DBSecondaryBadError);
5911#endif
5912
5913 MAKE_EX(DBInvalidArgError);
5914 MAKE_EX(DBAccessError);
5915 MAKE_EX(DBNoSpaceError);
5916 MAKE_EX(DBNoMemoryError);
5917 MAKE_EX(DBAgainError);
5918 MAKE_EX(DBBusyError);
5919 MAKE_EX(DBFileExistsError);
5920 MAKE_EX(DBNoSuchFileError);
5921 MAKE_EX(DBPermissionsError);
5922
5923#undef MAKE_EX
5924
Gregory P. Smith39250532007-10-09 06:02:21 +00005925 /* Initiliase the C API structure and add it to the module */
5926 bsddb_api.db_type = &DB_Type;
5927 bsddb_api.dbcursor_type = &DBCursor_Type;
5928 bsddb_api.dbenv_type = &DBEnv_Type;
5929 bsddb_api.dbtxn_type = &DBTxn_Type;
5930 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005931#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00005932 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005933#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00005934 bsddb_api.makeDBError = makeDBError;
5935
5936 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5937 PyDict_SetItemString(d, "api", py_api);
5938 Py_DECREF(py_api);
5939
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005940 /* Check for errors */
5941 if (PyErr_Occurred()) {
5942 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005943 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005944 }
5945}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005946
5947/* allow this module to be named _pybsddb so that it can be installed
5948 * and imported on top of python >= 2.3 that includes its own older
5949 * copy of the library named _bsddb without importing the old version. */
5950DL_EXPORT(void) init_pybsddb(void)
5951{
5952 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5953 init_bsddb();
5954}