blob: f40743493c3723ec1065e812df68df9b3612f6f6 [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) {
827 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000828 /* If the underlying database has been closed, we don't
829 need to do anything. If the environment has been closed
830 we need to leak, as BerkeleyDB will crash trying to access
831 the environment. There was an exception when the
832 user closed the environment even though there still was
833 a database open. */
834 if (self->mydb->db && self->mydb->myenvobj &&
835 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000836 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000837 self->dbc = NULL;
838 MYDB_END_ALLOW_THREADS;
839 }
840 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000841 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842}
843
844
845static DBEnvObject*
846newDBEnvObject(int flags)
847{
848 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000849 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 if (self == NULL)
851 return NULL;
852
853 self->closed = 1;
854 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000855 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
856 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000857 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000858
859 MYDB_BEGIN_ALLOW_THREADS;
860 err = db_env_create(&self->db_env, flags);
861 MYDB_END_ALLOW_THREADS;
862 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000863 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 self = NULL;
865 }
866 else {
867 self->db_env->set_errcall(self->db_env, _db_errorCallback);
868 }
869 return self;
870}
871
872
873static void
874DBEnv_dealloc(DBEnvObject* self)
875{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000876 if (self->in_weakreflist != NULL) {
877 PyObject_ClearWeakRefs((PyObject *) self);
878 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000879
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000880 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881 MYDB_BEGIN_ALLOW_THREADS;
882 self->db_env->close(self->db_env, 0);
883 MYDB_END_ALLOW_THREADS;
884 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886}
887
888
889static DBTxnObject*
890newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
891{
892 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000893 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894 if (self == NULL)
895 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000896 Py_INCREF(myenv);
897 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000898 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899
900 MYDB_BEGIN_ALLOW_THREADS;
901#if (DBVER >= 40)
902 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
903#else
904 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
905#endif
906 MYDB_END_ALLOW_THREADS;
907 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000908 Py_DECREF(self->env);
909 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000910 self = NULL;
911 }
912 return self;
913}
914
915
916static void
917DBTxn_dealloc(DBTxnObject* self)
918{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000919 if (self->in_weakreflist != NULL) {
920 PyObject_ClearWeakRefs((PyObject *) self);
921 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922
Gregory P. Smith31c50652004-06-28 01:20:40 +0000923 if (self->txn) {
924 /* it hasn't been finalized, abort it! */
925 MYDB_BEGIN_ALLOW_THREADS;
926#if (DBVER >= 40)
927 self->txn->abort(self->txn);
928#else
929 txn_abort(self->txn);
930#endif
931 MYDB_END_ALLOW_THREADS;
932 PyErr_Warn(PyExc_RuntimeWarning,
933 "DBTxn aborted in destructor. No prior commit() or abort().");
934 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935
Neal Norwitz62a21122006-01-25 05:21:55 +0000936 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000938}
939
940
941static DBLockObject*
942newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
943 db_lockmode_t lock_mode, int flags)
944{
945 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000946 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947 if (self == NULL)
948 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000949 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000950
951 MYDB_BEGIN_ALLOW_THREADS;
952#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000953 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
954 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000955#else
956 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
957#endif
958 MYDB_END_ALLOW_THREADS;
959 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000960 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000961 self = NULL;
962 }
963
964 return self;
965}
966
967
968static void
969DBLock_dealloc(DBLockObject* self)
970{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000971 if (self->in_weakreflist != NULL) {
972 PyObject_ClearWeakRefs((PyObject *) self);
973 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000974 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000977}
978
979
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000980#if (DBVER >= 43)
981static DBSequenceObject*
982newDBSequenceObject(DBObject* mydb, int flags)
983{
984 int err;
985 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
986 if (self == NULL)
987 return NULL;
988 Py_INCREF(mydb);
989 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000990 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000991
992
993 MYDB_BEGIN_ALLOW_THREADS;
994 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
995 MYDB_END_ALLOW_THREADS;
996 if (makeDBError(err)) {
997 Py_DECREF(self->mydb);
998 PyObject_Del(self);
999 self = NULL;
1000 }
1001
1002 return self;
1003}
1004
1005
1006static void
1007DBSequence_dealloc(DBSequenceObject* self)
1008{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001009 if (self->in_weakreflist != NULL) {
1010 PyObject_ClearWeakRefs((PyObject *) self);
1011 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001012
1013 Py_DECREF(self->mydb);
1014 PyObject_Del(self);
1015}
1016#endif
1017
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001018/* --------------------------------------------------------------------- */
1019/* DB methods */
1020
1021static PyObject*
1022DB_append(DBObject* self, PyObject* args)
1023{
1024 PyObject* txnobj = NULL;
1025 PyObject* dataobj;
1026 db_recno_t recno;
1027 DBT key, data;
1028 DB_TXN *txn = NULL;
1029
Georg Brandl96a8c392006-05-29 21:04:52 +00001030 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001031 return NULL;
1032
1033 CHECK_DB_NOT_CLOSED(self);
1034
1035 /* make a dummy key out of a recno */
1036 recno = 0;
1037 CLEAR_DBT(key);
1038 key.data = &recno;
1039 key.size = sizeof(recno);
1040 key.ulen = key.size;
1041 key.flags = DB_DBT_USERMEM;
1042
1043 if (!make_dbt(dataobj, &data)) return NULL;
1044 if (!checkTxnObj(txnobj, &txn)) return NULL;
1045
1046 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1047 return NULL;
1048
1049 return PyInt_FromLong(recno);
1050}
1051
1052
1053#if (DBVER >= 33)
1054
1055static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001056_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1057 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058{
1059 int retval = DB_DONOTINDEX;
1060 DBObject* secondaryDB = (DBObject*)db->app_private;
1061 PyObject* callback = secondaryDB->associateCallback;
1062 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001064 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001065
1066
1067 if (callback != NULL) {
1068 MYDB_BEGIN_BLOCK_THREADS;
1069
Thomas Woutersb3153832006-03-08 01:47:19 +00001070 if (type == DB_RECNO || type == DB_QUEUE)
1071 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1072 priData->data, priData->size);
1073 else
1074 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1075 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001076 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001077 result = PyEval_CallObject(callback, args);
1078 }
1079 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001080 PyErr_Print();
1081 }
1082 else if (result == Py_None) {
1083 retval = DB_DONOTINDEX;
1084 }
1085 else if (PyInt_Check(result)) {
1086 retval = PyInt_AsLong(result);
1087 }
1088 else if (PyString_Check(result)) {
1089 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001090 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001091
1092 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001093 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001094 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1095 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001096 if (secKey->data) {
1097 memcpy(secKey->data, data, size);
1098 secKey->size = size;
1099 retval = 0;
1100 }
1101 else {
1102 PyErr_SetString(PyExc_MemoryError,
1103 "malloc failed in _db_associateCallback");
1104 PyErr_Print();
1105 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106 }
1107 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001108 PyErr_SetString(
1109 PyExc_TypeError,
1110 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111 PyErr_Print();
1112 }
1113
Thomas Woutersb3153832006-03-08 01:47:19 +00001114 Py_XDECREF(args);
1115 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001116
1117 MYDB_END_BLOCK_THREADS;
1118 }
1119 return retval;
1120}
1121
1122
1123static PyObject*
1124DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1125{
1126 int err, flags=0;
1127 DBObject* secondaryDB;
1128 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001129#if (DBVER >= 41)
1130 PyObject *txnobj = NULL;
1131 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001132 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001133 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001134#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001135 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001136#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001137
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001138#if (DBVER >= 41)
1139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1140 &secondaryDB, &callback, &flags,
1141 &txnobj)) {
1142#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001144 &secondaryDB, &callback, &flags)) {
1145#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001147 }
1148
1149#if (DBVER >= 41)
1150 if (!checkTxnObj(txnobj, &txn)) return NULL;
1151#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152
1153 CHECK_DB_NOT_CLOSED(self);
1154 if (!DBObject_Check(secondaryDB)) {
1155 makeTypeError("DB", (PyObject*)secondaryDB);
1156 return NULL;
1157 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001158 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001159 if (callback == Py_None) {
1160 callback = NULL;
1161 }
1162 else if (!PyCallable_Check(callback)) {
1163 makeTypeError("Callable", callback);
1164 return NULL;
1165 }
1166
1167 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001168 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001169 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 secondaryDB->associateCallback = callback;
1171 secondaryDB->primaryDBType = _DB_get_type(self);
1172
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001173 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1174 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1175 * The global interepreter lock is not initialized until the first
1176 * thread is created using thread.start_new_thread() or fork() is
1177 * called. that would cause the ALLOW_THREADS here to segfault due
1178 * to a null pointer reference if no threads or child processes
1179 * have been created. This works around that and is a no-op if
1180 * threads have already been initialized.
1181 * (see pybsddb-users mailing list post on 2002-08-07)
1182 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001183#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001184 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001185#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001186 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001187#if (DBVER >= 41)
1188 err = self->db->associate(self->db,
1189 txn,
1190 secondaryDB->db,
1191 _db_associateCallback,
1192 flags);
1193#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001194 err = self->db->associate(self->db,
1195 secondaryDB->db,
1196 _db_associateCallback,
1197 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001198#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001199 MYDB_END_ALLOW_THREADS;
1200
1201 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001202 Py_XDECREF(secondaryDB->associateCallback);
1203 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001204 secondaryDB->primaryDBType = 0;
1205 }
1206
1207 RETURN_IF_ERR();
1208 RETURN_NONE();
1209}
1210
1211
1212#endif
1213
1214
1215static PyObject*
1216DB_close(DBObject* self, PyObject* args)
1217{
1218 int err, flags=0;
1219 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1220 return NULL;
1221 if (self->db != NULL) {
1222 if (self->myenvobj)
1223 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001224 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225 self->db = NULL;
1226 RETURN_IF_ERR();
1227 }
1228 RETURN_NONE();
1229}
1230
1231
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001232static PyObject*
1233_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1234{
1235 int err, flags=0, type;
1236 PyObject* txnobj = NULL;
1237 PyObject* retval = NULL;
1238 DBT key, data;
1239 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001240 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241
1242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1243 &txnobj, &flags))
1244 return NULL;
1245
1246 CHECK_DB_NOT_CLOSED(self);
1247 type = _DB_get_type(self);
1248 if (type == -1)
1249 return NULL;
1250 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001251 PyErr_SetString(PyExc_TypeError,
1252 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001253 return NULL;
1254 }
1255 if (!checkTxnObj(txnobj, &txn))
1256 return NULL;
1257
1258 CLEAR_DBT(key);
1259 CLEAR_DBT(data);
1260 if (CHECK_DBFLAG(self, DB_THREAD)) {
1261 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1262 data.flags = DB_DBT_MALLOC;
1263 key.flags = DB_DBT_MALLOC;
1264 }
1265
1266 MYDB_BEGIN_ALLOW_THREADS;
1267 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1268 MYDB_END_ALLOW_THREADS;
1269
Gregory P. Smithe9477062005-06-04 06:46:59 +00001270 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1271 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 err = 0;
1273 Py_INCREF(Py_None);
1274 retval = Py_None;
1275 }
1276 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001277 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1278 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001279 FREE_DBT(key);
1280 FREE_DBT(data);
1281 }
1282
1283 RETURN_IF_ERR();
1284 return retval;
1285}
1286
1287static PyObject*
1288DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1289{
1290 return _DB_consume(self, args, kwargs, DB_CONSUME);
1291}
1292
1293static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001294DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1295 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001296{
1297 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1298}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001299
1300
1301static PyObject*
1302DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1303{
1304 int err, flags=0;
1305 DBC* dbc;
1306 PyObject* txnobj = NULL;
1307 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001308 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001309
1310 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1311 &txnobj, &flags))
1312 return NULL;
1313 CHECK_DB_NOT_CLOSED(self);
1314 if (!checkTxnObj(txnobj, &txn))
1315 return NULL;
1316
1317 MYDB_BEGIN_ALLOW_THREADS;
1318 err = self->db->cursor(self->db, txn, &dbc, flags);
1319 MYDB_END_ALLOW_THREADS;
1320 RETURN_IF_ERR();
1321 return (PyObject*) newDBCursorObject(dbc, self);
1322}
1323
1324
1325static PyObject*
1326DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1327{
1328 PyObject* txnobj = NULL;
1329 int flags = 0;
1330 PyObject* keyobj;
1331 DBT key;
1332 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001333 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001334
1335 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1336 &keyobj, &txnobj, &flags))
1337 return NULL;
1338 CHECK_DB_NOT_CLOSED(self);
1339 if (!make_key_dbt(self, keyobj, &key, NULL))
1340 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001341 if (!checkTxnObj(txnobj, &txn)) {
1342 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001344 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001346 if (-1 == _DB_delete(self, txn, &key, 0)) {
1347 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001348 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001349 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001350
1351 FREE_DBT(key);
1352 RETURN_NONE();
1353}
1354
1355
1356static PyObject*
1357DB_fd(DBObject* self, PyObject* args)
1358{
1359 int err, the_fd;
1360
1361 if (!PyArg_ParseTuple(args,":fd"))
1362 return NULL;
1363 CHECK_DB_NOT_CLOSED(self);
1364
1365 MYDB_BEGIN_ALLOW_THREADS;
1366 err = self->db->fd(self->db, &the_fd);
1367 MYDB_END_ALLOW_THREADS;
1368 RETURN_IF_ERR();
1369 return PyInt_FromLong(the_fd);
1370}
1371
1372
1373static PyObject*
1374DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1375{
1376 int err, flags=0;
1377 PyObject* txnobj = NULL;
1378 PyObject* keyobj;
1379 PyObject* dfltobj = NULL;
1380 PyObject* retval = NULL;
1381 int dlen = -1;
1382 int doff = -1;
1383 DBT key, data;
1384 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001385 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001386 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001387
1388 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001389 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1390 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391 return NULL;
1392
1393 CHECK_DB_NOT_CLOSED(self);
1394 if (!make_key_dbt(self, keyobj, &key, &flags))
1395 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001396 if (!checkTxnObj(txnobj, &txn)) {
1397 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001398 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001399 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001400
1401 CLEAR_DBT(data);
1402 if (CHECK_DBFLAG(self, DB_THREAD)) {
1403 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1404 data.flags = DB_DBT_MALLOC;
1405 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001406 if (!add_partial_dbt(&data, dlen, doff)) {
1407 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001408 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001409 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410
1411 MYDB_BEGIN_ALLOW_THREADS;
1412 err = self->db->get(self->db, txn, &key, &data, flags);
1413 MYDB_END_ALLOW_THREADS;
1414
Gregory P. Smithe9477062005-06-04 06:46:59 +00001415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001416 err = 0;
1417 Py_INCREF(dfltobj);
1418 retval = dfltobj;
1419 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001420 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1421 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422 err = 0;
1423 Py_INCREF(Py_None);
1424 retval = Py_None;
1425 }
1426 else if (!err) {
1427 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001428 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1429 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001430 else /* return just the data */
1431 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001432 FREE_DBT(data);
1433 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001434 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435
1436 RETURN_IF_ERR();
1437 return retval;
1438}
1439
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001440#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001441static PyObject*
1442DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1443{
1444 int err, flags=0;
1445 PyObject* txnobj = NULL;
1446 PyObject* keyobj;
1447 PyObject* dfltobj = NULL;
1448 PyObject* retval = NULL;
1449 int dlen = -1;
1450 int doff = -1;
1451 DBT key, pkey, data;
1452 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001453 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001454 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001455
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1457 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1458 &doff))
1459 return NULL;
1460
1461 CHECK_DB_NOT_CLOSED(self);
1462 if (!make_key_dbt(self, keyobj, &key, &flags))
1463 return NULL;
1464 if (!checkTxnObj(txnobj, &txn)) {
1465 FREE_DBT(key);
1466 return NULL;
1467 }
1468
1469 CLEAR_DBT(data);
1470 if (CHECK_DBFLAG(self, DB_THREAD)) {
1471 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1472 data.flags = DB_DBT_MALLOC;
1473 }
1474 if (!add_partial_dbt(&data, dlen, doff)) {
1475 FREE_DBT(key);
1476 return NULL;
1477 }
1478
1479 CLEAR_DBT(pkey);
1480 pkey.flags = DB_DBT_MALLOC;
1481
1482 MYDB_BEGIN_ALLOW_THREADS;
1483 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1484 MYDB_END_ALLOW_THREADS;
1485
Gregory P. Smithe9477062005-06-04 06:46:59 +00001486 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001487 err = 0;
1488 Py_INCREF(dfltobj);
1489 retval = dfltobj;
1490 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001491 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1492 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001493 err = 0;
1494 Py_INCREF(Py_None);
1495 retval = Py_None;
1496 }
1497 else if (!err) {
1498 PyObject *pkeyObj;
1499 PyObject *dataObj;
1500 dataObj = PyString_FromStringAndSize(data.data, data.size);
1501
1502 if (self->primaryDBType == DB_RECNO ||
1503 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001504 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001505 else
1506 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1507
1508 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1509 {
1510 PyObject *keyObj;
1511 int type = _DB_get_type(self);
1512 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001513 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001514 else
1515 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001516#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001517 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001518#else
1519 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1520#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001521 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001522 }
1523 else /* return just the pkey and data */
1524 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001525#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001526 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001527#else
1528 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1529#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001530 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001531 Py_DECREF(dataObj);
1532 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001533 FREE_DBT(pkey);
1534 FREE_DBT(data);
1535 }
1536 FREE_DBT(key);
1537
1538 RETURN_IF_ERR();
1539 return retval;
1540}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001541#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001542
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001543
1544/* Return size of entry */
1545static PyObject*
1546DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1547{
1548 int err, flags=0;
1549 PyObject* txnobj = NULL;
1550 PyObject* keyobj;
1551 PyObject* retval = NULL;
1552 DBT key, data;
1553 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001554 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555
1556 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1557 &keyobj, &txnobj))
1558 return NULL;
1559 CHECK_DB_NOT_CLOSED(self);
1560 if (!make_key_dbt(self, keyobj, &key, &flags))
1561 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001562 if (!checkTxnObj(txnobj, &txn)) {
1563 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001564 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001565 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566 CLEAR_DBT(data);
1567
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001568 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1569 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001570 data.flags = DB_DBT_USERMEM;
1571 data.ulen = 0;
1572 MYDB_BEGIN_ALLOW_THREADS;
1573 err = self->db->get(self->db, txn, &key, &data, flags);
1574 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001575 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001576 retval = PyInt_FromLong((long)data.size);
1577 err = 0;
1578 }
1579
1580 FREE_DBT(key);
1581 FREE_DBT(data);
1582 RETURN_IF_ERR();
1583 return retval;
1584}
1585
1586
1587static PyObject*
1588DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1589{
1590 int err, flags=0;
1591 PyObject* txnobj = NULL;
1592 PyObject* keyobj;
1593 PyObject* dataobj;
1594 PyObject* retval = NULL;
1595 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001596 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001597 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001598 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599
1600
1601 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1602 &keyobj, &dataobj, &txnobj, &flags))
1603 return NULL;
1604
1605 CHECK_DB_NOT_CLOSED(self);
1606 if (!make_key_dbt(self, keyobj, &key, NULL))
1607 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001608 if ( !make_dbt(dataobj, &data) ||
1609 !checkTxnObj(txnobj, &txn) )
1610 {
1611 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001612 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001613 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001614
1615 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001616 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617
1618 if (CHECK_DBFLAG(self, DB_THREAD)) {
1619 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001620 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001621 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001622 }
1623
1624 MYDB_BEGIN_ALLOW_THREADS;
1625 err = self->db->get(self->db, txn, &key, &data, flags);
1626 MYDB_END_ALLOW_THREADS;
1627
Gregory P. Smithe9477062005-06-04 06:46:59 +00001628 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1629 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001630 err = 0;
1631 Py_INCREF(Py_None);
1632 retval = Py_None;
1633 }
1634 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001635 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001637
1638 /* Even though the flags require DB_DBT_MALLOC, data is not always
1639 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1640 if (data.data != orig_data)
1641 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001642 }
1643
1644 FREE_DBT(key);
1645 RETURN_IF_ERR();
1646 return retval;
1647}
1648
1649
1650static PyObject*
1651DB_get_byteswapped(DBObject* self, PyObject* args)
1652{
1653#if (DBVER >= 33)
1654 int err = 0;
1655#endif
1656 int retval = -1;
1657
1658 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1659 return NULL;
1660 CHECK_DB_NOT_CLOSED(self);
1661
1662#if (DBVER >= 33)
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->get_byteswapped(self->db, &retval);
1665 MYDB_END_ALLOW_THREADS;
1666 RETURN_IF_ERR();
1667#else
1668 MYDB_BEGIN_ALLOW_THREADS;
1669 retval = self->db->get_byteswapped(self->db);
1670 MYDB_END_ALLOW_THREADS;
1671#endif
1672 return PyInt_FromLong(retval);
1673}
1674
1675
1676static PyObject*
1677DB_get_type(DBObject* self, PyObject* args)
1678{
1679 int type;
1680
1681 if (!PyArg_ParseTuple(args,":get_type"))
1682 return NULL;
1683 CHECK_DB_NOT_CLOSED(self);
1684
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686 if (type == -1)
1687 return NULL;
1688 return PyInt_FromLong(type);
1689}
1690
1691
1692static PyObject*
1693DB_join(DBObject* self, PyObject* args)
1694{
1695 int err, flags=0;
1696 int length, x;
1697 PyObject* cursorsObj;
1698 DBC** cursors;
1699 DBC* dbc;
1700
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001701 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1702 return NULL;
1703
1704 CHECK_DB_NOT_CLOSED(self);
1705
1706 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001707 PyErr_SetString(PyExc_TypeError,
1708 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001709 return NULL;
1710 }
1711
1712 length = PyObject_Length(cursorsObj);
1713 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001714 if (!cursors) {
1715 PyErr_NoMemory();
1716 return NULL;
1717 }
1718
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719 cursors[length] = NULL;
1720 for (x=0; x<length; x++) {
1721 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001722 if (item == NULL) {
1723 free(cursors);
1724 return NULL;
1725 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001726 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001727 PyErr_SetString(PyExc_TypeError,
1728 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729 free(cursors);
1730 return NULL;
1731 }
1732 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001733 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001734 }
1735
1736 MYDB_BEGIN_ALLOW_THREADS;
1737 err = self->db->join(self->db, cursors, &dbc, flags);
1738 MYDB_END_ALLOW_THREADS;
1739 free(cursors);
1740 RETURN_IF_ERR();
1741
Gregory P. Smith7441e652003-11-03 21:35:31 +00001742 /* FIXME: this is a buggy interface. The returned cursor
1743 contains internal references to the passed in cursors
1744 but does not hold python references to them or prevent
1745 them from being closed prematurely. This can cause
1746 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001747 return (PyObject*) newDBCursorObject(dbc, self);
1748}
1749
1750
1751static PyObject*
1752DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1753{
1754 int err, flags=0;
1755 PyObject* txnobj = NULL;
1756 PyObject* keyobj;
1757 DBT key;
1758 DB_TXN *txn = NULL;
1759 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001760 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001761
1762 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1763 &keyobj, &txnobj, &flags))
1764 return NULL;
1765 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001766 if (!make_dbt(keyobj, &key))
1767 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001768 return NULL;
1769 if (!checkTxnObj(txnobj, &txn))
1770 return NULL;
1771
1772 MYDB_BEGIN_ALLOW_THREADS;
1773 err = self->db->key_range(self->db, txn, &key, &range, flags);
1774 MYDB_END_ALLOW_THREADS;
1775
1776 RETURN_IF_ERR();
1777 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1778}
1779
1780
1781static PyObject*
1782DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1783{
1784 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1785 char* filename = NULL;
1786 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001787#if (DBVER >= 41)
1788 PyObject *txnobj = NULL;
1789 DB_TXN *txn = NULL;
1790 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001791 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001792 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1793 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001794 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001795 "filename", "dbtype", "flags", "mode", "txn", NULL};
1796#else
1797 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001798 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001799 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1800 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001801 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001802 "filename", "dbtype", "flags", "mode", NULL};
1803#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001804
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001805#if (DBVER >= 41)
1806 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1807 &filename, &dbname, &type, &flags, &mode,
1808 &txnobj))
1809#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001810 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001811 &filename, &dbname, &type, &flags,
1812 &mode))
1813#endif
1814 {
1815 PyErr_Clear();
1816 type = DB_UNKNOWN; flags = 0; mode = 0660;
1817 filename = NULL; dbname = NULL;
1818#if (DBVER >= 41)
1819 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1820 kwnames_basic,
1821 &filename, &type, &flags, &mode,
1822 &txnobj))
1823 return NULL;
1824#else
1825 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1826 kwnames_basic,
1827 &filename, &type, &flags, &mode))
1828 return NULL;
1829#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001830 }
1831
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001832#if (DBVER >= 41)
1833 if (!checkTxnObj(txnobj, &txn)) return NULL;
1834#endif
1835
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001836 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001837 PyObject *t = Py_BuildValue("(is)", 0,
1838 "Cannot call open() twice for DB object");
1839 PyErr_SetObject(DBError, t);
1840 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001841 return NULL;
1842 }
1843
1844 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001845#if (DBVER >= 41)
1846 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1847#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001849#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850 MYDB_END_ALLOW_THREADS;
1851 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001852 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 self->db = NULL;
1854 return NULL;
1855 }
1856
Gregory P. Smithfc006692007-11-05 09:06:28 +00001857#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00001858 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00001859#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00001860
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 self->flags = flags;
1862 RETURN_NONE();
1863}
1864
1865
1866static PyObject*
1867DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1868{
1869 int flags=0;
1870 PyObject* txnobj = NULL;
1871 int dlen = -1;
1872 int doff = -1;
1873 PyObject* keyobj, *dataobj, *retval;
1874 DBT key, data;
1875 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001876 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001877 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001878
1879 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1880 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1881 return NULL;
1882
1883 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001884 if (!make_key_dbt(self, keyobj, &key, NULL))
1885 return NULL;
1886 if ( !make_dbt(dataobj, &data) ||
1887 !add_partial_dbt(&data, dlen, doff) ||
1888 !checkTxnObj(txnobj, &txn) )
1889 {
1890 FREE_DBT(key);
1891 return NULL;
1892 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001893
1894 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1895 FREE_DBT(key);
1896 return NULL;
1897 }
1898
1899 if (flags & DB_APPEND)
1900 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1901 else {
1902 retval = Py_None;
1903 Py_INCREF(retval);
1904 }
1905 FREE_DBT(key);
1906 return retval;
1907}
1908
1909
1910
1911static PyObject*
1912DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1913{
1914 char* filename;
1915 char* database = NULL;
1916 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001917 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001918
1919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1920 &filename, &database, &flags))
1921 return NULL;
1922 CHECK_DB_NOT_CLOSED(self);
1923
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001925 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001926 RETURN_IF_ERR();
1927 RETURN_NONE();
1928}
1929
1930
1931
1932static PyObject*
1933DB_rename(DBObject* self, PyObject* args)
1934{
1935 char* filename;
1936 char* database;
1937 char* newname;
1938 int err, flags=0;
1939
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001940 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1941 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001942 return NULL;
1943 CHECK_DB_NOT_CLOSED(self);
1944
1945 MYDB_BEGIN_ALLOW_THREADS;
1946 err = self->db->rename(self->db, filename, database, newname, flags);
1947 MYDB_END_ALLOW_THREADS;
1948 RETURN_IF_ERR();
1949 RETURN_NONE();
1950}
1951
1952
1953static PyObject*
1954DB_set_bt_minkey(DBObject* self, PyObject* args)
1955{
1956 int err, minkey;
1957
1958 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1959 return NULL;
1960 CHECK_DB_NOT_CLOSED(self);
1961
1962 MYDB_BEGIN_ALLOW_THREADS;
1963 err = self->db->set_bt_minkey(self->db, minkey);
1964 MYDB_END_ALLOW_THREADS;
1965 RETURN_IF_ERR();
1966 RETURN_NONE();
1967}
1968
Neal Norwitz84562352005-10-20 04:30:15 +00001969#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001970static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001971_default_cmp(const DBT *leftKey,
1972 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001973{
1974 int res;
1975 int lsize = leftKey->size, rsize = rightKey->size;
1976
Georg Brandlef1701f2006-03-07 14:57:48 +00001977 res = memcmp(leftKey->data, rightKey->data,
1978 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001979
1980 if (res == 0) {
1981 if (lsize < rsize) {
1982 res = -1;
1983 }
1984 else if (lsize > rsize) {
1985 res = 1;
1986 }
1987 }
1988 return res;
1989}
1990
1991static int
Georg Brandlef1701f2006-03-07 14:57:48 +00001992_db_compareCallback(DB* db,
1993 const DBT *leftKey,
1994 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001995{
1996 int res = 0;
1997 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001998 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00001999 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002000
2001 if (self == NULL || self->btCompareCallback == NULL) {
2002 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002003 PyErr_SetString(PyExc_TypeError,
2004 (self == 0
2005 ? "DB_bt_compare db is NULL."
2006 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002007 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002008 PyErr_Print();
2009 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002010 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002011 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002012 MYDB_BEGIN_BLOCK_THREADS;
2013
Thomas Woutersb3153832006-03-08 01:47:19 +00002014 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2015 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002016 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002017 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002018 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002019 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002020 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002021 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002022 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002023 PyErr_Print();
2024 res = _default_cmp(leftKey, rightKey);
2025 } else if (PyInt_Check(result)) {
2026 res = PyInt_AsLong(result);
2027 } else {
2028 PyErr_SetString(PyExc_TypeError,
2029 "DB_bt_compare callback MUST return an int.");
2030 /* we're in a callback within the DB code, we can't raise */
2031 PyErr_Print();
2032 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002033 }
2034
Thomas Woutersb3153832006-03-08 01:47:19 +00002035 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002036 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002037
2038 MYDB_END_BLOCK_THREADS;
2039 }
2040 return res;
2041}
2042
2043static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002044DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002045{
2046 int err;
2047 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002048 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002049
Georg Brandlef1701f2006-03-07 14:57:48 +00002050 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002051 return NULL;
2052
Georg Brandlef1701f2006-03-07 14:57:48 +00002053 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002054
Georg Brandlef1701f2006-03-07 14:57:48 +00002055 if (!PyCallable_Check(comparator)) {
2056 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002057 return NULL;
2058 }
2059
2060 /*
2061 * Perform a test call of the comparator function with two empty
2062 * string objects here. verify that it returns an int (0).
2063 * err if not.
2064 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002065 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002066 result = PyEval_CallObject(comparator, tuple);
2067 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002068 if (result == NULL)
2069 return NULL;
2070 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002071 PyErr_SetString(PyExc_TypeError,
2072 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002073 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002074 } else if (PyInt_AsLong(result) != 0) {
2075 PyErr_SetString(PyExc_TypeError,
2076 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077 return NULL;
2078 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002079 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002080
2081 /* We don't accept multiple set_bt_compare operations, in order to
2082 * simplify the code. This would have no real use, as one cannot
2083 * change the function once the db is opened anyway */
2084 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002085 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002086 return NULL;
2087 }
2088
Georg Brandlef1701f2006-03-07 14:57:48 +00002089 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002090 self->btCompareCallback = comparator;
2091
2092 /* This is to workaround a problem with un-initialized threads (see
2093 comment in DB_associate) */
2094#ifdef WITH_THREAD
2095 PyEval_InitThreads();
2096#endif
2097
Thomas Woutersb3153832006-03-08 01:47:19 +00002098 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002099
2100 if (err) {
2101 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002102 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103 self->btCompareCallback = NULL;
2104 }
2105
Georg Brandlef1701f2006-03-07 14:57:48 +00002106 RETURN_IF_ERR();
2107 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108}
Neal Norwitz84562352005-10-20 04:30:15 +00002109#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002110
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002111
2112static PyObject*
2113DB_set_cachesize(DBObject* self, PyObject* args)
2114{
2115 int err;
2116 int gbytes = 0, bytes = 0, ncache = 0;
2117
2118 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2119 &gbytes,&bytes,&ncache))
2120 return NULL;
2121 CHECK_DB_NOT_CLOSED(self);
2122
2123 MYDB_BEGIN_ALLOW_THREADS;
2124 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2125 MYDB_END_ALLOW_THREADS;
2126 RETURN_IF_ERR();
2127 RETURN_NONE();
2128}
2129
2130
2131static PyObject*
2132DB_set_flags(DBObject* self, PyObject* args)
2133{
2134 int err, flags;
2135
2136 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2137 return NULL;
2138 CHECK_DB_NOT_CLOSED(self);
2139
2140 MYDB_BEGIN_ALLOW_THREADS;
2141 err = self->db->set_flags(self->db, flags);
2142 MYDB_END_ALLOW_THREADS;
2143 RETURN_IF_ERR();
2144
2145 self->setflags |= flags;
2146 RETURN_NONE();
2147}
2148
2149
2150static PyObject*
2151DB_set_h_ffactor(DBObject* self, PyObject* args)
2152{
2153 int err, ffactor;
2154
2155 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2156 return NULL;
2157 CHECK_DB_NOT_CLOSED(self);
2158
2159 MYDB_BEGIN_ALLOW_THREADS;
2160 err = self->db->set_h_ffactor(self->db, ffactor);
2161 MYDB_END_ALLOW_THREADS;
2162 RETURN_IF_ERR();
2163 RETURN_NONE();
2164}
2165
2166
2167static PyObject*
2168DB_set_h_nelem(DBObject* self, PyObject* args)
2169{
2170 int err, nelem;
2171
2172 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2173 return NULL;
2174 CHECK_DB_NOT_CLOSED(self);
2175
2176 MYDB_BEGIN_ALLOW_THREADS;
2177 err = self->db->set_h_nelem(self->db, nelem);
2178 MYDB_END_ALLOW_THREADS;
2179 RETURN_IF_ERR();
2180 RETURN_NONE();
2181}
2182
2183
2184static PyObject*
2185DB_set_lorder(DBObject* self, PyObject* args)
2186{
2187 int err, lorder;
2188
2189 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2190 return NULL;
2191 CHECK_DB_NOT_CLOSED(self);
2192
2193 MYDB_BEGIN_ALLOW_THREADS;
2194 err = self->db->set_lorder(self->db, lorder);
2195 MYDB_END_ALLOW_THREADS;
2196 RETURN_IF_ERR();
2197 RETURN_NONE();
2198}
2199
2200
2201static PyObject*
2202DB_set_pagesize(DBObject* self, PyObject* args)
2203{
2204 int err, pagesize;
2205
2206 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2207 return NULL;
2208 CHECK_DB_NOT_CLOSED(self);
2209
2210 MYDB_BEGIN_ALLOW_THREADS;
2211 err = self->db->set_pagesize(self->db, pagesize);
2212 MYDB_END_ALLOW_THREADS;
2213 RETURN_IF_ERR();
2214 RETURN_NONE();
2215}
2216
2217
2218static PyObject*
2219DB_set_re_delim(DBObject* self, PyObject* args)
2220{
2221 int err;
2222 char delim;
2223
2224 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2225 PyErr_Clear();
2226 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2227 return NULL;
2228 }
2229
2230 CHECK_DB_NOT_CLOSED(self);
2231
2232 MYDB_BEGIN_ALLOW_THREADS;
2233 err = self->db->set_re_delim(self->db, delim);
2234 MYDB_END_ALLOW_THREADS;
2235 RETURN_IF_ERR();
2236 RETURN_NONE();
2237}
2238
2239static PyObject*
2240DB_set_re_len(DBObject* self, PyObject* args)
2241{
2242 int err, len;
2243
2244 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_re_len(self->db, len);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252 RETURN_NONE();
2253}
2254
2255
2256static PyObject*
2257DB_set_re_pad(DBObject* self, PyObject* args)
2258{
2259 int err;
2260 char pad;
2261
2262 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2263 PyErr_Clear();
2264 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2265 return NULL;
2266 }
2267 CHECK_DB_NOT_CLOSED(self);
2268
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->set_re_pad(self->db, pad);
2271 MYDB_END_ALLOW_THREADS;
2272 RETURN_IF_ERR();
2273 RETURN_NONE();
2274}
2275
2276
2277static PyObject*
2278DB_set_re_source(DBObject* self, PyObject* args)
2279{
2280 int err;
2281 char *re_source;
2282
2283 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2284 return NULL;
2285 CHECK_DB_NOT_CLOSED(self);
2286
2287 MYDB_BEGIN_ALLOW_THREADS;
2288 err = self->db->set_re_source(self->db, re_source);
2289 MYDB_END_ALLOW_THREADS;
2290 RETURN_IF_ERR();
2291 RETURN_NONE();
2292}
2293
2294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002295static PyObject*
2296DB_set_q_extentsize(DBObject* self, PyObject* args)
2297{
2298 int err;
2299 int extentsize;
2300
2301 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2302 return NULL;
2303 CHECK_DB_NOT_CLOSED(self);
2304
2305 MYDB_BEGIN_ALLOW_THREADS;
2306 err = self->db->set_q_extentsize(self->db, extentsize);
2307 MYDB_END_ALLOW_THREADS;
2308 RETURN_IF_ERR();
2309 RETURN_NONE();
2310}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002311
2312static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002313DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002314{
2315 int err, flags = 0, type;
2316 void* sp;
2317 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002318#if (DBVER >= 43)
2319 PyObject* txnobj = NULL;
2320 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002321 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002322#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002323 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002324#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002325
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002326#if (DBVER >= 43)
2327 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2328 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002329 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002330 if (!checkTxnObj(txnobj, &txn))
2331 return NULL;
2332#else
2333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2334 return NULL;
2335#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002336 CHECK_DB_NOT_CLOSED(self);
2337
2338 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002339#if (DBVER >= 43)
2340 err = self->db->stat(self->db, txn, &sp, flags);
2341#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002342 err = self->db->stat(self->db, &sp, flags);
2343#else
2344 err = self->db->stat(self->db, &sp, NULL, flags);
2345#endif
2346 MYDB_END_ALLOW_THREADS;
2347 RETURN_IF_ERR();
2348
2349 self->haveStat = 1;
2350
2351 /* Turn the stat structure into a dictionary */
2352 type = _DB_get_type(self);
2353 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2354 free(sp);
2355 return NULL;
2356 }
2357
2358#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2359#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2360#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2361
2362 switch (type) {
2363 case DB_HASH:
2364 MAKE_HASH_ENTRY(magic);
2365 MAKE_HASH_ENTRY(version);
2366 MAKE_HASH_ENTRY(nkeys);
2367 MAKE_HASH_ENTRY(ndata);
2368 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002369#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002370 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002371#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002372 MAKE_HASH_ENTRY(ffactor);
2373 MAKE_HASH_ENTRY(buckets);
2374 MAKE_HASH_ENTRY(free);
2375 MAKE_HASH_ENTRY(bfree);
2376 MAKE_HASH_ENTRY(bigpages);
2377 MAKE_HASH_ENTRY(big_bfree);
2378 MAKE_HASH_ENTRY(overflows);
2379 MAKE_HASH_ENTRY(ovfl_free);
2380 MAKE_HASH_ENTRY(dup);
2381 MAKE_HASH_ENTRY(dup_free);
2382 break;
2383
2384 case DB_BTREE:
2385 case DB_RECNO:
2386 MAKE_BT_ENTRY(magic);
2387 MAKE_BT_ENTRY(version);
2388 MAKE_BT_ENTRY(nkeys);
2389 MAKE_BT_ENTRY(ndata);
2390 MAKE_BT_ENTRY(pagesize);
2391 MAKE_BT_ENTRY(minkey);
2392 MAKE_BT_ENTRY(re_len);
2393 MAKE_BT_ENTRY(re_pad);
2394 MAKE_BT_ENTRY(levels);
2395 MAKE_BT_ENTRY(int_pg);
2396 MAKE_BT_ENTRY(leaf_pg);
2397 MAKE_BT_ENTRY(dup_pg);
2398 MAKE_BT_ENTRY(over_pg);
2399 MAKE_BT_ENTRY(free);
2400 MAKE_BT_ENTRY(int_pgfree);
2401 MAKE_BT_ENTRY(leaf_pgfree);
2402 MAKE_BT_ENTRY(dup_pgfree);
2403 MAKE_BT_ENTRY(over_pgfree);
2404 break;
2405
2406 case DB_QUEUE:
2407 MAKE_QUEUE_ENTRY(magic);
2408 MAKE_QUEUE_ENTRY(version);
2409 MAKE_QUEUE_ENTRY(nkeys);
2410 MAKE_QUEUE_ENTRY(ndata);
2411 MAKE_QUEUE_ENTRY(pagesize);
2412 MAKE_QUEUE_ENTRY(pages);
2413 MAKE_QUEUE_ENTRY(re_len);
2414 MAKE_QUEUE_ENTRY(re_pad);
2415 MAKE_QUEUE_ENTRY(pgfree);
2416#if (DBVER == 31)
2417 MAKE_QUEUE_ENTRY(start);
2418#endif
2419 MAKE_QUEUE_ENTRY(first_recno);
2420 MAKE_QUEUE_ENTRY(cur_recno);
2421 break;
2422
2423 default:
2424 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2425 Py_DECREF(d);
2426 d = NULL;
2427 }
2428
2429#undef MAKE_HASH_ENTRY
2430#undef MAKE_BT_ENTRY
2431#undef MAKE_QUEUE_ENTRY
2432
2433 free(sp);
2434 return d;
2435}
2436
2437static PyObject*
2438DB_sync(DBObject* self, PyObject* args)
2439{
2440 int err;
2441 int flags = 0;
2442
2443 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2444 return NULL;
2445 CHECK_DB_NOT_CLOSED(self);
2446
2447 MYDB_BEGIN_ALLOW_THREADS;
2448 err = self->db->sync(self->db, flags);
2449 MYDB_END_ALLOW_THREADS;
2450 RETURN_IF_ERR();
2451 RETURN_NONE();
2452}
2453
2454
2455#if (DBVER >= 33)
2456static PyObject*
2457DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2458{
2459 int err, flags=0;
2460 u_int32_t count=0;
2461 PyObject* txnobj = NULL;
2462 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002463 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002464
2465 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2466 &txnobj, &flags))
2467 return NULL;
2468 CHECK_DB_NOT_CLOSED(self);
2469 if (!checkTxnObj(txnobj, &txn))
2470 return NULL;
2471
2472 MYDB_BEGIN_ALLOW_THREADS;
2473 err = self->db->truncate(self->db, txn, &count, flags);
2474 MYDB_END_ALLOW_THREADS;
2475 RETURN_IF_ERR();
2476 return PyInt_FromLong(count);
2477}
2478#endif
2479
2480
2481static PyObject*
2482DB_upgrade(DBObject* self, PyObject* args)
2483{
2484 int err, flags=0;
2485 char *filename;
2486
2487 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2490
2491 MYDB_BEGIN_ALLOW_THREADS;
2492 err = self->db->upgrade(self->db, filename, flags);
2493 MYDB_END_ALLOW_THREADS;
2494 RETURN_IF_ERR();
2495 RETURN_NONE();
2496}
2497
2498
2499static PyObject*
2500DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2501{
2502 int err, flags=0;
2503 char* fileName;
2504 char* dbName=NULL;
2505 char* outFileName=NULL;
2506 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002507 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002508 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002509
2510 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2511 &fileName, &dbName, &outFileName, &flags))
2512 return NULL;
2513
2514 CHECK_DB_NOT_CLOSED(self);
2515 if (outFileName)
2516 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002517 /* XXX(nnorwitz): it should probably be an exception if outFile
2518 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002519
2520 MYDB_BEGIN_ALLOW_THREADS;
2521 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2522 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002523 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002524 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002525
2526 /* DB.verify acts as a DB handle destructor (like close); this was
2527 * documented in BerkeleyDB 4.2 but had the undocumented effect
2528 * of not being safe in prior versions while still requiring an explicit
2529 * DB.close call afterwards. Lets call close for the user to emulate
2530 * the safe 4.2 behaviour. */
2531#if (DBVER <= 41)
2532 self->db->close(self->db, 0);
2533#endif
2534 self->db = NULL;
2535
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002536 RETURN_IF_ERR();
2537 RETURN_NONE();
2538}
2539
2540
2541static PyObject*
2542DB_set_get_returns_none(DBObject* self, PyObject* args)
2543{
2544 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002545 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002546
2547 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2548 return NULL;
2549 CHECK_DB_NOT_CLOSED(self);
2550
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002551 if (self->moduleFlags.getReturnsNone)
2552 ++oldValue;
2553 if (self->moduleFlags.cursorSetReturnsNone)
2554 ++oldValue;
2555 self->moduleFlags.getReturnsNone = (flags >= 1);
2556 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002557 return PyInt_FromLong(oldValue);
2558}
2559
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002560#if (DBVER >= 41)
2561static PyObject*
2562DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2563{
2564 int err;
2565 u_int32_t flags=0;
2566 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002567 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002568
2569 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2570 &passwd, &flags)) {
2571 return NULL;
2572 }
2573
2574 MYDB_BEGIN_ALLOW_THREADS;
2575 err = self->db->set_encrypt(self->db, passwd, flags);
2576 MYDB_END_ALLOW_THREADS;
2577
2578 RETURN_IF_ERR();
2579 RETURN_NONE();
2580}
2581#endif /* DBVER >= 41 */
2582
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002583
2584/*-------------------------------------------------------------- */
2585/* Mapping and Dictionary-like access routines */
2586
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002587Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002588{
2589 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002590 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002591 int flags = 0;
2592 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002593 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002594
2595 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002596 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2597 PyErr_SetObject(DBError, t);
2598 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002599 return -1;
2600 }
2601
2602 if (self->haveStat) { /* Has the stat function been called recently? If
2603 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002604 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002605 }
2606
2607 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002608redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002609#if (DBVER >= 43)
2610 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2611#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002612 err = self->db->stat(self->db, &sp, flags);
2613#else
2614 err = self->db->stat(self->db, &sp, NULL, flags);
2615#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002616
2617 /* All the stat structures have matching fields upto the ndata field,
2618 so we can use any of them for the type cast */
2619 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2620
2621 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2622 * redo a full stat to make sure.
2623 * Fixes SF python bug 1493322, pybsddb bug 1184012
2624 */
2625 if (size == 0 && (flags & DB_FAST_STAT)) {
2626 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002627 if (!err)
2628 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002629 goto redo_stat_for_length;
2630 }
2631
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002632 MYDB_END_ALLOW_THREADS;
2633
2634 if (err)
2635 return -1;
2636
2637 self->haveStat = 1;
2638
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002639 free(sp);
2640 return size;
2641}
2642
2643
2644PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2645{
2646 int err;
2647 PyObject* retval;
2648 DBT key;
2649 DBT data;
2650
2651 CHECK_DB_NOT_CLOSED(self);
2652 if (!make_key_dbt(self, keyobj, &key, NULL))
2653 return NULL;
2654
2655 CLEAR_DBT(data);
2656 if (CHECK_DBFLAG(self, DB_THREAD)) {
2657 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2658 data.flags = DB_DBT_MALLOC;
2659 }
2660 MYDB_BEGIN_ALLOW_THREADS;
2661 err = self->db->get(self->db, NULL, &key, &data, 0);
2662 MYDB_END_ALLOW_THREADS;
2663 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2664 PyErr_SetObject(PyExc_KeyError, keyobj);
2665 retval = NULL;
2666 }
2667 else if (makeDBError(err)) {
2668 retval = NULL;
2669 }
2670 else {
2671 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2672 FREE_DBT(data);
2673 }
2674
2675 FREE_DBT(key);
2676 return retval;
2677}
2678
2679
2680static int
2681DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2682{
2683 DBT key, data;
2684 int retval;
2685 int flags = 0;
2686
2687 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002688 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2689 PyErr_SetObject(DBError, t);
2690 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002691 return -1;
2692 }
2693
2694 if (!make_key_dbt(self, keyobj, &key, NULL))
2695 return -1;
2696
2697 if (dataobj != NULL) {
2698 if (!make_dbt(dataobj, &data))
2699 retval = -1;
2700 else {
2701 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002702 /* dictionaries shouldn't have duplicate keys */
2703 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704 retval = _DB_put(self, NULL, &key, &data, flags);
2705
2706 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002707 /* try deleting any old record that matches and then PUT it
2708 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 _DB_delete(self, NULL, &key, 0);
2710 PyErr_Clear();
2711 retval = _DB_put(self, NULL, &key, &data, flags);
2712 }
2713 }
2714 }
2715 else {
2716 /* dataobj == NULL, so delete the key */
2717 retval = _DB_delete(self, NULL, &key, 0);
2718 }
2719 FREE_DBT(key);
2720 return retval;
2721}
2722
2723
2724static PyObject*
2725DB_has_key(DBObject* self, PyObject* args)
2726{
2727 int err;
2728 PyObject* keyobj;
2729 DBT key, data;
2730 PyObject* txnobj = NULL;
2731 DB_TXN *txn = NULL;
2732
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002733 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 return NULL;
2735 CHECK_DB_NOT_CLOSED(self);
2736 if (!make_key_dbt(self, keyobj, &key, NULL))
2737 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002738 if (!checkTxnObj(txnobj, &txn)) {
2739 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002741 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002742
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002743 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 it has a record but can't allocate a buffer for the data. This saves
2745 having to deal with data we won't be using.
2746 */
2747 CLEAR_DBT(data);
2748 data.flags = DB_DBT_USERMEM;
2749
2750 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002751 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002752 MYDB_END_ALLOW_THREADS;
2753 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002754
2755 if (err == DB_BUFFER_SMALL || err == 0) {
2756 return PyInt_FromLong(1);
2757 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2758 return PyInt_FromLong(0);
2759 }
2760
2761 makeDBError(err);
2762 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002763}
2764
2765
2766#define _KEYS_LIST 1
2767#define _VALUES_LIST 2
2768#define _ITEMS_LIST 3
2769
2770static PyObject*
2771_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2772{
2773 int err, dbtype;
2774 DBT key;
2775 DBT data;
2776 DBC *cursor;
2777 PyObject* list;
2778 PyObject* item = NULL;
2779
2780 CHECK_DB_NOT_CLOSED(self);
2781 CLEAR_DBT(key);
2782 CLEAR_DBT(data);
2783
2784 dbtype = _DB_get_type(self);
2785 if (dbtype == -1)
2786 return NULL;
2787
2788 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002789 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002790 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002791
2792 /* get a cursor */
2793 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002794 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002795 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002796 if (makeDBError(err)) {
2797 Py_DECREF(list);
2798 return NULL;
2799 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002800
2801 if (CHECK_DBFLAG(self, DB_THREAD)) {
2802 key.flags = DB_DBT_REALLOC;
2803 data.flags = DB_DBT_REALLOC;
2804 }
2805
2806 while (1) { /* use the cursor to traverse the DB, collecting items */
2807 MYDB_BEGIN_ALLOW_THREADS;
2808 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2809 MYDB_END_ALLOW_THREADS;
2810
2811 if (err) {
2812 /* for any error, break out of the loop */
2813 break;
2814 }
2815
2816 switch (type) {
2817 case _KEYS_LIST:
2818 switch(dbtype) {
2819 case DB_BTREE:
2820 case DB_HASH:
2821 default:
2822 item = PyString_FromStringAndSize((char*)key.data, key.size);
2823 break;
2824 case DB_RECNO:
2825 case DB_QUEUE:
2826 item = PyInt_FromLong(*((db_recno_t*)key.data));
2827 break;
2828 }
2829 break;
2830
2831 case _VALUES_LIST:
2832 item = PyString_FromStringAndSize((char*)data.data, data.size);
2833 break;
2834
2835 case _ITEMS_LIST:
2836 switch(dbtype) {
2837 case DB_BTREE:
2838 case DB_HASH:
2839 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002840 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2841 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002842 break;
2843 case DB_RECNO:
2844 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002845 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2846 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 break;
2848 }
2849 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002850 default:
2851 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2852 item = NULL;
2853 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 }
2855 if (item == NULL) {
2856 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 list = NULL;
2858 goto done;
2859 }
2860 PyList_Append(list, item);
2861 Py_DECREF(item);
2862 }
2863
Gregory P. Smithe9477062005-06-04 06:46:59 +00002864 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2865 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 Py_DECREF(list);
2867 list = NULL;
2868 }
2869
2870 done:
2871 FREE_DBT(key);
2872 FREE_DBT(data);
2873 MYDB_BEGIN_ALLOW_THREADS;
2874 cursor->c_close(cursor);
2875 MYDB_END_ALLOW_THREADS;
2876 return list;
2877}
2878
2879
2880static PyObject*
2881DB_keys(DBObject* self, PyObject* args)
2882{
2883 PyObject* txnobj = NULL;
2884 DB_TXN *txn = NULL;
2885
Georg Brandl96a8c392006-05-29 21:04:52 +00002886 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002887 return NULL;
2888 if (!checkTxnObj(txnobj, &txn))
2889 return NULL;
2890 return _DB_make_list(self, txn, _KEYS_LIST);
2891}
2892
2893
2894static PyObject*
2895DB_items(DBObject* self, PyObject* args)
2896{
2897 PyObject* txnobj = NULL;
2898 DB_TXN *txn = NULL;
2899
Georg Brandl96a8c392006-05-29 21:04:52 +00002900 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901 return NULL;
2902 if (!checkTxnObj(txnobj, &txn))
2903 return NULL;
2904 return _DB_make_list(self, txn, _ITEMS_LIST);
2905}
2906
2907
2908static PyObject*
2909DB_values(DBObject* self, PyObject* args)
2910{
2911 PyObject* txnobj = NULL;
2912 DB_TXN *txn = NULL;
2913
Georg Brandl96a8c392006-05-29 21:04:52 +00002914 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915 return NULL;
2916 if (!checkTxnObj(txnobj, &txn))
2917 return NULL;
2918 return _DB_make_list(self, txn, _VALUES_LIST);
2919}
2920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002921/* --------------------------------------------------------------------- */
2922/* DBCursor methods */
2923
2924
2925static PyObject*
2926DBC_close(DBCursorObject* self, PyObject* args)
2927{
2928 int err = 0;
2929
2930 if (!PyArg_ParseTuple(args, ":close"))
2931 return NULL;
2932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002933 if (self->dbc != NULL) {
2934 MYDB_BEGIN_ALLOW_THREADS;
2935 err = self->dbc->c_close(self->dbc);
2936 self->dbc = NULL;
2937 MYDB_END_ALLOW_THREADS;
2938 }
2939 RETURN_IF_ERR();
2940 RETURN_NONE();
2941}
2942
2943
2944static PyObject*
2945DBC_count(DBCursorObject* self, PyObject* args)
2946{
2947 int err = 0;
2948 db_recno_t count;
2949 int flags = 0;
2950
2951 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2952 return NULL;
2953
2954 CHECK_CURSOR_NOT_CLOSED(self);
2955
2956 MYDB_BEGIN_ALLOW_THREADS;
2957 err = self->dbc->c_count(self->dbc, &count, flags);
2958 MYDB_END_ALLOW_THREADS;
2959 RETURN_IF_ERR();
2960
2961 return PyInt_FromLong(count);
2962}
2963
2964
2965static PyObject*
2966DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2967{
2968 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2969}
2970
2971
2972static PyObject*
2973DBC_delete(DBCursorObject* self, PyObject* args)
2974{
2975 int err, flags=0;
2976
2977 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2978 return NULL;
2979
2980 CHECK_CURSOR_NOT_CLOSED(self);
2981
2982 MYDB_BEGIN_ALLOW_THREADS;
2983 err = self->dbc->c_del(self->dbc, flags);
2984 MYDB_END_ALLOW_THREADS;
2985 RETURN_IF_ERR();
2986
2987 self->mydb->haveStat = 0;
2988 RETURN_NONE();
2989}
2990
2991
2992static PyObject*
2993DBC_dup(DBCursorObject* self, PyObject* args)
2994{
2995 int err, flags =0;
2996 DBC* dbc = NULL;
2997
2998 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2999 return NULL;
3000
3001 CHECK_CURSOR_NOT_CLOSED(self);
3002
3003 MYDB_BEGIN_ALLOW_THREADS;
3004 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3005 MYDB_END_ALLOW_THREADS;
3006 RETURN_IF_ERR();
3007
3008 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3009}
3010
3011static PyObject*
3012DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3013{
3014 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3015}
3016
3017
3018static PyObject*
3019DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3020{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003021 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003022 PyObject* keyobj = NULL;
3023 PyObject* dataobj = NULL;
3024 PyObject* retval = NULL;
3025 int dlen = -1;
3026 int doff = -1;
3027 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003028 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003029 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030
3031 CLEAR_DBT(key);
3032 CLEAR_DBT(data);
3033 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003034 &flags, &dlen, &doff))
3035 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3038 &kwnames[1],
3039 &keyobj, &flags, &dlen, &doff))
3040 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003041 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3043 kwnames, &keyobj, &dataobj,
3044 &flags, &dlen, &doff))
3045 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046 return NULL;
3047 }
3048 }
3049 }
3050
3051 CHECK_CURSOR_NOT_CLOSED(self);
3052
3053 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3054 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003055 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3056 (!add_partial_dbt(&data, dlen, doff)) )
3057 {
3058 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003060 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003061
3062 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3063 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003064 if (!(key.flags & DB_DBT_REALLOC)) {
3065 key.flags |= DB_DBT_MALLOC;
3066 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 }
3068
3069 MYDB_BEGIN_ALLOW_THREADS;
3070 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3071 MYDB_END_ALLOW_THREADS;
3072
Gregory P. Smithe9477062005-06-04 06:46:59 +00003073 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3074 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003075 Py_INCREF(Py_None);
3076 retval = Py_None;
3077 }
3078 else if (makeDBError(err)) {
3079 retval = NULL;
3080 }
3081 else {
3082 switch (_DB_get_type(self->mydb)) {
3083 case -1:
3084 retval = NULL;
3085 break;
3086 case DB_BTREE:
3087 case DB_HASH:
3088 default:
3089 retval = Py_BuildValue("s#s#", key.data, key.size,
3090 data.data, data.size);
3091 break;
3092 case DB_RECNO:
3093 case DB_QUEUE:
3094 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3095 data.data, data.size);
3096 break;
3097 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003098 FREE_DBT(data);
3099 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003100 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003101 return retval;
3102}
3103
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003104#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003105static PyObject*
3106DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3107{
3108 int err, flags=0;
3109 PyObject* keyobj = NULL;
3110 PyObject* dataobj = NULL;
3111 PyObject* retval = NULL;
3112 int dlen = -1;
3113 int doff = -1;
3114 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003115 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3116 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003117
3118 CLEAR_DBT(key);
3119 CLEAR_DBT(data);
3120 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3121 &flags, &dlen, &doff))
3122 {
3123 PyErr_Clear();
3124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003125 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003126 &keyobj, &flags, &dlen, &doff))
3127 {
3128 PyErr_Clear();
3129 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3130 kwnames, &keyobj, &dataobj,
3131 &flags, &dlen, &doff))
3132 {
3133 return NULL;
3134 }
3135 }
3136 }
3137
3138 CHECK_CURSOR_NOT_CLOSED(self);
3139
3140 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3141 return NULL;
3142 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3143 (!add_partial_dbt(&data, dlen, doff)) ) {
3144 FREE_DBT(key);
3145 return NULL;
3146 }
3147
3148 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3149 data.flags = DB_DBT_MALLOC;
3150 if (!(key.flags & DB_DBT_REALLOC)) {
3151 key.flags |= DB_DBT_MALLOC;
3152 }
3153 }
3154
3155 CLEAR_DBT(pkey);
3156 pkey.flags = DB_DBT_MALLOC;
3157
3158 MYDB_BEGIN_ALLOW_THREADS;
3159 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3160 MYDB_END_ALLOW_THREADS;
3161
Gregory P. Smithe9477062005-06-04 06:46:59 +00003162 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3163 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003164 Py_INCREF(Py_None);
3165 retval = Py_None;
3166 }
3167 else if (makeDBError(err)) {
3168 retval = NULL;
3169 }
3170 else {
3171 PyObject *pkeyObj;
3172 PyObject *dataObj;
3173 dataObj = PyString_FromStringAndSize(data.data, data.size);
3174
3175 if (self->mydb->primaryDBType == DB_RECNO ||
3176 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003177 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003178 else
3179 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3180
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003181 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003182 {
3183 PyObject *keyObj;
3184 int type = _DB_get_type(self->mydb);
3185 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003186 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003187 else
3188 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003189#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003190 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003191#else
3192 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3193#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003194 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003195 FREE_DBT(key);
3196 }
3197 else /* return just the pkey and data */
3198 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003199#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003200 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003201#else
3202 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3203#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003204 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003205 Py_DECREF(dataObj);
3206 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003207 FREE_DBT(pkey);
3208 FREE_DBT(data);
3209 }
3210 /* the only time REALLOC should be set is if we used an integer
3211 * key that make_key_dbt malloc'd for us. always free these. */
3212 if (key.flags & DB_DBT_REALLOC) {
3213 FREE_DBT(key);
3214 }
3215 return retval;
3216}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003217#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003219
3220static PyObject*
3221DBC_get_recno(DBCursorObject* self, PyObject* args)
3222{
3223 int err;
3224 db_recno_t recno;
3225 DBT key;
3226 DBT data;
3227
3228 if (!PyArg_ParseTuple(args, ":get_recno"))
3229 return NULL;
3230
3231 CHECK_CURSOR_NOT_CLOSED(self);
3232
3233 CLEAR_DBT(key);
3234 CLEAR_DBT(data);
3235 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3236 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3237 data.flags = DB_DBT_MALLOC;
3238 key.flags = DB_DBT_MALLOC;
3239 }
3240
3241 MYDB_BEGIN_ALLOW_THREADS;
3242 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3243 MYDB_END_ALLOW_THREADS;
3244 RETURN_IF_ERR();
3245
3246 recno = *((db_recno_t*)data.data);
3247 FREE_DBT(key);
3248 FREE_DBT(data);
3249 return PyInt_FromLong(recno);
3250}
3251
3252
3253static PyObject*
3254DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3255{
3256 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3257}
3258
3259
3260static PyObject*
3261DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3262{
3263 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3264}
3265
3266
3267static PyObject*
3268DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3269{
3270 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3271}
3272
3273
3274static PyObject*
3275DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3276{
3277 int err, flags = 0;
3278 PyObject* keyobj, *dataobj;
3279 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003280 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003281 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003282 int dlen = -1;
3283 int doff = -1;
3284
3285 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3286 &keyobj, &dataobj, &flags, &dlen, &doff))
3287 return NULL;
3288
3289 CHECK_CURSOR_NOT_CLOSED(self);
3290
3291 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3292 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003293 if (!make_dbt(dataobj, &data) ||
3294 !add_partial_dbt(&data, dlen, doff) )
3295 {
3296 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003297 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003298 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003299
3300 MYDB_BEGIN_ALLOW_THREADS;
3301 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3302 MYDB_END_ALLOW_THREADS;
3303 FREE_DBT(key);
3304 RETURN_IF_ERR();
3305 self->mydb->haveStat = 0;
3306 RETURN_NONE();
3307}
3308
3309
3310static PyObject*
3311DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3312{
3313 int err, flags = 0;
3314 DBT key, data;
3315 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003316 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003317 int dlen = -1;
3318 int doff = -1;
3319
3320 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3321 &keyobj, &flags, &dlen, &doff))
3322 return NULL;
3323
3324 CHECK_CURSOR_NOT_CLOSED(self);
3325
3326 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3327 return NULL;
3328
3329 CLEAR_DBT(data);
3330 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3331 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3332 data.flags = DB_DBT_MALLOC;
3333 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003334 if (!add_partial_dbt(&data, dlen, doff)) {
3335 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003336 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003337 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003338
3339 MYDB_BEGIN_ALLOW_THREADS;
3340 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3341 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003342 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3343 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003344 Py_INCREF(Py_None);
3345 retval = Py_None;
3346 }
3347 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348 retval = NULL;
3349 }
3350 else {
3351 switch (_DB_get_type(self->mydb)) {
3352 case -1:
3353 retval = NULL;
3354 break;
3355 case DB_BTREE:
3356 case DB_HASH:
3357 default:
3358 retval = Py_BuildValue("s#s#", key.data, key.size,
3359 data.data, data.size);
3360 break;
3361 case DB_RECNO:
3362 case DB_QUEUE:
3363 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3364 data.data, data.size);
3365 break;
3366 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003367 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003368 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003369 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003370 /* the only time REALLOC should be set is if we used an integer
3371 * key that make_key_dbt malloc'd for us. always free these. */
3372 if (key.flags & DB_DBT_REALLOC) {
3373 FREE_DBT(key);
3374 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003375
3376 return retval;
3377}
3378
3379
3380static PyObject*
3381DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3382{
3383 int err, flags = 0;
3384 DBT key, data;
3385 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003386 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003387 int dlen = -1;
3388 int doff = -1;
3389
3390 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3391 &keyobj, &flags, &dlen, &doff))
3392 return NULL;
3393
3394 CHECK_CURSOR_NOT_CLOSED(self);
3395
3396 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3397 return NULL;
3398
3399 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003400 if (!add_partial_dbt(&data, dlen, doff)) {
3401 FREE_DBT(key);
3402 return NULL;
3403 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003404 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3405 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003406 data.flags |= DB_DBT_MALLOC;
3407 /* only BTREE databases will return anything in the key */
3408 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3409 key.flags |= DB_DBT_MALLOC;
3410 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3414 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3416 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003417 Py_INCREF(Py_None);
3418 retval = Py_None;
3419 }
3420 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003421 retval = NULL;
3422 }
3423 else {
3424 switch (_DB_get_type(self->mydb)) {
3425 case -1:
3426 retval = NULL;
3427 break;
3428 case DB_BTREE:
3429 case DB_HASH:
3430 default:
3431 retval = Py_BuildValue("s#s#", key.data, key.size,
3432 data.data, data.size);
3433 break;
3434 case DB_RECNO:
3435 case DB_QUEUE:
3436 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3437 data.data, data.size);
3438 break;
3439 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003440 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003441 FREE_DBT(data);
3442 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003443 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003444 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003445 if (key.flags & DB_DBT_REALLOC) {
3446 FREE_DBT(key);
3447 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448
3449 return retval;
3450}
3451
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003452static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003453_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3454 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003455{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003456 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003458 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459
Gregory P. Smith7441e652003-11-03 21:35:31 +00003460 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3462 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003463 if (!make_dbt(dataobj, &data)) {
3464 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003465 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003466 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467
3468 MYDB_BEGIN_ALLOW_THREADS;
3469 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3470 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003471 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003472 Py_INCREF(Py_None);
3473 retval = Py_None;
3474 }
3475 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003476 retval = NULL;
3477 }
3478 else {
3479 switch (_DB_get_type(self->mydb)) {
3480 case -1:
3481 retval = NULL;
3482 break;
3483 case DB_BTREE:
3484 case DB_HASH:
3485 default:
3486 retval = Py_BuildValue("s#s#", key.data, key.size,
3487 data.data, data.size);
3488 break;
3489 case DB_RECNO:
3490 case DB_QUEUE:
3491 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3492 data.data, data.size);
3493 break;
3494 }
3495 }
3496
3497 FREE_DBT(key);
3498 return retval;
3499}
3500
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003501static PyObject*
3502DBC_get_both(DBCursorObject* self, PyObject* args)
3503{
3504 int flags=0;
3505 PyObject *keyobj, *dataobj;
3506
3507 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3508 return NULL;
3509
Gregory P. Smith7441e652003-11-03 21:35:31 +00003510 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003511 CHECK_CURSOR_NOT_CLOSED(self);
3512
3513 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3514 self->mydb->moduleFlags.getReturnsNone);
3515}
3516
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003517/* Return size of entry */
3518static PyObject*
3519DBC_get_current_size(DBCursorObject* self, PyObject* args)
3520{
3521 int err, flags=DB_CURRENT;
3522 PyObject* retval = NULL;
3523 DBT key, data;
3524
3525 if (!PyArg_ParseTuple(args, ":get_current_size"))
3526 return NULL;
3527 CHECK_CURSOR_NOT_CLOSED(self);
3528 CLEAR_DBT(key);
3529 CLEAR_DBT(data);
3530
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003531 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003532 getting the record size. */
3533 data.flags = DB_DBT_USERMEM;
3534 data.ulen = 0;
3535 MYDB_BEGIN_ALLOW_THREADS;
3536 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3537 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003538 if (err == DB_BUFFER_SMALL || !err) {
3539 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003540 retval = PyInt_FromLong((long)data.size);
3541 err = 0;
3542 }
3543
3544 FREE_DBT(key);
3545 FREE_DBT(data);
3546 RETURN_IF_ERR();
3547 return retval;
3548}
3549
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003550static PyObject*
3551DBC_set_both(DBCursorObject* self, PyObject* args)
3552{
3553 int flags=0;
3554 PyObject *keyobj, *dataobj;
3555
3556 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3557 return NULL;
3558
Gregory P. Smith7441e652003-11-03 21:35:31 +00003559 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003560 CHECK_CURSOR_NOT_CLOSED(self);
3561
3562 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3563 self->mydb->moduleFlags.cursorSetReturnsNone);
3564}
3565
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566
3567static PyObject*
3568DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3569{
3570 int err, irecno, flags=0;
3571 db_recno_t recno;
3572 DBT key, data;
3573 PyObject* retval;
3574 int dlen = -1;
3575 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003576 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577
3578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3579 &irecno, &flags, &dlen, &doff))
3580 return NULL;
3581
3582 CHECK_CURSOR_NOT_CLOSED(self);
3583
3584 CLEAR_DBT(key);
3585 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003586 /* use allocated space so DB will be able to realloc room for the real
3587 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 key.data = malloc(sizeof(db_recno_t));
3589 if (key.data == NULL) {
3590 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3591 return NULL;
3592 }
3593 key.size = sizeof(db_recno_t);
3594 key.ulen = key.size;
3595 memcpy(key.data, &recno, sizeof(db_recno_t));
3596 key.flags = DB_DBT_REALLOC;
3597
3598 CLEAR_DBT(data);
3599 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3600 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3601 data.flags = DB_DBT_MALLOC;
3602 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003603 if (!add_partial_dbt(&data, dlen, doff)) {
3604 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003605 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003606 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003607
3608 MYDB_BEGIN_ALLOW_THREADS;
3609 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3610 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003611 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3612 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003613 Py_INCREF(Py_None);
3614 retval = Py_None;
3615 }
3616 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003617 retval = NULL;
3618 }
3619 else { /* Can only be used for BTrees, so no need to return int key */
3620 retval = Py_BuildValue("s#s#", key.data, key.size,
3621 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003622 FREE_DBT(data);
3623 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003624 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003625
3626 return retval;
3627}
3628
3629
3630static PyObject*
3631DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3632{
3633 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3634}
3635
3636
3637static PyObject*
3638DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3639{
3640 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3641}
3642
3643
3644static PyObject*
3645DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3646{
3647 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3648}
3649
3650
3651static PyObject*
3652DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3653{
3654 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3655}
3656
3657
3658static PyObject*
3659DBC_join_item(DBCursorObject* self, PyObject* args)
3660{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003661 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003662 DBT key, data;
3663 PyObject* retval;
3664
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003666 return NULL;
3667
3668 CHECK_CURSOR_NOT_CLOSED(self);
3669
3670 CLEAR_DBT(key);
3671 CLEAR_DBT(data);
3672 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3673 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3674 key.flags = DB_DBT_MALLOC;
3675 }
3676
3677 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003678 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003679 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003680 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3681 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003682 Py_INCREF(Py_None);
3683 retval = Py_None;
3684 }
3685 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686 retval = NULL;
3687 }
3688 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003689 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 FREE_DBT(key);
3691 }
3692
3693 return retval;
3694}
3695
3696
3697
3698/* --------------------------------------------------------------------- */
3699/* DBEnv methods */
3700
3701
3702static PyObject*
3703DBEnv_close(DBEnvObject* self, PyObject* args)
3704{
3705 int err, flags = 0;
3706
3707 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3708 return NULL;
3709 if (!self->closed) { /* Don't close more than once */
3710 MYDB_BEGIN_ALLOW_THREADS;
3711 err = self->db_env->close(self->db_env, flags);
3712 MYDB_END_ALLOW_THREADS;
3713 /* after calling DBEnv->close, regardless of error, this DBEnv
3714 * may not be accessed again (BerkeleyDB docs). */
3715 self->closed = 1;
3716 self->db_env = NULL;
3717 RETURN_IF_ERR();
3718 }
3719 RETURN_NONE();
3720}
3721
3722
3723static PyObject*
3724DBEnv_open(DBEnvObject* self, PyObject* args)
3725{
3726 int err, flags=0, mode=0660;
3727 char *db_home;
3728
3729 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3730 return NULL;
3731
3732 CHECK_ENV_NOT_CLOSED(self);
3733
3734 MYDB_BEGIN_ALLOW_THREADS;
3735 err = self->db_env->open(self->db_env, db_home, flags, mode);
3736 MYDB_END_ALLOW_THREADS;
3737 RETURN_IF_ERR();
3738 self->closed = 0;
3739 self->flags = flags;
3740 RETURN_NONE();
3741}
3742
3743
3744static PyObject*
3745DBEnv_remove(DBEnvObject* self, PyObject* args)
3746{
3747 int err, flags=0;
3748 char *db_home;
3749
3750 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3751 return NULL;
3752 CHECK_ENV_NOT_CLOSED(self);
3753 MYDB_BEGIN_ALLOW_THREADS;
3754 err = self->db_env->remove(self->db_env, db_home, flags);
3755 MYDB_END_ALLOW_THREADS;
3756 RETURN_IF_ERR();
3757 RETURN_NONE();
3758}
3759
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003760#if (DBVER >= 41)
3761static PyObject*
3762DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3763{
3764 int err;
3765 u_int32_t flags=0;
3766 char *file = NULL;
3767 char *database = NULL;
3768 PyObject *txnobj = NULL;
3769 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003770 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003771 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003772
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003773 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003774 &file, &database, &txnobj, &flags)) {
3775 return NULL;
3776 }
3777 if (!checkTxnObj(txnobj, &txn)) {
3778 return NULL;
3779 }
3780 CHECK_ENV_NOT_CLOSED(self);
3781 MYDB_BEGIN_ALLOW_THREADS;
3782 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3783 MYDB_END_ALLOW_THREADS;
3784 RETURN_IF_ERR();
3785 RETURN_NONE();
3786}
3787
3788static PyObject*
3789DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3790{
3791 int err;
3792 u_int32_t flags=0;
3793 char *file = NULL;
3794 char *database = NULL;
3795 char *newname = NULL;
3796 PyObject *txnobj = NULL;
3797 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003798 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003799 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003800
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003802 &file, &database, &newname, &txnobj, &flags)) {
3803 return NULL;
3804 }
3805 if (!checkTxnObj(txnobj, &txn)) {
3806 return NULL;
3807 }
3808 CHECK_ENV_NOT_CLOSED(self);
3809 MYDB_BEGIN_ALLOW_THREADS;
3810 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3811 flags);
3812 MYDB_END_ALLOW_THREADS;
3813 RETURN_IF_ERR();
3814 RETURN_NONE();
3815}
3816
3817static PyObject*
3818DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3819{
3820 int err;
3821 u_int32_t flags=0;
3822 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003823 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003824
3825 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3826 &passwd, &flags)) {
3827 return NULL;
3828 }
3829
3830 MYDB_BEGIN_ALLOW_THREADS;
3831 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3832 MYDB_END_ALLOW_THREADS;
3833
3834 RETURN_IF_ERR();
3835 RETURN_NONE();
3836}
3837#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003838
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003839#if (DBVER >= 40)
3840static PyObject*
3841DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3842{
3843 int err;
3844 u_int32_t flags=0;
3845 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003846 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003847
3848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3849 &timeout, &flags)) {
3850 return NULL;
3851 }
3852
3853 MYDB_BEGIN_ALLOW_THREADS;
3854 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3855 MYDB_END_ALLOW_THREADS;
3856
3857 RETURN_IF_ERR();
3858 RETURN_NONE();
3859}
3860#endif /* DBVER >= 40 */
3861
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003862static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003863DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3864{
3865 int err;
3866 long shm_key = 0;
3867
3868 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3869 return NULL;
3870 CHECK_ENV_NOT_CLOSED(self);
3871
3872 err = self->db_env->set_shm_key(self->db_env, shm_key);
3873 RETURN_IF_ERR();
3874 RETURN_NONE();
3875}
3876
3877static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003878DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3879{
3880 int err, gbytes=0, bytes=0, ncache=0;
3881
3882 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3883 &gbytes, &bytes, &ncache))
3884 return NULL;
3885 CHECK_ENV_NOT_CLOSED(self);
3886
3887 MYDB_BEGIN_ALLOW_THREADS;
3888 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3889 MYDB_END_ALLOW_THREADS;
3890 RETURN_IF_ERR();
3891 RETURN_NONE();
3892}
3893
3894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003895static PyObject*
3896DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3897{
3898 int err, flags=0, onoff=0;
3899
3900 if (!PyArg_ParseTuple(args, "ii:set_flags",
3901 &flags, &onoff))
3902 return NULL;
3903 CHECK_ENV_NOT_CLOSED(self);
3904
3905 MYDB_BEGIN_ALLOW_THREADS;
3906 err = self->db_env->set_flags(self->db_env, flags, onoff);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3910}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003911
3912
3913static PyObject*
3914DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3915{
3916 int err;
3917 char *dir;
3918
3919 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3920 return NULL;
3921 CHECK_ENV_NOT_CLOSED(self);
3922
3923 MYDB_BEGIN_ALLOW_THREADS;
3924 err = self->db_env->set_data_dir(self->db_env, dir);
3925 MYDB_END_ALLOW_THREADS;
3926 RETURN_IF_ERR();
3927 RETURN_NONE();
3928}
3929
3930
3931static PyObject*
3932DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3933{
3934 int err, lg_bsize;
3935
3936 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3937 return NULL;
3938 CHECK_ENV_NOT_CLOSED(self);
3939
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3942 MYDB_END_ALLOW_THREADS;
3943 RETURN_IF_ERR();
3944 RETURN_NONE();
3945}
3946
3947
3948static PyObject*
3949DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3950{
3951 int err;
3952 char *dir;
3953
3954 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3955 return NULL;
3956 CHECK_ENV_NOT_CLOSED(self);
3957
3958 MYDB_BEGIN_ALLOW_THREADS;
3959 err = self->db_env->set_lg_dir(self->db_env, dir);
3960 MYDB_END_ALLOW_THREADS;
3961 RETURN_IF_ERR();
3962 RETURN_NONE();
3963}
3964
3965static PyObject*
3966DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3967{
3968 int err, lg_max;
3969
3970 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3971 return NULL;
3972 CHECK_ENV_NOT_CLOSED(self);
3973
3974 MYDB_BEGIN_ALLOW_THREADS;
3975 err = self->db_env->set_lg_max(self->db_env, lg_max);
3976 MYDB_END_ALLOW_THREADS;
3977 RETURN_IF_ERR();
3978 RETURN_NONE();
3979}
3980
3981
Neal Norwitz84562352005-10-20 04:30:15 +00003982#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003983static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00003984DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3985{
3986 int err, lg_max;
3987
3988 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3989 return NULL;
3990 CHECK_ENV_NOT_CLOSED(self);
3991
3992 MYDB_BEGIN_ALLOW_THREADS;
3993 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3994 MYDB_END_ALLOW_THREADS;
3995 RETURN_IF_ERR();
3996 RETURN_NONE();
3997}
Neal Norwitz84562352005-10-20 04:30:15 +00003998#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00003999
4000
4001static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004002DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4003{
4004 int err, lk_detect;
4005
4006 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4007 return NULL;
4008 CHECK_ENV_NOT_CLOSED(self);
4009
4010 MYDB_BEGIN_ALLOW_THREADS;
4011 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4012 MYDB_END_ALLOW_THREADS;
4013 RETURN_IF_ERR();
4014 RETURN_NONE();
4015}
4016
4017
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004018#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004019static PyObject*
4020DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4021{
4022 int err, max;
4023
4024 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4025 return NULL;
4026 CHECK_ENV_NOT_CLOSED(self);
4027
4028 MYDB_BEGIN_ALLOW_THREADS;
4029 err = self->db_env->set_lk_max(self->db_env, max);
4030 MYDB_END_ALLOW_THREADS;
4031 RETURN_IF_ERR();
4032 RETURN_NONE();
4033}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004034#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004035
4036
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004037
4038static PyObject*
4039DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4040{
4041 int err, max;
4042
4043 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4044 return NULL;
4045 CHECK_ENV_NOT_CLOSED(self);
4046
4047 MYDB_BEGIN_ALLOW_THREADS;
4048 err = self->db_env->set_lk_max_locks(self->db_env, max);
4049 MYDB_END_ALLOW_THREADS;
4050 RETURN_IF_ERR();
4051 RETURN_NONE();
4052}
4053
4054
4055static PyObject*
4056DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4057{
4058 int err, max;
4059
4060 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4061 return NULL;
4062 CHECK_ENV_NOT_CLOSED(self);
4063
4064 MYDB_BEGIN_ALLOW_THREADS;
4065 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4066 MYDB_END_ALLOW_THREADS;
4067 RETURN_IF_ERR();
4068 RETURN_NONE();
4069}
4070
4071
4072static PyObject*
4073DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4074{
4075 int err, max;
4076
4077 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4078 return NULL;
4079 CHECK_ENV_NOT_CLOSED(self);
4080
4081 MYDB_BEGIN_ALLOW_THREADS;
4082 err = self->db_env->set_lk_max_objects(self->db_env, max);
4083 MYDB_END_ALLOW_THREADS;
4084 RETURN_IF_ERR();
4085 RETURN_NONE();
4086}
4087
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004088
4089static PyObject*
4090DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4091{
4092 int err, mp_mmapsize;
4093
4094 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4095 return NULL;
4096 CHECK_ENV_NOT_CLOSED(self);
4097
4098 MYDB_BEGIN_ALLOW_THREADS;
4099 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4100 MYDB_END_ALLOW_THREADS;
4101 RETURN_IF_ERR();
4102 RETURN_NONE();
4103}
4104
4105
4106static PyObject*
4107DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4108{
4109 int err;
4110 char *dir;
4111
4112 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4113 return NULL;
4114 CHECK_ENV_NOT_CLOSED(self);
4115
4116 MYDB_BEGIN_ALLOW_THREADS;
4117 err = self->db_env->set_tmp_dir(self->db_env, dir);
4118 MYDB_END_ALLOW_THREADS;
4119 RETURN_IF_ERR();
4120 RETURN_NONE();
4121}
4122
4123
4124static PyObject*
4125DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4126{
4127 int flags = 0;
4128 PyObject* txnobj = NULL;
4129 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004130 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004131
4132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4133 &txnobj, &flags))
4134 return NULL;
4135
4136 if (!checkTxnObj(txnobj, &txn))
4137 return NULL;
4138 CHECK_ENV_NOT_CLOSED(self);
4139
4140 return (PyObject*)newDBTxnObject(self, txn, flags);
4141}
4142
4143
4144static PyObject*
4145DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4146{
4147 int err, kbyte=0, min=0, flags=0;
4148
4149 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4150 return NULL;
4151 CHECK_ENV_NOT_CLOSED(self);
4152
4153 MYDB_BEGIN_ALLOW_THREADS;
4154#if (DBVER >= 40)
4155 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4156#else
4157 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4158#endif
4159 MYDB_END_ALLOW_THREADS;
4160 RETURN_IF_ERR();
4161 RETURN_NONE();
4162}
4163
4164
4165static PyObject*
4166DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4167{
4168 int err, max;
4169
4170 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4171 return NULL;
4172 CHECK_ENV_NOT_CLOSED(self);
4173
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004174 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004175 RETURN_IF_ERR();
4176 RETURN_NONE();
4177}
4178
4179
4180static PyObject*
4181DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4182{
4183 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004184 long stamp;
4185 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004186
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004187 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004188 return NULL;
4189 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004190 timestamp = (time_t)stamp;
4191 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004192 RETURN_IF_ERR();
4193 RETURN_NONE();
4194}
4195
4196
4197static PyObject*
4198DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4199{
4200 int err, atype, flags=0;
4201 int aborted = 0;
4202
4203 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4204 return NULL;
4205 CHECK_ENV_NOT_CLOSED(self);
4206
4207 MYDB_BEGIN_ALLOW_THREADS;
4208#if (DBVER >= 40)
4209 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4210#else
4211 err = lock_detect(self->db_env, flags, atype, &aborted);
4212#endif
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 return PyInt_FromLong(aborted);
4216}
4217
4218
4219static PyObject*
4220DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4221{
4222 int flags=0;
4223 int locker, lock_mode;
4224 DBT obj;
4225 PyObject* objobj;
4226
4227 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4228 return NULL;
4229
4230
4231 if (!make_dbt(objobj, &obj))
4232 return NULL;
4233
4234 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4235}
4236
4237
4238static PyObject*
4239DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4240{
4241 int err;
4242 u_int32_t theID;
4243
4244 if (!PyArg_ParseTuple(args, ":lock_id"))
4245 return NULL;
4246
4247 CHECK_ENV_NOT_CLOSED(self);
4248 MYDB_BEGIN_ALLOW_THREADS;
4249#if (DBVER >= 40)
4250 err = self->db_env->lock_id(self->db_env, &theID);
4251#else
4252 err = lock_id(self->db_env, &theID);
4253#endif
4254 MYDB_END_ALLOW_THREADS;
4255 RETURN_IF_ERR();
4256
4257 return PyInt_FromLong((long)theID);
4258}
4259
Gregory P. Smithac11e022007-11-05 02:56:31 +00004260#if (DBVER >= 40)
4261static PyObject*
4262DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4263{
4264 int err;
4265 u_int32_t theID;
4266
4267 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4268 return NULL;
4269
4270 CHECK_ENV_NOT_CLOSED(self);
4271 MYDB_BEGIN_ALLOW_THREADS;
4272 err = self->db_env->lock_id_free(self->db_env, theID);
4273 MYDB_END_ALLOW_THREADS;
4274 RETURN_IF_ERR();
4275 RETURN_NONE();
4276}
4277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004278
4279static PyObject*
4280DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4281{
4282 int err;
4283 DBLockObject* dblockobj;
4284
4285 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4286 return NULL;
4287
4288 CHECK_ENV_NOT_CLOSED(self);
4289 MYDB_BEGIN_ALLOW_THREADS;
4290#if (DBVER >= 40)
4291 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4292#else
4293 err = lock_put(self->db_env, &dblockobj->lock);
4294#endif
4295 MYDB_END_ALLOW_THREADS;
4296 RETURN_IF_ERR();
4297 RETURN_NONE();
4298}
4299
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004300#if (DBVER >= 44)
4301static PyObject*
4302DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4303{
4304 int err;
4305 char *file;
4306 u_int32_t flags = 0;
4307 static char* kwnames[] = { "file", "flags", NULL};
4308
4309 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4310 &file, &flags))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4313
4314 MYDB_BEGIN_ALLOW_THREADS;
4315 err = self->db_env->lsn_reset(self->db_env, file, flags);
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318 RETURN_NONE();
4319}
4320#endif /* DBVER >= 4.4 */
4321
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004322#if (DBVER >= 40)
4323static PyObject*
4324DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4325{
4326 int err;
4327 DB_LOG_STAT* statp = NULL;
4328 PyObject* d = NULL;
4329 u_int32_t flags = 0;
4330
4331 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4332 return NULL;
4333 CHECK_ENV_NOT_CLOSED(self);
4334
4335 MYDB_BEGIN_ALLOW_THREADS;
4336 err = self->db_env->log_stat(self->db_env, &statp, flags);
4337 MYDB_END_ALLOW_THREADS;
4338 RETURN_IF_ERR();
4339
4340 /* Turn the stat structure into a dictionary */
4341 d = PyDict_New();
4342 if (d == NULL) {
4343 if (statp)
4344 free(statp);
4345 return NULL;
4346 }
4347
4348#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4349
4350 MAKE_ENTRY(magic);
4351 MAKE_ENTRY(version);
4352 MAKE_ENTRY(mode);
4353 MAKE_ENTRY(lg_bsize);
4354#if (DBVER >= 44)
4355 MAKE_ENTRY(lg_size);
4356 MAKE_ENTRY(record);
4357#endif
4358#if (DBVER <= 40)
4359 MAKE_ENTRY(lg_max);
4360#endif
4361 MAKE_ENTRY(w_mbytes);
4362 MAKE_ENTRY(w_bytes);
4363 MAKE_ENTRY(wc_mbytes);
4364 MAKE_ENTRY(wc_bytes);
4365 MAKE_ENTRY(wcount);
4366 MAKE_ENTRY(wcount_fill);
4367#if (DBVER >= 44)
4368 MAKE_ENTRY(rcount);
4369#endif
4370 MAKE_ENTRY(scount);
4371 MAKE_ENTRY(cur_file);
4372 MAKE_ENTRY(cur_offset);
4373 MAKE_ENTRY(disk_file);
4374 MAKE_ENTRY(disk_offset);
4375 MAKE_ENTRY(maxcommitperflush);
4376 MAKE_ENTRY(mincommitperflush);
4377 MAKE_ENTRY(regsize);
4378 MAKE_ENTRY(region_wait);
4379 MAKE_ENTRY(region_nowait);
4380
4381#undef MAKE_ENTRY
4382 free(statp);
4383 return d;
4384} /* DBEnv_log_stat */
4385#endif /* DBVER >= 4.0 for log_stat method */
4386
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004387
4388static PyObject*
4389DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4390{
4391 int err;
4392 DB_LOCK_STAT* sp;
4393 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004394 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004395
4396 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4397 return NULL;
4398 CHECK_ENV_NOT_CLOSED(self);
4399
4400 MYDB_BEGIN_ALLOW_THREADS;
4401#if (DBVER >= 40)
4402 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4403#else
4404#if (DBVER >= 33)
4405 err = lock_stat(self->db_env, &sp);
4406#else
4407 err = lock_stat(self->db_env, &sp, NULL);
4408#endif
4409#endif
4410 MYDB_END_ALLOW_THREADS;
4411 RETURN_IF_ERR();
4412
4413 /* Turn the stat structure into a dictionary */
4414 d = PyDict_New();
4415 if (d == NULL) {
4416 free(sp);
4417 return NULL;
4418 }
4419
4420#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4421
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004422#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004423 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004424#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004425 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004426 MAKE_ENTRY(maxlocks);
4427 MAKE_ENTRY(maxlockers);
4428 MAKE_ENTRY(maxobjects);
4429 MAKE_ENTRY(nlocks);
4430 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004431 MAKE_ENTRY(nlockers);
4432 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004433 MAKE_ENTRY(nobjects);
4434 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004435 MAKE_ENTRY(nrequests);
4436 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004437#if (DBVER < 44)
4438 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004439 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004440#else
4441 MAKE_ENTRY(lock_nowait);
4442 MAKE_ENTRY(lock_wait);
4443#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004444 MAKE_ENTRY(ndeadlocks);
4445 MAKE_ENTRY(regsize);
4446 MAKE_ENTRY(region_wait);
4447 MAKE_ENTRY(region_nowait);
4448
4449#undef MAKE_ENTRY
4450 free(sp);
4451 return d;
4452}
4453
4454
4455static PyObject*
4456DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4457{
4458 int flags=0;
4459 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004460 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004461 PyObject* list;
4462 PyObject* item = NULL;
4463
4464 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4465 return NULL;
4466
4467 CHECK_ENV_NOT_CLOSED(self);
4468 MYDB_BEGIN_ALLOW_THREADS;
4469#if (DBVER >= 40)
4470 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4471#elif (DBVER == 33)
4472 err = log_archive(self->db_env, &log_list, flags);
4473#else
4474 err = log_archive(self->db_env, &log_list, flags, NULL);
4475#endif
4476 MYDB_END_ALLOW_THREADS;
4477 RETURN_IF_ERR();
4478
Gregory P. Smithbad47452006-06-05 00:33:35 +00004479 list = PyList_New(0);
4480 if (list == NULL) {
4481 if (log_list)
4482 free(log_list);
4483 return NULL;
4484 }
4485
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004486 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004487 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004488 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4489 item = PyString_FromString (*log_list);
4490 if (item == NULL) {
4491 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492 list = NULL;
4493 break;
4494 }
4495 PyList_Append(list, item);
4496 Py_DECREF(item);
4497 }
4498 free(log_list_start);
4499 }
4500 return list;
4501}
4502
4503
4504static PyObject*
4505DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4506{
4507 int err;
4508 DB_TXN_STAT* sp;
4509 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004510 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004511
4512 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4513 return NULL;
4514 CHECK_ENV_NOT_CLOSED(self);
4515
4516 MYDB_BEGIN_ALLOW_THREADS;
4517#if (DBVER >= 40)
4518 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4519#elif (DBVER == 33)
4520 err = txn_stat(self->db_env, &sp);
4521#else
4522 err = txn_stat(self->db_env, &sp, NULL);
4523#endif
4524 MYDB_END_ALLOW_THREADS;
4525 RETURN_IF_ERR();
4526
4527 /* Turn the stat structure into a dictionary */
4528 d = PyDict_New();
4529 if (d == NULL) {
4530 free(sp);
4531 return NULL;
4532 }
4533
4534#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004535#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004536
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004537 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538 MAKE_ENTRY(last_txnid);
4539 MAKE_ENTRY(maxtxns);
4540 MAKE_ENTRY(nactive);
4541 MAKE_ENTRY(maxnactive);
4542 MAKE_ENTRY(nbegins);
4543 MAKE_ENTRY(naborts);
4544 MAKE_ENTRY(ncommits);
4545 MAKE_ENTRY(regsize);
4546 MAKE_ENTRY(region_wait);
4547 MAKE_ENTRY(region_nowait);
4548
4549#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004550#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004551 free(sp);
4552 return d;
4553}
4554
4555
4556static PyObject*
4557DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4558{
4559 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004560 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561
4562 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4563 return NULL;
4564 CHECK_ENV_NOT_CLOSED(self);
4565
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004566 if (self->moduleFlags.getReturnsNone)
4567 ++oldValue;
4568 if (self->moduleFlags.cursorSetReturnsNone)
4569 ++oldValue;
4570 self->moduleFlags.getReturnsNone = (flags >= 1);
4571 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004572 return PyInt_FromLong(oldValue);
4573}
4574
4575
4576/* --------------------------------------------------------------------- */
4577/* DBTxn methods */
4578
4579
4580static PyObject*
4581DBTxn_commit(DBTxnObject* self, PyObject* args)
4582{
4583 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004584 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004585
4586 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4587 return NULL;
4588
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004589 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004590 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4591 "after txn_commit or txn_abort");
4592 PyErr_SetObject(DBError, t);
4593 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004594 return NULL;
4595 }
4596 txn = self->txn;
4597 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 MYDB_BEGIN_ALLOW_THREADS;
4599#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004600 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004601#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004602 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004603#endif
4604 MYDB_END_ALLOW_THREADS;
4605 RETURN_IF_ERR();
4606 RETURN_NONE();
4607}
4608
4609static PyObject*
4610DBTxn_prepare(DBTxnObject* self, PyObject* args)
4611{
4612#if (DBVER >= 33)
4613 int err;
4614 char* gid=NULL;
4615 int gid_size=0;
4616
4617 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4618 return NULL;
4619
4620 if (gid_size != DB_XIDDATASIZE) {
4621 PyErr_SetString(PyExc_TypeError,
4622 "gid must be DB_XIDDATASIZE bytes long");
4623 return NULL;
4624 }
4625
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004626 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004627 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4628 "after txn_commit or txn_abort");
4629 PyErr_SetObject(DBError, t);
4630 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004631 return NULL;
4632 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004633 MYDB_BEGIN_ALLOW_THREADS;
4634#if (DBVER >= 40)
4635 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4636#else
4637 err = txn_prepare(self->txn, (u_int8_t*)gid);
4638#endif
4639 MYDB_END_ALLOW_THREADS;
4640 RETURN_IF_ERR();
4641 RETURN_NONE();
4642#else
4643 int err;
4644
4645 if (!PyArg_ParseTuple(args, ":prepare"))
4646 return NULL;
4647
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004648 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004649 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4650 "after txn_commit or txn_abort");
4651 PyErr_SetObject(DBError, t);
4652 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004653 return NULL;
4654 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004655 MYDB_BEGIN_ALLOW_THREADS;
4656 err = txn_prepare(self->txn);
4657 MYDB_END_ALLOW_THREADS;
4658 RETURN_IF_ERR();
4659 RETURN_NONE();
4660#endif
4661}
4662
4663
4664static PyObject*
4665DBTxn_abort(DBTxnObject* self, PyObject* args)
4666{
4667 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004668 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004669
4670 if (!PyArg_ParseTuple(args, ":abort"))
4671 return NULL;
4672
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004673 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004674 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4675 "after txn_commit or txn_abort");
4676 PyErr_SetObject(DBError, t);
4677 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004678 return NULL;
4679 }
4680 txn = self->txn;
4681 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682 MYDB_BEGIN_ALLOW_THREADS;
4683#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004685#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004686 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687#endif
4688 MYDB_END_ALLOW_THREADS;
4689 RETURN_IF_ERR();
4690 RETURN_NONE();
4691}
4692
4693
4694static PyObject*
4695DBTxn_id(DBTxnObject* self, PyObject* args)
4696{
4697 int id;
4698
4699 if (!PyArg_ParseTuple(args, ":id"))
4700 return NULL;
4701
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004702 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004703 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4704 "after txn_commit or txn_abort");
4705 PyErr_SetObject(DBError, t);
4706 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004707 return NULL;
4708 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004709 MYDB_BEGIN_ALLOW_THREADS;
4710#if (DBVER >= 40)
4711 id = self->txn->id(self->txn);
4712#else
4713 id = txn_id(self->txn);
4714#endif
4715 MYDB_END_ALLOW_THREADS;
4716 return PyInt_FromLong(id);
4717}
4718
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004719#if (DBVER >= 43)
4720/* --------------------------------------------------------------------- */
4721/* DBSequence methods */
4722
4723
4724static PyObject*
4725DBSequence_close(DBSequenceObject* self, PyObject* args)
4726{
4727 int err, flags=0;
4728 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4729 return NULL;
4730 CHECK_SEQUENCE_NOT_CLOSED(self)
4731
4732 MYDB_BEGIN_ALLOW_THREADS
4733 err = self->sequence->close(self->sequence, flags);
4734 self->sequence = NULL;
4735 MYDB_END_ALLOW_THREADS
4736
4737 RETURN_IF_ERR();
4738
4739 RETURN_NONE();
4740}
4741
4742static PyObject*
4743DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4744{
4745 int err, flags = 0;
4746 int delta = 1;
4747 db_seq_t value;
4748 PyObject *txnobj = NULL;
4749 DB_TXN *txn = NULL;
4750 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4751 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4752 return NULL;
4753 CHECK_SEQUENCE_NOT_CLOSED(self)
4754
4755 if (!checkTxnObj(txnobj, &txn))
4756 return NULL;
4757
4758 MYDB_BEGIN_ALLOW_THREADS
4759 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4760 MYDB_END_ALLOW_THREADS
4761
4762 RETURN_IF_ERR();
4763 return PyLong_FromLongLong(value);
4764
4765}
4766
4767static PyObject*
4768DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4769{
4770 if (!PyArg_ParseTuple(args,":get_dbp"))
4771 return NULL;
4772 CHECK_SEQUENCE_NOT_CLOSED(self)
4773 Py_INCREF(self->mydb);
4774 return (PyObject* )self->mydb;
4775}
4776
4777static PyObject*
4778DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4779{
4780 int err;
4781 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00004782 PyObject *retval = NULL;
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004783 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004784 CHECK_SEQUENCE_NOT_CLOSED(self)
4785 MYDB_BEGIN_ALLOW_THREADS
4786 err = self->sequence->get_key(self->sequence, &key);
4787 MYDB_END_ALLOW_THREADS
4788
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004789 if (!err)
4790 retval = PyString_FromStringAndSize(key.data, key.size);
4791
4792 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004793 RETURN_IF_ERR();
4794
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00004795 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004796}
4797
4798static PyObject*
4799DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4800{
4801 int err;
4802 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004803 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004804 return NULL;
4805 CHECK_SEQUENCE_NOT_CLOSED(self)
4806
4807 MYDB_BEGIN_ALLOW_THREADS
4808 err = self->sequence->initial_value(self->sequence, value);
4809 MYDB_END_ALLOW_THREADS
4810
4811 RETURN_IF_ERR();
4812
4813 RETURN_NONE();
4814}
4815
4816static PyObject*
4817DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4818{
4819 int err, flags = 0;
4820 PyObject* keyobj;
4821 PyObject *txnobj = NULL;
4822 DB_TXN *txn = NULL;
4823 DBT key;
4824
4825 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004826 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004827 return NULL;
4828
4829 if (!checkTxnObj(txnobj, &txn))
4830 return NULL;
4831
4832 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4833 return NULL;
4834
4835 MYDB_BEGIN_ALLOW_THREADS
4836 err = self->sequence->open(self->sequence, txn, &key, flags);
4837 MYDB_END_ALLOW_THREADS
4838
4839 CLEAR_DBT(key);
4840 RETURN_IF_ERR();
4841
4842 RETURN_NONE();
4843}
4844
4845static PyObject*
4846DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4847{
4848 int err, flags = 0;
4849 PyObject *txnobj = NULL;
4850 DB_TXN *txn = NULL;
4851
4852 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004853 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004854 return NULL;
4855
4856 if (!checkTxnObj(txnobj, &txn))
4857 return NULL;
4858
4859 CHECK_SEQUENCE_NOT_CLOSED(self)
4860
4861 MYDB_BEGIN_ALLOW_THREADS
4862 err = self->sequence->remove(self->sequence, txn, flags);
4863 MYDB_END_ALLOW_THREADS
4864
4865 RETURN_IF_ERR();
4866 RETURN_NONE();
4867}
4868
4869static PyObject*
4870DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4871{
4872 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004873 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004874 return NULL;
4875 CHECK_SEQUENCE_NOT_CLOSED(self)
4876
4877 MYDB_BEGIN_ALLOW_THREADS
4878 err = self->sequence->set_cachesize(self->sequence, size);
4879 MYDB_END_ALLOW_THREADS
4880
4881 RETURN_IF_ERR();
4882 RETURN_NONE();
4883}
4884
4885static PyObject*
4886DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4887{
4888 int err, size;
4889 if (!PyArg_ParseTuple(args,":get_cachesize"))
4890 return NULL;
4891 CHECK_SEQUENCE_NOT_CLOSED(self)
4892
4893 MYDB_BEGIN_ALLOW_THREADS
4894 err = self->sequence->get_cachesize(self->sequence, &size);
4895 MYDB_END_ALLOW_THREADS
4896
4897 RETURN_IF_ERR();
4898 return PyInt_FromLong(size);
4899}
4900
4901static PyObject*
4902DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4903{
4904 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004905 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004906 return NULL;
4907 CHECK_SEQUENCE_NOT_CLOSED(self)
4908
4909 MYDB_BEGIN_ALLOW_THREADS
4910 err = self->sequence->set_flags(self->sequence, flags);
4911 MYDB_END_ALLOW_THREADS
4912
4913 RETURN_IF_ERR();
4914 RETURN_NONE();
4915
4916}
4917
4918static PyObject*
4919DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4920{
4921 unsigned int flags;
4922 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004923 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004924 return NULL;
4925 CHECK_SEQUENCE_NOT_CLOSED(self)
4926
4927 MYDB_BEGIN_ALLOW_THREADS
4928 err = self->sequence->get_flags(self->sequence, &flags);
4929 MYDB_END_ALLOW_THREADS
4930
4931 RETURN_IF_ERR();
4932 return PyInt_FromLong((int)flags);
4933}
4934
4935static PyObject*
4936DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4937{
4938 int err;
4939 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00004940 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004941 return NULL;
4942 CHECK_SEQUENCE_NOT_CLOSED(self)
4943
4944 MYDB_BEGIN_ALLOW_THREADS
4945 err = self->sequence->set_range(self->sequence, min, max);
4946 MYDB_END_ALLOW_THREADS
4947
4948 RETURN_IF_ERR();
4949 RETURN_NONE();
4950}
4951
4952static PyObject*
4953DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4954{
4955 int err;
4956 db_seq_t min, max;
4957 if (!PyArg_ParseTuple(args,":get_range"))
4958 return NULL;
4959 CHECK_SEQUENCE_NOT_CLOSED(self)
4960
4961 MYDB_BEGIN_ALLOW_THREADS
4962 err = self->sequence->get_range(self->sequence, &min, &max);
4963 MYDB_END_ALLOW_THREADS
4964
4965 RETURN_IF_ERR();
4966 return Py_BuildValue("(LL)", min, max);
4967}
4968
4969static PyObject*
4970DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4971{
4972 int err, flags = 0;
4973 DB_SEQUENCE_STAT* sp = NULL;
4974 PyObject* dict_stat;
4975 static char* kwnames[] = {"flags", NULL };
4976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4977 return NULL;
4978 CHECK_SEQUENCE_NOT_CLOSED(self);
4979
4980 MYDB_BEGIN_ALLOW_THREADS;
4981 err = self->sequence->stat(self->sequence, &sp, flags);
4982 MYDB_END_ALLOW_THREADS;
4983 RETURN_IF_ERR();
4984
4985 if ((dict_stat = PyDict_New()) == NULL) {
4986 free(sp);
4987 return NULL;
4988 }
4989
4990
4991#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4992#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4993
4994 MAKE_INT_ENTRY(wait);
4995 MAKE_INT_ENTRY(nowait);
4996 MAKE_LONG_LONG_ENTRY(current);
4997 MAKE_LONG_LONG_ENTRY(value);
4998 MAKE_LONG_LONG_ENTRY(last_value);
4999 MAKE_LONG_LONG_ENTRY(min);
5000 MAKE_LONG_LONG_ENTRY(max);
5001 MAKE_INT_ENTRY(cache_size);
5002 MAKE_INT_ENTRY(flags);
5003
5004#undef MAKE_INT_ENTRY
5005#undef MAKE_LONG_LONG_ENTRY
5006
5007 free(sp);
5008 return dict_stat;
5009}
5010#endif
5011
5012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005013/* --------------------------------------------------------------------- */
5014/* Method definition tables and type objects */
5015
5016static PyMethodDef DB_methods[] = {
5017 {"append", (PyCFunction)DB_append, METH_VARARGS},
5018#if (DBVER >= 33)
5019 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5020#endif
5021 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005022 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5023 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005024 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5025 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5026 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5027 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005028#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005029 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005030#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005031 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5032 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5033 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5034 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5035 {"join", (PyCFunction)DB_join, METH_VARARGS},
5036 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5037 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5038 {"items", (PyCFunction)DB_items, METH_VARARGS},
5039 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5040 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5041 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5042 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5043 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5044 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005045#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005046 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005047#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005048 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005049#if (DBVER >= 41)
5050 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5051#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005052 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5053 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5054 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5055 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5056 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5057 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5058 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5059 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5060 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005061 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005062 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005063 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5064#if (DBVER >= 33)
5065 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5066#endif
5067 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5068 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5069 {"values", (PyCFunction)DB_values, METH_VARARGS},
5070 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5071 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5072 {NULL, NULL} /* sentinel */
5073};
5074
5075
5076static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005077 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005078 (binaryfunc)DB_subscript, /*mp_subscript*/
5079 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5080};
5081
5082
5083static PyMethodDef DBCursor_methods[] = {
5084 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5085 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5086 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5087 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5088 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5089 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5090 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005091#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005092 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005093#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005094 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5095 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5096 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5097 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5098 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5099 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5100 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5101 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005102 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005103 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005104 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5105 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5106 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5107 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5108 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5109 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5110 {NULL, NULL} /* sentinel */
5111};
5112
5113
5114static PyMethodDef DBEnv_methods[] = {
5115 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5116 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5117 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005118#if (DBVER >= 41)
5119 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5120 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5121 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5122#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005123#if (DBVER >= 40)
5124 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5125#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005126 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005127 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5128 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005129 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005130 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5131 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5132 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005133#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005134 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005135#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005136 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005137#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005138 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005139#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005140 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5141 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5142 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005143 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5144 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5145 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5146 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5147 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5148 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005149 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5151 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5152 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00005153#if (DBVER >= 40)
5154 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5155#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005156 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5157 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5158 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005159#if (DBVER >= 40)
5160 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5161#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005162#if (DBVER >= 44)
5163 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5164#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005165 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5166 {NULL, NULL} /* sentinel */
5167};
5168
5169
5170static PyMethodDef DBTxn_methods[] = {
5171 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5172 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5173 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5174 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5175 {NULL, NULL} /* sentinel */
5176};
5177
5178
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005179#if (DBVER >= 43)
5180static PyMethodDef DBSequence_methods[] = {
5181 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5182 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5183 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5184 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005185 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5186 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5187 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5188 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5189 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5190 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5191 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5192 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5193 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5194 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5195 {NULL, NULL} /* sentinel */
5196};
5197#endif
5198
5199
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005200static PyObject*
5201DB_getattr(DBObject* self, char *name)
5202{
5203 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5204}
5205
5206
5207static PyObject*
5208DBEnv_getattr(DBEnvObject* self, char *name)
5209{
5210 if (!strcmp(name, "db_home")) {
5211 CHECK_ENV_NOT_CLOSED(self);
5212 if (self->db_env->db_home == NULL) {
5213 RETURN_NONE();
5214 }
5215 return PyString_FromString(self->db_env->db_home);
5216 }
5217
5218 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5219}
5220
5221
5222static PyObject*
5223DBCursor_getattr(DBCursorObject* self, char *name)
5224{
5225 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5226}
5227
5228static PyObject*
5229DBTxn_getattr(DBTxnObject* self, char *name)
5230{
5231 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5232}
5233
5234static PyObject*
5235DBLock_getattr(DBLockObject* self, char *name)
5236{
5237 return NULL;
5238}
5239
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005240#if (DBVER >= 43)
5241static PyObject*
5242DBSequence_getattr(DBSequenceObject* self, char *name)
5243{
5244 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5245}
5246#endif
5247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005248statichere PyTypeObject DB_Type = {
5249 PyObject_HEAD_INIT(NULL)
5250 0, /*ob_size*/
5251 "DB", /*tp_name*/
5252 sizeof(DBObject), /*tp_basicsize*/
5253 0, /*tp_itemsize*/
5254 /* methods */
5255 (destructor)DB_dealloc, /*tp_dealloc*/
5256 0, /*tp_print*/
5257 (getattrfunc)DB_getattr, /*tp_getattr*/
5258 0, /*tp_setattr*/
5259 0, /*tp_compare*/
5260 0, /*tp_repr*/
5261 0, /*tp_as_number*/
5262 0, /*tp_as_sequence*/
5263 &DB_mapping,/*tp_as_mapping*/
5264 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005265 0, /* tp_call */
5266 0, /* tp_str */
5267 0, /* tp_getattro */
5268 0, /* tp_setattro */
5269 0, /* tp_as_buffer */
5270 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5271 0, /* tp_doc */
5272 0, /* tp_traverse */
5273 0, /* tp_clear */
5274 0, /* tp_richcompare */
5275 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005276};
5277
5278
5279statichere PyTypeObject DBCursor_Type = {
5280 PyObject_HEAD_INIT(NULL)
5281 0, /*ob_size*/
5282 "DBCursor", /*tp_name*/
5283 sizeof(DBCursorObject), /*tp_basicsize*/
5284 0, /*tp_itemsize*/
5285 /* methods */
5286 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5287 0, /*tp_print*/
5288 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5289 0, /*tp_setattr*/
5290 0, /*tp_compare*/
5291 0, /*tp_repr*/
5292 0, /*tp_as_number*/
5293 0, /*tp_as_sequence*/
5294 0, /*tp_as_mapping*/
5295 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005296 0, /* tp_call */
5297 0, /* tp_str */
5298 0, /* tp_getattro */
5299 0, /* tp_setattro */
5300 0, /* tp_as_buffer */
5301 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5302 0, /* tp_doc */
5303 0, /* tp_traverse */
5304 0, /* tp_clear */
5305 0, /* tp_richcompare */
5306 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005307};
5308
5309
5310statichere PyTypeObject DBEnv_Type = {
5311 PyObject_HEAD_INIT(NULL)
5312 0, /*ob_size*/
5313 "DBEnv", /*tp_name*/
5314 sizeof(DBEnvObject), /*tp_basicsize*/
5315 0, /*tp_itemsize*/
5316 /* methods */
5317 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5318 0, /*tp_print*/
5319 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5320 0, /*tp_setattr*/
5321 0, /*tp_compare*/
5322 0, /*tp_repr*/
5323 0, /*tp_as_number*/
5324 0, /*tp_as_sequence*/
5325 0, /*tp_as_mapping*/
5326 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005327 0, /* tp_call */
5328 0, /* tp_str */
5329 0, /* tp_getattro */
5330 0, /* tp_setattro */
5331 0, /* tp_as_buffer */
5332 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5333 0, /* tp_doc */
5334 0, /* tp_traverse */
5335 0, /* tp_clear */
5336 0, /* tp_richcompare */
5337 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005338};
5339
5340statichere PyTypeObject DBTxn_Type = {
5341 PyObject_HEAD_INIT(NULL)
5342 0, /*ob_size*/
5343 "DBTxn", /*tp_name*/
5344 sizeof(DBTxnObject), /*tp_basicsize*/
5345 0, /*tp_itemsize*/
5346 /* methods */
5347 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5348 0, /*tp_print*/
5349 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5350 0, /*tp_setattr*/
5351 0, /*tp_compare*/
5352 0, /*tp_repr*/
5353 0, /*tp_as_number*/
5354 0, /*tp_as_sequence*/
5355 0, /*tp_as_mapping*/
5356 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005357 0, /* tp_call */
5358 0, /* tp_str */
5359 0, /* tp_getattro */
5360 0, /* tp_setattro */
5361 0, /* tp_as_buffer */
5362 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5363 0, /* tp_doc */
5364 0, /* tp_traverse */
5365 0, /* tp_clear */
5366 0, /* tp_richcompare */
5367 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005368};
5369
5370
5371statichere PyTypeObject DBLock_Type = {
5372 PyObject_HEAD_INIT(NULL)
5373 0, /*ob_size*/
5374 "DBLock", /*tp_name*/
5375 sizeof(DBLockObject), /*tp_basicsize*/
5376 0, /*tp_itemsize*/
5377 /* methods */
5378 (destructor)DBLock_dealloc, /*tp_dealloc*/
5379 0, /*tp_print*/
5380 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5381 0, /*tp_setattr*/
5382 0, /*tp_compare*/
5383 0, /*tp_repr*/
5384 0, /*tp_as_number*/
5385 0, /*tp_as_sequence*/
5386 0, /*tp_as_mapping*/
5387 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005388 0, /* tp_call */
5389 0, /* tp_str */
5390 0, /* tp_getattro */
5391 0, /* tp_setattro */
5392 0, /* tp_as_buffer */
5393 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5394 0, /* tp_doc */
5395 0, /* tp_traverse */
5396 0, /* tp_clear */
5397 0, /* tp_richcompare */
5398 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005399};
5400
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005401#if (DBVER >= 43)
5402statichere PyTypeObject DBSequence_Type = {
5403 PyObject_HEAD_INIT(NULL)
5404 0, /*ob_size*/
5405 "DBSequence", /*tp_name*/
5406 sizeof(DBSequenceObject), /*tp_basicsize*/
5407 0, /*tp_itemsize*/
5408 /* methods */
5409 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5410 0, /*tp_print*/
5411 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5412 0, /*tp_setattr*/
5413 0, /*tp_compare*/
5414 0, /*tp_repr*/
5415 0, /*tp_as_number*/
5416 0, /*tp_as_sequence*/
5417 0, /*tp_as_mapping*/
5418 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005419 0, /* tp_call */
5420 0, /* tp_str */
5421 0, /* tp_getattro */
5422 0, /* tp_setattro */
5423 0, /* tp_as_buffer */
5424 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5425 0, /* tp_doc */
5426 0, /* tp_traverse */
5427 0, /* tp_clear */
5428 0, /* tp_richcompare */
5429 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005430};
5431#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005432
5433/* --------------------------------------------------------------------- */
5434/* Module-level functions */
5435
5436static PyObject*
5437DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5438{
5439 PyObject* dbenvobj = NULL;
5440 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005441 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005442
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005443 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5444 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005445 return NULL;
5446 if (dbenvobj == Py_None)
5447 dbenvobj = NULL;
5448 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5449 makeTypeError("DBEnv", dbenvobj);
5450 return NULL;
5451 }
5452
5453 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5454}
5455
5456
5457static PyObject*
5458DBEnv_construct(PyObject* self, PyObject* args)
5459{
5460 int flags = 0;
5461 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5462 return (PyObject* )newDBEnvObject(flags);
5463}
5464
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005465#if (DBVER >= 43)
5466static PyObject*
5467DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5468{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005469 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005470 int flags = 0;
5471 static char* kwnames[] = { "db", "flags", NULL};
5472
5473 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5474 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005475 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005476 makeTypeError("DB", dbobj);
5477 return NULL;
5478 }
5479 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5480}
5481#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005482
5483static char bsddb_version_doc[] =
5484"Returns a tuple of major, minor, and patch release numbers of the\n\
5485underlying DB library.";
5486
5487static PyObject*
5488bsddb_version(PyObject* self, PyObject* args)
5489{
5490 int major, minor, patch;
5491
5492 if (!PyArg_ParseTuple(args, ":version"))
5493 return NULL;
5494 db_version(&major, &minor, &patch);
5495 return Py_BuildValue("(iii)", major, minor, patch);
5496}
5497
5498
5499/* List of functions defined in the module */
5500
5501static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005502 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5503 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5504#if (DBVER >= 43)
5505 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5506#endif
5507 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005508 {NULL, NULL} /* sentinel */
5509};
5510
Gregory P. Smith39250532007-10-09 06:02:21 +00005511/* API structure */
5512static BSDDB_api bsddb_api;
5513
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005514
5515/* --------------------------------------------------------------------- */
5516/* Module initialization */
5517
5518
5519/* Convenience routine to export an integer value.
5520 * Errors are silently ignored, for better or for worse...
5521 */
5522#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5523
Gregory P. Smith41631e82003-09-21 00:08:14 +00005524#define MODULE_NAME_MAX_LEN 11
5525static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005526
5527DL_EXPORT(void) init_bsddb(void)
5528{
5529 PyObject* m;
5530 PyObject* d;
5531 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5532 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5533 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00005534 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005535
5536 /* Initialize the type of the new type objects here; doing it here
5537 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00005538 Py_TYPE(&DB_Type) = &PyType_Type;
5539 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5540 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5541 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5542 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005543#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00005544 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005545#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005546
5547
Mark Hammonda69d4092003-04-22 23:13:27 +00005548#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005549 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005550 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005551#endif
5552
5553 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005554 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005555 if (m == NULL)
5556 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005557
5558 /* Add some symbolic constants to the module */
5559 d = PyModule_GetDict(m);
5560 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5561 PyDict_SetItemString(d, "cvsid", cvsid_s);
5562 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5563 Py_DECREF(pybsddb_version_s);
5564 pybsddb_version_s = NULL;
5565 Py_DECREF(cvsid_s);
5566 cvsid_s = NULL;
5567 Py_DECREF(db_version_s);
5568 db_version_s = NULL;
5569
5570 ADD_INT(d, DB_VERSION_MAJOR);
5571 ADD_INT(d, DB_VERSION_MINOR);
5572 ADD_INT(d, DB_VERSION_PATCH);
5573
5574 ADD_INT(d, DB_MAX_PAGES);
5575 ADD_INT(d, DB_MAX_RECORDS);
5576
Gregory P. Smith41631e82003-09-21 00:08:14 +00005577#if (DBVER >= 42)
5578 ADD_INT(d, DB_RPCCLIENT);
5579#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005580 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005581 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5582 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5583#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005584 ADD_INT(d, DB_XA_CREATE);
5585
5586 ADD_INT(d, DB_CREATE);
5587 ADD_INT(d, DB_NOMMAP);
5588 ADD_INT(d, DB_THREAD);
5589
5590 ADD_INT(d, DB_FORCE);
5591 ADD_INT(d, DB_INIT_CDB);
5592 ADD_INT(d, DB_INIT_LOCK);
5593 ADD_INT(d, DB_INIT_LOG);
5594 ADD_INT(d, DB_INIT_MPOOL);
5595 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005596 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005597
5598 ADD_INT(d, DB_RECOVER);
5599 ADD_INT(d, DB_RECOVER_FATAL);
5600 ADD_INT(d, DB_TXN_NOSYNC);
5601 ADD_INT(d, DB_USE_ENVIRON);
5602 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5603
5604 ADD_INT(d, DB_LOCKDOWN);
5605 ADD_INT(d, DB_PRIVATE);
5606 ADD_INT(d, DB_SYSTEM_MEM);
5607
5608 ADD_INT(d, DB_TXN_SYNC);
5609 ADD_INT(d, DB_TXN_NOWAIT);
5610
5611 ADD_INT(d, DB_EXCL);
5612 ADD_INT(d, DB_FCNTL_LOCKING);
5613 ADD_INT(d, DB_ODDFILESIZE);
5614 ADD_INT(d, DB_RDWRMASTER);
5615 ADD_INT(d, DB_RDONLY);
5616 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005617 ADD_INT(d, DB_EXTENT);
5618 ADD_INT(d, DB_CDB_ALLDB);
5619 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005620 ADD_INT(d, DB_UPGRADE);
5621
5622 ADD_INT(d, DB_AGGRESSIVE);
5623 ADD_INT(d, DB_NOORDERCHK);
5624 ADD_INT(d, DB_ORDERCHKONLY);
5625 ADD_INT(d, DB_PR_PAGE);
5626#if ! (DBVER >= 33)
5627 ADD_INT(d, DB_VRFY_FLAGMASK);
5628 ADD_INT(d, DB_PR_HEADERS);
5629#endif
5630 ADD_INT(d, DB_PR_RECOVERYTEST);
5631 ADD_INT(d, DB_SALVAGE);
5632
5633 ADD_INT(d, DB_LOCK_NORUN);
5634 ADD_INT(d, DB_LOCK_DEFAULT);
5635 ADD_INT(d, DB_LOCK_OLDEST);
5636 ADD_INT(d, DB_LOCK_RANDOM);
5637 ADD_INT(d, DB_LOCK_YOUNGEST);
5638#if (DBVER >= 33)
5639 ADD_INT(d, DB_LOCK_MAXLOCKS);
5640 ADD_INT(d, DB_LOCK_MINLOCKS);
5641 ADD_INT(d, DB_LOCK_MINWRITE);
5642#endif
5643
5644
5645#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005646 /* docs say to use zero instead */
5647 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005648#else
5649 ADD_INT(d, DB_LOCK_CONFLICT);
5650#endif
5651
5652 ADD_INT(d, DB_LOCK_DUMP);
5653 ADD_INT(d, DB_LOCK_GET);
5654 ADD_INT(d, DB_LOCK_INHERIT);
5655 ADD_INT(d, DB_LOCK_PUT);
5656 ADD_INT(d, DB_LOCK_PUT_ALL);
5657 ADD_INT(d, DB_LOCK_PUT_OBJ);
5658
5659 ADD_INT(d, DB_LOCK_NG);
5660 ADD_INT(d, DB_LOCK_READ);
5661 ADD_INT(d, DB_LOCK_WRITE);
5662 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005663 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664 ADD_INT(d, DB_LOCK_IWRITE);
5665 ADD_INT(d, DB_LOCK_IREAD);
5666 ADD_INT(d, DB_LOCK_IWR);
5667#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005668#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005669 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005670#else
5671 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5672#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 ADD_INT(d, DB_LOCK_WWRITE);
5674#endif
5675
5676 ADD_INT(d, DB_LOCK_RECORD);
5677 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005679#if (DBVER >= 33)
5680 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5681#endif
5682
5683 ADD_INT(d, DB_LOCK_NOWAIT);
5684 ADD_INT(d, DB_LOCK_RECORD);
5685 ADD_INT(d, DB_LOCK_UPGRADE);
5686
5687#if (DBVER >= 33)
5688 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005689#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005690 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005691#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005692 ADD_INT(d, DB_LSTAT_FREE);
5693 ADD_INT(d, DB_LSTAT_HELD);
5694#if (DBVER == 33)
5695 ADD_INT(d, DB_LSTAT_NOGRANT);
5696#endif
5697 ADD_INT(d, DB_LSTAT_PENDING);
5698 ADD_INT(d, DB_LSTAT_WAITING);
5699#endif
5700
5701 ADD_INT(d, DB_ARCH_ABS);
5702 ADD_INT(d, DB_ARCH_DATA);
5703 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005704#if (DBVER >= 42)
5705 ADD_INT(d, DB_ARCH_REMOVE);
5706#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005707
5708 ADD_INT(d, DB_BTREE);
5709 ADD_INT(d, DB_HASH);
5710 ADD_INT(d, DB_RECNO);
5711 ADD_INT(d, DB_QUEUE);
5712 ADD_INT(d, DB_UNKNOWN);
5713
5714 ADD_INT(d, DB_DUP);
5715 ADD_INT(d, DB_DUPSORT);
5716 ADD_INT(d, DB_RECNUM);
5717 ADD_INT(d, DB_RENUMBER);
5718 ADD_INT(d, DB_REVSPLITOFF);
5719 ADD_INT(d, DB_SNAPSHOT);
5720
5721 ADD_INT(d, DB_JOIN_NOSORT);
5722
5723 ADD_INT(d, DB_AFTER);
5724 ADD_INT(d, DB_APPEND);
5725 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005726#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005727 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005728#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005729#if (DBVER >= 41)
5730 _addIntToDict(d, "DB_CHECKPOINT", 0);
5731#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005732 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005733 ADD_INT(d, DB_CURLSN);
5734#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005735#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005736 ADD_INT(d, DB_COMMIT);
5737#endif
5738 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005739 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005740 ADD_INT(d, DB_CURRENT);
5741#if (DBVER >= 33)
5742 ADD_INT(d, DB_FAST_STAT);
5743#endif
5744 ADD_INT(d, DB_FIRST);
5745 ADD_INT(d, DB_FLUSH);
5746 ADD_INT(d, DB_GET_BOTH);
5747 ADD_INT(d, DB_GET_RECNO);
5748 ADD_INT(d, DB_JOIN_ITEM);
5749 ADD_INT(d, DB_KEYFIRST);
5750 ADD_INT(d, DB_KEYLAST);
5751 ADD_INT(d, DB_LAST);
5752 ADD_INT(d, DB_NEXT);
5753 ADD_INT(d, DB_NEXT_DUP);
5754 ADD_INT(d, DB_NEXT_NODUP);
5755 ADD_INT(d, DB_NODUPDATA);
5756 ADD_INT(d, DB_NOOVERWRITE);
5757 ADD_INT(d, DB_NOSYNC);
5758 ADD_INT(d, DB_POSITION);
5759 ADD_INT(d, DB_PREV);
5760 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005761#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005762 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00005763#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005764 ADD_INT(d, DB_SET);
5765 ADD_INT(d, DB_SET_RANGE);
5766 ADD_INT(d, DB_SET_RECNO);
5767 ADD_INT(d, DB_WRITECURSOR);
5768
5769 ADD_INT(d, DB_OPFLAGS_MASK);
5770 ADD_INT(d, DB_RMW);
5771#if (DBVER >= 33)
5772 ADD_INT(d, DB_DIRTY_READ);
5773 ADD_INT(d, DB_MULTIPLE);
5774 ADD_INT(d, DB_MULTIPLE_KEY);
5775#endif
5776
Gregory P. Smith29602d22006-01-24 09:46:48 +00005777#if (DBVER >= 44)
5778 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5779 ADD_INT(d, DB_READ_COMMITTED);
5780#endif
5781
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005782#if (DBVER >= 33)
5783 ADD_INT(d, DB_DONOTINDEX);
5784#endif
5785
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005786#if (DBVER >= 41)
5787 _addIntToDict(d, "DB_INCOMPLETE", 0);
5788#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005789 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005790#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005791 ADD_INT(d, DB_KEYEMPTY);
5792 ADD_INT(d, DB_KEYEXIST);
5793 ADD_INT(d, DB_LOCK_DEADLOCK);
5794 ADD_INT(d, DB_LOCK_NOTGRANTED);
5795 ADD_INT(d, DB_NOSERVER);
5796 ADD_INT(d, DB_NOSERVER_HOME);
5797 ADD_INT(d, DB_NOSERVER_ID);
5798 ADD_INT(d, DB_NOTFOUND);
5799 ADD_INT(d, DB_OLD_VERSION);
5800 ADD_INT(d, DB_RUNRECOVERY);
5801 ADD_INT(d, DB_VERIFY_BAD);
5802#if (DBVER >= 33)
5803 ADD_INT(d, DB_PAGE_NOTFOUND);
5804 ADD_INT(d, DB_SECONDARY_BAD);
5805#endif
5806#if (DBVER >= 40)
5807 ADD_INT(d, DB_STAT_CLEAR);
5808 ADD_INT(d, DB_REGION_INIT);
5809 ADD_INT(d, DB_NOLOCKING);
5810 ADD_INT(d, DB_YIELDCPU);
5811 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5812 ADD_INT(d, DB_NOPANIC);
5813#endif
5814
Gregory P. Smithaae141a2007-11-01 21:08:14 +00005815#ifdef DB_REGISTER
5816 ADD_INT(d, DB_REGISTER);
5817#endif
5818
Gregory P. Smith41631e82003-09-21 00:08:14 +00005819#if (DBVER >= 42)
5820 ADD_INT(d, DB_TIME_NOTGRANTED);
5821 ADD_INT(d, DB_TXN_NOT_DURABLE);
5822 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5823 ADD_INT(d, DB_LOG_AUTOREMOVE);
5824 ADD_INT(d, DB_DIRECT_LOG);
5825 ADD_INT(d, DB_DIRECT_DB);
5826 ADD_INT(d, DB_INIT_REP);
5827 ADD_INT(d, DB_ENCRYPT);
5828 ADD_INT(d, DB_CHKSUM);
5829#endif
5830
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005831#if (DBVER >= 43)
5832 ADD_INT(d, DB_LOG_INMEMORY);
5833 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005834 ADD_INT(d, DB_SEQ_DEC);
5835 ADD_INT(d, DB_SEQ_INC);
5836 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005837#endif
5838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005839#if (DBVER >= 41)
5840 ADD_INT(d, DB_ENCRYPT_AES);
5841 ADD_INT(d, DB_AUTO_COMMIT);
5842#else
5843 /* allow berkeleydb 4.1 aware apps to run on older versions */
5844 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5845#endif
5846
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005847 ADD_INT(d, EINVAL);
5848 ADD_INT(d, EACCES);
5849 ADD_INT(d, ENOSPC);
5850 ADD_INT(d, ENOMEM);
5851 ADD_INT(d, EAGAIN);
5852 ADD_INT(d, EBUSY);
5853 ADD_INT(d, EEXIST);
5854 ADD_INT(d, ENOENT);
5855 ADD_INT(d, EPERM);
5856
Barry Warsaw1baa9822003-03-31 19:51:29 +00005857#if (DBVER >= 40)
5858 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5859 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5860#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005861
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005862 /* The exception name must be correct for pickled exception *
5863 * objects to unpickle properly. */
5864#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5865#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5866#else
5867#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5868#endif
5869
5870 /* All the rest of the exceptions derive only from DBError */
5871#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5872 PyDict_SetItemString(d, #name, name)
5873
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005874 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005875 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5876 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877
Gregory P. Smithe9477062005-06-04 06:46:59 +00005878 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5879 * from both DBError and KeyError, since the API only supports
5880 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005882 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5883 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005884 Py_file_input, d, d);
5885 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005886 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005887 PyDict_DelItemString(d, "KeyError");
5888
5889
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005890#if !INCOMPLETE_IS_WARNING
5891 MAKE_EX(DBIncompleteError);
5892#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005893 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005894 MAKE_EX(DBKeyEmptyError);
5895 MAKE_EX(DBKeyExistError);
5896 MAKE_EX(DBLockDeadlockError);
5897 MAKE_EX(DBLockNotGrantedError);
5898 MAKE_EX(DBOldVersionError);
5899 MAKE_EX(DBRunRecoveryError);
5900 MAKE_EX(DBVerifyBadError);
5901 MAKE_EX(DBNoServerError);
5902 MAKE_EX(DBNoServerHomeError);
5903 MAKE_EX(DBNoServerIDError);
5904#if (DBVER >= 33)
5905 MAKE_EX(DBPageNotFoundError);
5906 MAKE_EX(DBSecondaryBadError);
5907#endif
5908
5909 MAKE_EX(DBInvalidArgError);
5910 MAKE_EX(DBAccessError);
5911 MAKE_EX(DBNoSpaceError);
5912 MAKE_EX(DBNoMemoryError);
5913 MAKE_EX(DBAgainError);
5914 MAKE_EX(DBBusyError);
5915 MAKE_EX(DBFileExistsError);
5916 MAKE_EX(DBNoSuchFileError);
5917 MAKE_EX(DBPermissionsError);
5918
5919#undef MAKE_EX
5920
Gregory P. Smith39250532007-10-09 06:02:21 +00005921 /* Initiliase the C API structure and add it to the module */
5922 bsddb_api.db_type = &DB_Type;
5923 bsddb_api.dbcursor_type = &DBCursor_Type;
5924 bsddb_api.dbenv_type = &DBEnv_Type;
5925 bsddb_api.dbtxn_type = &DBTxn_Type;
5926 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005927#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00005928 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00005929#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00005930 bsddb_api.makeDBError = makeDBError;
5931
5932 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5933 PyDict_SetItemString(d, "api", py_api);
5934 Py_DECREF(py_api);
5935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005936 /* Check for errors */
5937 if (PyErr_Occurred()) {
5938 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005939 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005940 }
5941}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005942
5943/* allow this module to be named _pybsddb so that it can be installed
5944 * and imported on top of python >= 2.3 that includes its own older
5945 * copy of the library named _bsddb without importing the old version. */
5946DL_EXPORT(void) init_pybsddb(void)
5947{
5948 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5949 init_bsddb();
5950}