blob: 52d83eca61a53ab533c2ba9862a38a0d34e7996c [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. Smithc4119182007-09-09 20:17:22 +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. Smithc4119182007-09-09 20:17:22 +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 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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>
Guido van Rossum8ce8a782007-11-01 19:42:39 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000101typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +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
Guido van Rossum8ce8a782007-11-01 19:42:39 +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
Guido van Rossum8ce8a782007-11-01 19:42:39 +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
Neal Norwitz227b5332006-03-22 09:28:35 +0000204static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000205
Christian Heimes90aa7642007-12-19 02:45:37 +0000206#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000211#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +0000212#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000254
255static int makeDBError(int err);
256
257
258/* Return the access method type of the DBObject */
259static int _DB_get_type(DBObject* self)
260{
261#if (DBVER >= 33)
262 DBTYPE type;
263 int err;
264 err = self->db->get_type(self->db, &type);
265 if (makeDBError(err)) {
266 return -1;
267 }
268 return type;
269#else
270 return self->db->get_type(self->db);
271#endif
272}
273
274
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000275/* Handy function to free a DBT and any self-allocated data within.
276 To be used on self created DBTs. The make_dbt and make_key_dbt
277 functions have their own free routines that do more that this. */
278static void free_dbt(DBT *dbt)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279{
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000280 if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
281 free(dbt->data);
282 dbt->data = NULL;
283 }
284}
285
286
287/* Cleanup a Python buffer API view created by make_dbt() */
Thomas Heller39763a12007-09-24 14:43:56 +0000288static void free_buf_view(PyObject *obj, Py_buffer *view)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000289{
290 if (view) {
291 PyObject_ReleaseBuffer(obj, view);
292 PyMem_Free(view);
293 }
294}
295
296
297/* Cleanup a DBT and an associated Python buffer API view
298 created by make_key_dbt() */
299#define FREE_DBT_VIEW(dbt, obj, view) \
300 do { \
301 free_dbt(&(dbt)); \
302 free_buf_view((obj), (view)); \
303 } while(0);
304
305
Thomas Heller39763a12007-09-24 14:43:56 +0000306static Py_buffer * _malloc_view(PyObject *obj)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000307{
Thomas Heller39763a12007-09-24 14:43:56 +0000308 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000309
Thomas Heller39763a12007-09-24 14:43:56 +0000310 if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000311 PyErr_SetString(PyExc_MemoryError,
Thomas Heller39763a12007-09-24 14:43:56 +0000312 "Py_buffer malloc failed");
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000313 return NULL;
314 }
315 /* XXX(gps): PyBUF_LOCKDATA is desired to prevent other theads from
316 trashing the data buffer while we release the GIL during the db
317 operation. see http://bugs.python.org/issue1035 */
318 if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
319 PyMem_Free(view);
320 return NULL;
321 }
322 if (view->ndim > 1) {
323 PyErr_SetString(PyExc_BufferError,
324 "buffers must be single dimension");
325 PyObject_ReleaseBuffer(obj, view);
326 PyMem_Free(view);
327 return NULL;
328 }
329 return view;
330}
331
332
333/* Create a DBT structure (containing key and data values) from Python
334 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000335 may be filled with a newly allocated Py_buffer view on success.
336 The caller MUST call free_buf_view() on any returned Py_buffer. */
337static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000338{
Thomas Heller39763a12007-09-24 14:43:56 +0000339 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000340
341 /* simple way to ensure the caller can detect if we've returned a
342 new buffer view or not: require their pointer to start out NULL. */
343 assert(*returned_view_p == NULL);
344
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345 CLEAR_DBT(*dbt);
346 if (obj == Py_None) {
347 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000348 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000349 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000350 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000352 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353 return 0;
354 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000355
356 if ( !(view = _malloc_view(obj)) )
357 return 0;
358
359 dbt->data = view->buf;
360 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
361 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362 return 1;
363}
364
365
366/* Recno and Queue DBs can have integer keys. This function figures out
367 what's been given, verifies that it's allowed, and then makes the DBT.
368
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000369 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000370 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000371static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000372make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000373 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000374{
375 db_recno_t recno;
376 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000377 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000378
379 /* simple way to ensure the caller can detect if we've returned a
380 new buffer view or not: require their pointer to start out NULL. */
381 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382
383 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000384 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000386 if (type == -1)
387 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000388 if (type == DB_RECNO || type == DB_QUEUE) {
389 PyErr_SetString(
390 PyExc_TypeError,
391 "None keys not allowed for Recno and Queue DB's");
392 return 0;
393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000394 /* no need to do anything, the structure has already been zeroed */
395 }
396
Christian Heimes217cfd12007-12-02 14:31:20 +0000397 else if (PyLong_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 /* verify access method type */
399 type = _DB_get_type(self);
400 if (type == -1)
401 return 0;
402 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000403 /* if BTREE then an Integer key is allowed with the
404 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000405 *pflags |= DB_SET_RECNO;
406 }
407 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000408 PyErr_SetString(
409 PyExc_TypeError,
410 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000411 return 0;
412 }
413
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414 /* Make a key out of the requested recno, use allocated space so DB
415 * will be able to realloc room for the real key if needed. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000416 recno = PyLong_AS_LONG(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000417 key->data = malloc(sizeof(db_recno_t));
418 if (key->data == NULL) {
419 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
420 return 0;
421 }
422 key->ulen = key->size = sizeof(db_recno_t);
423 memcpy(key->data, &recno, sizeof(db_recno_t));
424 key->flags = DB_DBT_REALLOC;
425 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000426
427 else if (PyObject_CheckBuffer(keyobj)) {
428 /* verify access method type */
429 type = _DB_get_type(self);
430 if (type == -1)
431 return 0;
432 if (type == DB_RECNO || type == DB_QUEUE) {
433 PyErr_SetString(
434 PyExc_TypeError,
435 "Non-integer keys not allowed for Recno and Queue DB's");
436 return 0;
437 }
438
439 if ( !(view = _malloc_view(keyobj)) )
440 return 0;
441
Gregory P. Smith568065e2007-11-01 21:55:08 +0000442 /*
443 * NOTE(gps): I don't like doing a data copy here, it seems
444 * wasteful. But without a clean way to tell FREE_DBT if it
445 * should free key->data or not we have to. Other places in
446 * the code check for DB_THREAD and forceably set DBT_MALLOC
447 * when we otherwise would leave flags 0 to indicate that.
448 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000449 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000450 key->data = malloc(key->size);
451 if (key->data == NULL) {
452 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
453 key->size = 0;
454 return 0;
455 }
456 memcpy(key->data, view->buf, key->size);
457 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000458 *returned_view_p = view;
459 }
460
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 else {
462 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000463 "buffer or int object expected for key, %s found",
Christian Heimes90aa7642007-12-19 02:45:37 +0000464 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000548 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
550#else /* do an exception instead */
551 errObj = DBIncompleteError;
552#endif
553 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000554#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000555
556 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
557 case DB_KEYEXIST: errObj = DBKeyExistError; break;
558 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
559 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
560 case DB_NOTFOUND: errObj = DBNotFoundError; break;
561 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
562 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
563 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
564 case DB_NOSERVER: errObj = DBNoServerError; break;
565 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
566 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
567#if (DBVER >= 33)
568 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
569 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
570#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000571 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000572
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000573#if (DBVER >= 43)
574 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
575 case ENOMEM: errObj = PyExc_MemoryError; break;
576#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577 case EINVAL: errObj = DBInvalidArgError; break;
578 case EACCES: errObj = DBAccessError; break;
579 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000580 case EAGAIN: errObj = DBAgainError; break;
581 case EBUSY : errObj = DBBusyError; break;
582 case EEXIST: errObj = DBFileExistsError; break;
583 case ENOENT: errObj = DBNoSuchFileError; break;
584 case EPERM : errObj = DBPermissionsError; break;
585
586 default: errObj = DBError; break;
587 }
588
589 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000590 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
591 /* Ensure that bytes_left never goes negative */
592 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
593 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
594 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000595 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000596 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000597 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000598 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000599
600 errTuple = Py_BuildValue("(is)", err, errTxt);
601 PyErr_SetObject(errObj, errTuple);
602 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 }
604
605 return ((errObj != NULL) || exceptionRaised);
606}
607
608
609
610/* set a type exception */
611static void makeTypeError(char* expected, PyObject* found)
612{
613 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000614 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000615}
616
617
618/* verify that an obj is either None or a DBTxn, and set the txn pointer */
619static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
620{
621 if (txnobj == Py_None || txnobj == NULL) {
622 *txn = NULL;
623 return 1;
624 }
625 if (DBTxnObject_Check(txnobj)) {
626 *txn = ((DBTxnObject*)txnobj)->txn;
627 return 1;
628 }
629 else
630 makeTypeError("DBTxn", txnobj);
631 return 0;
632}
633
634
635/* Delete a key from a database
636 Returns 0 on success, -1 on an error. */
637static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
638{
639 int err;
640
641 MYDB_BEGIN_ALLOW_THREADS;
642 err = self->db->del(self->db, txn, key, 0);
643 MYDB_END_ALLOW_THREADS;
644 if (makeDBError(err)) {
645 return -1;
646 }
647 self->haveStat = 0;
648 return 0;
649}
650
651
652/* Store a key into a database
653 Returns 0 on success, -1 on an error. */
654static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
655{
656 int err;
657
658 MYDB_BEGIN_ALLOW_THREADS;
659 err = self->db->put(self->db, txn, key, data, flags);
660 MYDB_END_ALLOW_THREADS;
661 if (makeDBError(err)) {
662 return -1;
663 }
664 self->haveStat = 0;
665 return 0;
666}
667
668/* Get a key/data pair from a cursor */
669static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
670 PyObject *args, PyObject *kwargs, char *format)
671{
672 int err;
673 PyObject* retval = NULL;
674 DBT key, data;
675 int dlen = -1;
676 int doff = -1;
677 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000678 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679
680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
681 &flags, &dlen, &doff))
682 return NULL;
683
684 CHECK_CURSOR_NOT_CLOSED(self);
685
686 flags |= extra_flags;
687 CLEAR_DBT(key);
688 CLEAR_DBT(data);
689 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
690 /* Tell BerkeleyDB to malloc the return value (thread safe) */
691 data.flags = DB_DBT_MALLOC;
692 key.flags = DB_DBT_MALLOC;
693 }
694 if (!add_partial_dbt(&data, dlen, doff))
695 return NULL;
696
697 MYDB_BEGIN_ALLOW_THREADS;
698 err = self->dbc->c_get(self->dbc, &key, &data, flags);
699 MYDB_END_ALLOW_THREADS;
700
Gregory P. Smithe9477062005-06-04 06:46:59 +0000701 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
702 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 Py_INCREF(Py_None);
704 retval = Py_None;
705 }
706 else if (makeDBError(err)) {
707 retval = NULL;
708 }
709 else { /* otherwise, success! */
710
711 /* if Recno or Queue, return the key as an Int */
712 switch (_DB_get_type(self->mydb)) {
713 case -1:
714 retval = NULL;
715 break;
716
717 case DB_RECNO:
718 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000719 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720 data.data, data.size);
721 break;
722 case DB_HASH:
723 case DB_BTREE:
724 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000725 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 data.data, data.size);
727 break;
728 }
729 }
730 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000731 free_dbt(&key);
732 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000733 }
734 return retval;
735}
736
737
738/* add an integer to a dictionary using the given name as a key */
739static void _addIntToDict(PyObject* dict, char *name, int value)
740{
Christian Heimes217cfd12007-12-02 14:31:20 +0000741 PyObject* v = PyLong_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742 if (!v || PyDict_SetItemString(dict, name, v))
743 PyErr_Clear();
744
745 Py_XDECREF(v);
746}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000747
748/* The same, when the value is a time_t */
749static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
750{
751 PyObject* v;
752 /* if the value fits in regular int, use that. */
753#ifdef HAVE_LONG_LONG
754 if (sizeof(time_t) > sizeof(long))
755 v = PyLong_FromLongLong((PY_LONG_LONG) value);
756 else
757#endif
Christian Heimes217cfd12007-12-02 14:31:20 +0000758 v = PyLong_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000759 if (!v || PyDict_SetItemString(dict, name, v))
760 PyErr_Clear();
761
762 Py_XDECREF(v);
763}
764
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000765#if (DBVER >= 43)
766/* add an db_seq_t to a dictionary using the given name as a key */
767static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
768{
769 PyObject* v = PyLong_FromLongLong(value);
770 if (!v || PyDict_SetItemString(dict, name, v))
771 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000772
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000773 Py_XDECREF(v);
774}
775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776
777
778
779/* --------------------------------------------------------------------- */
780/* Allocators and deallocators */
781
782static DBObject*
783newDBObject(DBEnvObject* arg, int flags)
784{
785 DBObject* self;
786 DB_ENV* db_env = NULL;
787 int err;
788
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 if (self == NULL)
791 return NULL;
792
793 self->haveStat = 0;
794 self->flags = 0;
795 self->setflags = 0;
796 self->myenvobj = NULL;
797#if (DBVER >= 33)
798 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000799 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000800 self->primaryDBType = 0;
801#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000802 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000803
804 /* keep a reference to our python DBEnv object */
805 if (arg) {
806 Py_INCREF(arg);
807 self->myenvobj = arg;
808 db_env = arg->db_env;
809 }
810
811 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000812 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000814 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
815 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816
817 MYDB_BEGIN_ALLOW_THREADS;
818 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000819 if (self->db != NULL) {
820 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000822 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000825 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000826 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
827 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000828 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000829 if (makeDBError(err)) {
830 if (self->myenvobj) {
831 Py_DECREF(self->myenvobj);
832 self->myenvobj = NULL;
833 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000834 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 self = NULL;
836 }
837 return self;
838}
839
840
841static void
842DB_dealloc(DBObject* self)
843{
844 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000845 /* avoid closing a DB when its DBEnv has been closed out from under
846 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000848 (self->myenvobj && self->myenvobj->db_env))
849 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 MYDB_BEGIN_ALLOW_THREADS;
851 self->db->close(self->db, 0);
852 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000854 PyErr_WarnEx(PyExc_RuntimeWarning,
855 "DB could not be closed in destructor:"
856 " DBEnv already closed",
857 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000858 }
859 self->db = NULL;
860 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000861 if (self->in_weakreflist != NULL) {
862 PyObject_ClearWeakRefs((PyObject *) self);
863 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 if (self->myenvobj) {
865 Py_DECREF(self->myenvobj);
866 self->myenvobj = NULL;
867 }
868#if (DBVER >= 33)
869 if (self->associateCallback != NULL) {
870 Py_DECREF(self->associateCallback);
871 self->associateCallback = NULL;
872 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000873 if (self->btCompareCallback != NULL) {
874 Py_DECREF(self->btCompareCallback);
875 self->btCompareCallback = NULL;
876 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879}
880
881
882static DBCursorObject*
883newDBCursorObject(DBC* dbc, DBObject* db)
884{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000885 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886 if (self == NULL)
887 return NULL;
888
889 self->dbc = dbc;
890 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000891 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 Py_INCREF(self->mydb);
893 return self;
894}
895
896
897static void
898DBCursor_dealloc(DBCursorObject* self)
899{
900 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000901
Gregory P. Smitha703a212003-11-03 01:04:41 +0000902 if (self->in_weakreflist != NULL) {
903 PyObject_ClearWeakRefs((PyObject *) self);
904 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000905
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000906 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000907 /* If the underlying database has been closed, we don't
908 need to do anything. If the environment has been closed
909 we need to leak, as BerkeleyDB will crash trying to access
910 the environment. There was an exception when the
911 user closed the environment even though there still was
912 a database open. */
913 if (self->mydb->db && self->mydb->myenvobj &&
914 !self->mydb->myenvobj->closed)
Christian Heimes292d3512008-02-03 16:51:08 +0000915 /* test for: open db + no environment or non-closed environment */
916 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
917 !self->mydb->myenvobj->closed))) {
918 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000919 err = self->dbc->c_close(self->dbc);
Christian Heimes292d3512008-02-03 16:51:08 +0000920 MYDB_END_ALLOW_THREADS;
921 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000923 }
924 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000926}
927
928
929static DBEnvObject*
930newDBEnvObject(int flags)
931{
932 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000933 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934 if (self == NULL)
935 return NULL;
936
937 self->closed = 1;
938 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000939 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
940 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000941 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942
943 MYDB_BEGIN_ALLOW_THREADS;
944 err = db_env_create(&self->db_env, flags);
945 MYDB_END_ALLOW_THREADS;
946 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000947 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948 self = NULL;
949 }
950 else {
951 self->db_env->set_errcall(self->db_env, _db_errorCallback);
952 }
953 return self;
954}
955
956
957static void
958DBEnv_dealloc(DBEnvObject* self)
959{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000960 if (self->in_weakreflist != NULL) {
961 PyObject_ClearWeakRefs((PyObject *) self);
962 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000963
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000964 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 MYDB_BEGIN_ALLOW_THREADS;
966 self->db_env->close(self->db_env, 0);
967 MYDB_END_ALLOW_THREADS;
968 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970}
971
972
973static DBTxnObject*
974newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
975{
976 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000977 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 if (self == NULL)
979 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000980 Py_INCREF(myenv);
981 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000982 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983
984 MYDB_BEGIN_ALLOW_THREADS;
985#if (DBVER >= 40)
986 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
987#else
988 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
989#endif
990 MYDB_END_ALLOW_THREADS;
991 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000992 Py_DECREF(self->env);
993 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994 self = NULL;
995 }
996 return self;
997}
998
999
1000static void
1001DBTxn_dealloc(DBTxnObject* self)
1002{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 if (self->in_weakreflist != NULL) {
1004 PyObject_ClearWeakRefs((PyObject *) self);
1005 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001006
Gregory P. Smith31c50652004-06-28 01:20:40 +00001007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010#if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012#else
1013 txn_abort(self->txn);
1014#endif
1015 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001016 PyErr_WarnEx(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. "
1018 " No prior commit() or abort().",
1019 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001020 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001021
Neal Norwitz62a21122006-01-25 05:21:55 +00001022 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024}
1025
1026
1027static DBLockObject*
1028newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1029 db_lockmode_t lock_mode, int flags)
1030{
1031 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001032 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033 if (self == NULL)
1034 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001035 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001036
1037 MYDB_BEGIN_ALLOW_THREADS;
1038#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001039 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1040 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001041#else
1042 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1043#endif
1044 MYDB_END_ALLOW_THREADS;
1045 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001046 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001047 self = NULL;
1048 }
1049
1050 return self;
1051}
1052
1053
1054static void
1055DBLock_dealloc(DBLockObject* self)
1056{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001057 if (self->in_weakreflist != NULL) {
1058 PyObject_ClearWeakRefs((PyObject *) self);
1059 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001060 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063}
1064
1065
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001066#if (DBVER >= 43)
1067static DBSequenceObject*
1068newDBSequenceObject(DBObject* mydb, int flags)
1069{
1070 int err;
1071 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1072 if (self == NULL)
1073 return NULL;
1074 Py_INCREF(mydb);
1075 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001076 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001077
1078
1079 MYDB_BEGIN_ALLOW_THREADS;
1080 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1081 MYDB_END_ALLOW_THREADS;
1082 if (makeDBError(err)) {
1083 Py_DECREF(self->mydb);
1084 PyObject_Del(self);
1085 self = NULL;
1086 }
1087
1088 return self;
1089}
1090
1091
1092static void
1093DBSequence_dealloc(DBSequenceObject* self)
1094{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001095 if (self->in_weakreflist != NULL) {
1096 PyObject_ClearWeakRefs((PyObject *) self);
1097 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001098
1099 Py_DECREF(self->mydb);
1100 PyObject_Del(self);
1101}
1102#endif
1103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001104/* --------------------------------------------------------------------- */
1105/* DB methods */
1106
1107static PyObject*
1108DB_append(DBObject* self, PyObject* args)
1109{
1110 PyObject* txnobj = NULL;
1111 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001112 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001113 db_recno_t recno;
1114 DBT key, data;
1115 DB_TXN *txn = NULL;
1116
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001117 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001118 return NULL;
1119
1120 CHECK_DB_NOT_CLOSED(self);
1121
1122 /* make a dummy key out of a recno */
1123 recno = 0;
1124 CLEAR_DBT(key);
1125 key.data = &recno;
1126 key.size = sizeof(recno);
1127 key.ulen = key.size;
1128 key.flags = DB_DBT_USERMEM;
1129
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001131 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001133 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1134 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001135 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001136 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001137
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001138 free_buf_view(dataobj, data_buf_view);
Christian Heimes217cfd12007-12-02 14:31:20 +00001139 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001140}
1141
1142
1143#if (DBVER >= 33)
1144
1145static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001146_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1147 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001148{
1149 int retval = DB_DONOTINDEX;
1150 DBObject* secondaryDB = (DBObject*)db->app_private;
1151 PyObject* callback = secondaryDB->associateCallback;
1152 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001153 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001154 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001155
1156
1157 if (callback != NULL) {
1158 MYDB_BEGIN_BLOCK_THREADS;
1159
Thomas Woutersb3153832006-03-08 01:47:19 +00001160 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001161 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001162 priData->data, priData->size);
1163 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001164 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001165 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001166 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001167 result = PyEval_CallObject(callback, args);
1168 }
1169 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 PyErr_Print();
1171 }
1172 else if (result == Py_None) {
1173 retval = DB_DONOTINDEX;
1174 }
Christian Heimes217cfd12007-12-02 14:31:20 +00001175 else if (PyLong_Check(result)) {
1176 retval = PyLong_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177 }
Guido van Rossum98297ee2007-11-06 21:34:58 +00001178 else if (PyBytes_Check(result) || PyString_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001179 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001180 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181
1182 CLEAR_DBT(*secKey);
Christian Heimes90aa7642007-12-19 02:45:37 +00001183 size = Py_SIZE(result);
Guido van Rossum98297ee2007-11-06 21:34:58 +00001184 if (PyBytes_Check(result))
1185 data = PyBytes_AS_STRING(result);
1186 else
1187 data = PyString_AS_STRING(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001188 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1189 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001190 if (secKey->data) {
1191 memcpy(secKey->data, data, size);
1192 secKey->size = size;
1193 retval = 0;
1194 }
1195 else {
1196 PyErr_SetString(PyExc_MemoryError,
1197 "malloc failed in _db_associateCallback");
1198 PyErr_Print();
1199 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001200 }
1201 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001202 PyErr_SetString(
1203 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001204 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 PyErr_Print();
1206 }
1207
Thomas Woutersb3153832006-03-08 01:47:19 +00001208 Py_XDECREF(args);
1209 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210
1211 MYDB_END_BLOCK_THREADS;
1212 }
1213 return retval;
1214}
1215
1216
1217static PyObject*
1218DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1219{
1220 int err, flags=0;
1221 DBObject* secondaryDB;
1222 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001223#if (DBVER >= 41)
1224 PyObject *txnobj = NULL;
1225 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001226 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001227 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001229 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001230#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001231
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001232#if (DBVER >= 41)
1233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1234 &secondaryDB, &callback, &flags,
1235 &txnobj)) {
1236#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001238 &secondaryDB, &callback, &flags)) {
1239#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001240 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001241 }
1242
1243#if (DBVER >= 41)
1244 if (!checkTxnObj(txnobj, &txn)) return NULL;
1245#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001246
1247 CHECK_DB_NOT_CLOSED(self);
1248 if (!DBObject_Check(secondaryDB)) {
1249 makeTypeError("DB", (PyObject*)secondaryDB);
1250 return NULL;
1251 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001252 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001253 if (callback == Py_None) {
1254 callback = NULL;
1255 }
1256 else if (!PyCallable_Check(callback)) {
1257 makeTypeError("Callable", callback);
1258 return NULL;
1259 }
1260
1261 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001262 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001263 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001264 secondaryDB->associateCallback = callback;
1265 secondaryDB->primaryDBType = _DB_get_type(self);
1266
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001267 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1268 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1269 * The global interepreter lock is not initialized until the first
1270 * thread is created using thread.start_new_thread() or fork() is
1271 * called. that would cause the ALLOW_THREADS here to segfault due
1272 * to a null pointer reference if no threads or child processes
1273 * have been created. This works around that and is a no-op if
1274 * threads have already been initialized.
1275 * (see pybsddb-users mailing list post on 2002-08-07)
1276 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001277#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001278 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001279#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001280 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001281#if (DBVER >= 41)
1282 err = self->db->associate(self->db,
1283 txn,
1284 secondaryDB->db,
1285 _db_associateCallback,
1286 flags);
1287#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001288 err = self->db->associate(self->db,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001292#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293 MYDB_END_ALLOW_THREADS;
1294
1295 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001296 Py_XDECREF(secondaryDB->associateCallback);
1297 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 secondaryDB->primaryDBType = 0;
1299 }
1300
1301 RETURN_IF_ERR();
1302 RETURN_NONE();
1303}
1304
1305
1306#endif
1307
1308
1309static PyObject*
1310DB_close(DBObject* self, PyObject* args)
1311{
1312 int err, flags=0;
1313 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1314 return NULL;
1315 if (self->db != NULL) {
1316 if (self->myenvobj)
1317 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001318 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319 self->db = NULL;
1320 RETURN_IF_ERR();
1321 }
1322 RETURN_NONE();
1323}
1324
1325
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001326static PyObject*
1327_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1328{
1329 int err, flags=0, type;
1330 PyObject* txnobj = NULL;
1331 PyObject* retval = NULL;
1332 DBT key, data;
1333 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001334 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001335
1336 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1337 &txnobj, &flags))
1338 return NULL;
1339
1340 CHECK_DB_NOT_CLOSED(self);
1341 type = _DB_get_type(self);
1342 if (type == -1)
1343 return NULL;
1344 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001345 PyErr_SetString(PyExc_TypeError,
1346 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001347 return NULL;
1348 }
1349 if (!checkTxnObj(txnobj, &txn))
1350 return NULL;
1351
1352 CLEAR_DBT(key);
1353 CLEAR_DBT(data);
1354 if (CHECK_DBFLAG(self, DB_THREAD)) {
1355 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1356 data.flags = DB_DBT_MALLOC;
1357 key.flags = DB_DBT_MALLOC;
1358 }
1359
1360 MYDB_BEGIN_ALLOW_THREADS;
1361 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1362 MYDB_END_ALLOW_THREADS;
1363
Gregory P. Smithe9477062005-06-04 06:46:59 +00001364 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1365 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366 err = 0;
1367 Py_INCREF(Py_None);
1368 retval = Py_None;
1369 }
1370 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001371 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001372 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001373 free_dbt(&key);
1374 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001375 }
1376
1377 RETURN_IF_ERR();
1378 return retval;
1379}
1380
1381static PyObject*
1382DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1383{
1384 return _DB_consume(self, args, kwargs, DB_CONSUME);
1385}
1386
1387static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001388DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1389 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001390{
1391 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1392}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393
1394
1395static PyObject*
1396DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1397{
1398 int err, flags=0;
1399 DBC* dbc;
1400 PyObject* txnobj = NULL;
1401 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001402 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403
1404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1405 &txnobj, &flags))
1406 return NULL;
1407 CHECK_DB_NOT_CLOSED(self);
1408 if (!checkTxnObj(txnobj, &txn))
1409 return NULL;
1410
1411 MYDB_BEGIN_ALLOW_THREADS;
1412 err = self->db->cursor(self->db, txn, &dbc, flags);
1413 MYDB_END_ALLOW_THREADS;
1414 RETURN_IF_ERR();
1415 return (PyObject*) newDBCursorObject(dbc, self);
1416}
1417
1418
1419static PyObject*
1420DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1421{
1422 PyObject* txnobj = NULL;
1423 int flags = 0;
1424 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001425 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001426 DBT key;
1427 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001428 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1431 &keyobj, &txnobj, &flags))
1432 return NULL;
1433 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001434 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001436 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001437 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001439 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001440
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001441 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001442 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001444 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001446 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001447 RETURN_NONE();
1448}
1449
1450
1451static PyObject*
1452DB_fd(DBObject* self, PyObject* args)
1453{
1454 int err, the_fd;
1455
1456 if (!PyArg_ParseTuple(args,":fd"))
1457 return NULL;
1458 CHECK_DB_NOT_CLOSED(self);
1459
1460 MYDB_BEGIN_ALLOW_THREADS;
1461 err = self->db->fd(self->db, &the_fd);
1462 MYDB_END_ALLOW_THREADS;
1463 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00001464 return PyLong_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465}
1466
1467
1468static PyObject*
1469DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1470{
1471 int err, flags=0;
1472 PyObject* txnobj = NULL;
1473 PyObject* keyobj;
1474 PyObject* dfltobj = NULL;
1475 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001476 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001477 int dlen = -1;
1478 int doff = -1;
1479 DBT key, data;
1480 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001481 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001482 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001483
1484 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001485 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1486 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
1488
1489 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001490 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001492 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001493 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001494 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001495 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001496
1497 CLEAR_DBT(data);
1498 if (CHECK_DBFLAG(self, DB_THREAD)) {
1499 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1500 data.flags = DB_DBT_MALLOC;
1501 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001502 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001503 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001504 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001506
1507 MYDB_BEGIN_ALLOW_THREADS;
1508 err = self->db->get(self->db, txn, &key, &data, flags);
1509 MYDB_END_ALLOW_THREADS;
1510
Gregory P. Smithe9477062005-06-04 06:46:59 +00001511 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 err = 0;
1513 Py_INCREF(dfltobj);
1514 retval = dfltobj;
1515 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001516 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1517 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001518 err = 0;
1519 Py_INCREF(Py_None);
1520 retval = Py_None;
1521 }
1522 else if (!err) {
1523 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001524 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001525 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001526 else /* return just the data */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001527 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001528 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001530 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001531
1532 RETURN_IF_ERR();
1533 return retval;
1534}
1535
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001536#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001537static PyObject*
1538DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1539{
1540 int err, flags=0;
1541 PyObject* txnobj = NULL;
1542 PyObject* keyobj;
1543 PyObject* dfltobj = NULL;
1544 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001545 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001546 int dlen = -1;
1547 int doff = -1;
1548 DBT key, pkey, data;
1549 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001550 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001551 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001552
1553 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1554 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1555 &doff))
1556 return NULL;
1557
1558 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001559 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001560 return NULL;
1561 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001562 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001563 return NULL;
1564 }
1565
1566 CLEAR_DBT(data);
1567 if (CHECK_DBFLAG(self, DB_THREAD)) {
1568 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1569 data.flags = DB_DBT_MALLOC;
1570 }
1571 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001572 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001573 return NULL;
1574 }
1575
1576 CLEAR_DBT(pkey);
1577 pkey.flags = DB_DBT_MALLOC;
1578
1579 MYDB_BEGIN_ALLOW_THREADS;
1580 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1581 MYDB_END_ALLOW_THREADS;
1582
Gregory P. Smithe9477062005-06-04 06:46:59 +00001583 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001584 err = 0;
1585 Py_INCREF(dfltobj);
1586 retval = dfltobj;
1587 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001588 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1589 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001590 err = 0;
1591 Py_INCREF(Py_None);
1592 retval = Py_None;
1593 }
1594 else if (!err) {
1595 PyObject *pkeyObj;
1596 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00001597 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001598
1599 if (self->primaryDBType == DB_RECNO ||
1600 self->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001601 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001602 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001603 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001604
1605 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1606 {
1607 PyObject *keyObj;
1608 int type = _DB_get_type(self);
1609 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001610 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001611 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001612 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001613#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001614 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001615#else
1616 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1617#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001618 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001619 }
1620 else /* return just the pkey and data */
1621 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001622#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001623 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001624#else
1625 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1626#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001627 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001628 Py_DECREF(dataObj);
1629 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001630 free_dbt(&pkey);
1631 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001633 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001634
1635 RETURN_IF_ERR();
1636 return retval;
1637}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001638#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001639
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640
1641/* Return size of entry */
1642static PyObject*
1643DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1644{
1645 int err, flags=0;
1646 PyObject* txnobj = NULL;
1647 PyObject* keyobj;
1648 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001649 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001650 DBT key, data;
1651 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001652 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001653
1654 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1655 &keyobj, &txnobj))
1656 return NULL;
1657 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001658 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001660 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001661 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001662 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001663 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 CLEAR_DBT(data);
1665
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001666 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1667 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668 data.flags = DB_DBT_USERMEM;
1669 data.ulen = 0;
1670 MYDB_BEGIN_ALLOW_THREADS;
1671 err = self->db->get(self->db, txn, &key, &data, flags);
1672 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001673 if (err == DB_BUFFER_SMALL) {
Christian Heimes217cfd12007-12-02 14:31:20 +00001674 retval = PyLong_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001675 err = 0;
1676 }
1677
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001678 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1679 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001680 RETURN_IF_ERR();
1681 return retval;
1682}
1683
1684
1685static PyObject*
1686DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1687{
1688 int err, flags=0;
1689 PyObject* txnobj = NULL;
1690 PyObject* keyobj;
1691 PyObject* dataobj;
1692 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001693 Py_buffer* data_buf_view = NULL;
1694 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001695 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001696 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001697 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001698 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001699
1700
1701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1702 &keyobj, &dataobj, &txnobj, &flags))
1703 return NULL;
1704
1705 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001706 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001707 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001708 if ( !checkTxnObj(txnobj, &txn) ||
1709 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001710 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001711 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001712 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001713 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714
1715 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001716 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001720 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001722 }
1723
1724 MYDB_BEGIN_ALLOW_THREADS;
1725 err = self->db->get(self->db, txn, &key, &data, flags);
1726 MYDB_END_ALLOW_THREADS;
1727
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001728 free_buf_view(dataobj, data_buf_view);
1729
Gregory P. Smithe9477062005-06-04 06:46:59 +00001730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1735 }
1736 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001737 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001738 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001739 /* XXX(guido) But what if the input is PyString? */
1740 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001741
1742 /* Even though the flags require DB_DBT_MALLOC, data is not always
1743 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1744 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001745 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746 }
1747
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001748 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001749 RETURN_IF_ERR();
1750 return retval;
1751}
1752
1753
1754static PyObject*
1755DB_get_byteswapped(DBObject* self, PyObject* args)
1756{
1757#if (DBVER >= 33)
1758 int err = 0;
1759#endif
1760 int retval = -1;
1761
1762 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1763 return NULL;
1764 CHECK_DB_NOT_CLOSED(self);
1765
1766#if (DBVER >= 33)
1767 MYDB_BEGIN_ALLOW_THREADS;
1768 err = self->db->get_byteswapped(self->db, &retval);
1769 MYDB_END_ALLOW_THREADS;
1770 RETURN_IF_ERR();
1771#else
1772 MYDB_BEGIN_ALLOW_THREADS;
1773 retval = self->db->get_byteswapped(self->db);
1774 MYDB_END_ALLOW_THREADS;
1775#endif
Christian Heimes217cfd12007-12-02 14:31:20 +00001776 return PyLong_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001777}
1778
1779
1780static PyObject*
1781DB_get_type(DBObject* self, PyObject* args)
1782{
1783 int type;
1784
1785 if (!PyArg_ParseTuple(args,":get_type"))
1786 return NULL;
1787 CHECK_DB_NOT_CLOSED(self);
1788
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001789 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001790 if (type == -1)
1791 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00001792 return PyLong_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001793}
1794
1795
1796static PyObject*
1797DB_join(DBObject* self, PyObject* args)
1798{
1799 int err, flags=0;
1800 int length, x;
1801 PyObject* cursorsObj;
1802 DBC** cursors;
1803 DBC* dbc;
1804
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001805 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1806 return NULL;
1807
1808 CHECK_DB_NOT_CLOSED(self);
1809
1810 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001811 PyErr_SetString(PyExc_TypeError,
1812 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001813 return NULL;
1814 }
1815
1816 length = PyObject_Length(cursorsObj);
1817 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001818 if (!cursors) {
1819 PyErr_NoMemory();
1820 return NULL;
1821 }
1822
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 cursors[length] = NULL;
1824 for (x=0; x<length; x++) {
1825 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001826 if (item == NULL) {
1827 free(cursors);
1828 return NULL;
1829 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001830 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001831 PyErr_SetString(PyExc_TypeError,
1832 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 free(cursors);
1834 return NULL;
1835 }
1836 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001837 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001838 }
1839
1840 MYDB_BEGIN_ALLOW_THREADS;
1841 err = self->db->join(self->db, cursors, &dbc, flags);
1842 MYDB_END_ALLOW_THREADS;
1843 free(cursors);
1844 RETURN_IF_ERR();
1845
Gregory P. Smith7441e652003-11-03 21:35:31 +00001846 /* FIXME: this is a buggy interface. The returned cursor
1847 contains internal references to the passed in cursors
1848 but does not hold python references to them or prevent
1849 them from being closed prematurely. This can cause
1850 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001851 return (PyObject*) newDBCursorObject(dbc, self);
1852}
1853
1854
1855static PyObject*
1856DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1857{
1858 int err, flags=0;
1859 PyObject* txnobj = NULL;
1860 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001861 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001862 DBT key;
1863 DB_TXN *txn = NULL;
1864 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001865 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001866
1867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1868 &keyobj, &txnobj, &flags))
1869 return NULL;
1870 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001871 if (!checkTxnObj(txnobj, &txn))
1872 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001873 if (!make_dbt(keyobj, &key, &key_buf_view))
1874 /* BTree only, don't need to allow for an int key */
1875 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001876
1877 MYDB_BEGIN_ALLOW_THREADS;
1878 err = self->db->key_range(self->db, txn, &key, &range, flags);
1879 MYDB_END_ALLOW_THREADS;
1880
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001881 free_buf_view(keyobj, key_buf_view);
1882
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001883 RETURN_IF_ERR();
1884 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1885}
1886
1887
1888static PyObject*
1889DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1890{
1891 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1892 char* filename = NULL;
1893 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001894#if (DBVER >= 41)
1895 PyObject *txnobj = NULL;
1896 DB_TXN *txn = NULL;
1897 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001898 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001899 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1900 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001901 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001902 "filename", "dbtype", "flags", "mode", "txn", NULL};
1903#else
1904 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001905 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001906 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1907 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001908 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001909 "filename", "dbtype", "flags", "mode", NULL};
1910#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001912#if (DBVER >= 41)
1913 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1914 &filename, &dbname, &type, &flags, &mode,
1915 &txnobj))
1916#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918 &filename, &dbname, &type, &flags,
1919 &mode))
1920#endif
1921 {
1922 PyErr_Clear();
1923 type = DB_UNKNOWN; flags = 0; mode = 0660;
1924 filename = NULL; dbname = NULL;
1925#if (DBVER >= 41)
1926 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1927 kwnames_basic,
1928 &filename, &type, &flags, &mode,
1929 &txnobj))
1930 return NULL;
1931#else
1932 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1933 kwnames_basic,
1934 &filename, &type, &flags, &mode))
1935 return NULL;
1936#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001937 }
1938
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001939#if (DBVER >= 41)
1940 if (!checkTxnObj(txnobj, &txn)) return NULL;
1941#endif
1942
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001943 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001944 PyObject *t = Py_BuildValue("(is)", 0,
1945 "Cannot call open() twice for DB object");
1946 PyErr_SetObject(DBError, t);
1947 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 return NULL;
1949 }
1950
1951 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001952#if (DBVER >= 41)
1953 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1954#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001955 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001956#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 MYDB_END_ALLOW_THREADS;
1958 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001959 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 self->db = NULL;
1961 return NULL;
1962 }
1963
Guido van Rossum77677112007-11-05 19:43:04 +00001964#if (DBVER >= 42)
1965 self->db->get_flags(self->db, &self->setflags);
1966#endif
1967
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001968 self->flags = flags;
1969 RETURN_NONE();
1970}
1971
1972
1973static PyObject*
1974DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1975{
1976 int flags=0;
1977 PyObject* txnobj = NULL;
1978 int dlen = -1;
1979 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001980 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001981 Py_buffer *data_buf_view = NULL;
1982 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 DBT key, data;
1984 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001985 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001986 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001987
1988 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1989 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1990 return NULL;
1991
1992 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001993 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001994 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001995 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001996 !add_partial_dbt(&data, dlen, doff) ||
1997 !checkTxnObj(txnobj, &txn) )
1998 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001999 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2000 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002001 return NULL;
2002 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002003
2004 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002005 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2006 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002007 return NULL;
2008 }
2009
2010 if (flags & DB_APPEND)
Christian Heimes217cfd12007-12-02 14:31:20 +00002011 retval = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002012 else {
2013 retval = Py_None;
2014 Py_INCREF(retval);
2015 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002016 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2017 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002018 return retval;
2019}
2020
2021
2022
2023static PyObject*
2024DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2025{
2026 char* filename;
2027 char* database = NULL;
2028 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002029 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002030
2031 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2032 &filename, &database, &flags))
2033 return NULL;
2034 CHECK_DB_NOT_CLOSED(self);
2035
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002036 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002037 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002038 RETURN_IF_ERR();
2039 RETURN_NONE();
2040}
2041
2042
2043
2044static PyObject*
2045DB_rename(DBObject* self, PyObject* args)
2046{
2047 char* filename;
2048 char* database;
2049 char* newname;
2050 int err, flags=0;
2051
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002052 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2053 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002054 return NULL;
2055 CHECK_DB_NOT_CLOSED(self);
2056
2057 MYDB_BEGIN_ALLOW_THREADS;
2058 err = self->db->rename(self->db, filename, database, newname, flags);
2059 MYDB_END_ALLOW_THREADS;
2060 RETURN_IF_ERR();
2061 RETURN_NONE();
2062}
2063
2064
2065static PyObject*
2066DB_set_bt_minkey(DBObject* self, PyObject* args)
2067{
2068 int err, minkey;
2069
2070 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2071 return NULL;
2072 CHECK_DB_NOT_CLOSED(self);
2073
2074 MYDB_BEGIN_ALLOW_THREADS;
2075 err = self->db->set_bt_minkey(self->db, minkey);
2076 MYDB_END_ALLOW_THREADS;
2077 RETURN_IF_ERR();
2078 RETURN_NONE();
2079}
2080
Neal Norwitz84562352005-10-20 04:30:15 +00002081#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002082static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002083_default_cmp(const DBT *leftKey,
2084 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002085{
2086 int res;
2087 int lsize = leftKey->size, rsize = rightKey->size;
2088
Georg Brandlef1701f2006-03-07 14:57:48 +00002089 res = memcmp(leftKey->data, rightKey->data,
2090 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002091
2092 if (res == 0) {
2093 if (lsize < rsize) {
2094 res = -1;
2095 }
2096 else if (lsize > rsize) {
2097 res = 1;
2098 }
2099 }
2100 return res;
2101}
2102
2103static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002104_db_compareCallback(DB* db,
2105 const DBT *leftKey,
2106 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107{
2108 int res = 0;
2109 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002110 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002111 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002112
2113 if (self == NULL || self->btCompareCallback == NULL) {
2114 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002115 PyErr_SetString(PyExc_TypeError,
2116 (self == 0
2117 ? "DB_bt_compare db is NULL."
2118 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002119 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 PyErr_Print();
2121 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002122 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002123 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002124 MYDB_BEGIN_BLOCK_THREADS;
2125
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002126 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002127 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002129 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002132 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002135 PyErr_Print();
2136 res = _default_cmp(leftKey, rightKey);
Christian Heimes217cfd12007-12-02 14:31:20 +00002137 } else if (PyLong_Check(result)) {
2138 res = PyLong_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002139 } else {
2140 PyErr_SetString(PyExc_TypeError,
2141 "DB_bt_compare callback MUST return an int.");
2142 /* we're in a callback within the DB code, we can't raise */
2143 PyErr_Print();
2144 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002145 }
2146
Thomas Woutersb3153832006-03-08 01:47:19 +00002147 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149
2150 MYDB_END_BLOCK_THREADS;
2151 }
2152 return res;
2153}
2154
2155static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002156DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002157{
2158 int err;
2159 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002160 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002161
Georg Brandlef1701f2006-03-07 14:57:48 +00002162 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163 return NULL;
2164
Georg Brandlef1701f2006-03-07 14:57:48 +00002165 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166
Georg Brandlef1701f2006-03-07 14:57:48 +00002167 if (!PyCallable_Check(comparator)) {
2168 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002169 return NULL;
2170 }
2171
2172 /*
2173 * Perform a test call of the comparator function with two empty
2174 * string objects here. verify that it returns an int (0).
2175 * err if not.
2176 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002177 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002178 result = PyEval_CallObject(comparator, tuple);
2179 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002180 if (result == NULL)
2181 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002182 if (!PyLong_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 PyErr_SetString(PyExc_TypeError,
2184 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002185 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002186 } else if (PyLong_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002187 PyErr_SetString(PyExc_TypeError,
2188 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002189 return NULL;
2190 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002191 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002192
2193 /* We don't accept multiple set_bt_compare operations, in order to
2194 * simplify the code. This would have no real use, as one cannot
2195 * change the function once the db is opened anyway */
2196 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002197 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002198 return NULL;
2199 }
2200
Georg Brandlef1701f2006-03-07 14:57:48 +00002201 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002202 self->btCompareCallback = comparator;
2203
2204 /* This is to workaround a problem with un-initialized threads (see
2205 comment in DB_associate) */
2206#ifdef WITH_THREAD
2207 PyEval_InitThreads();
2208#endif
2209
Thomas Woutersb3153832006-03-08 01:47:19 +00002210 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211
2212 if (err) {
2213 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002214 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002215 self->btCompareCallback = NULL;
2216 }
2217
Georg Brandlef1701f2006-03-07 14:57:48 +00002218 RETURN_IF_ERR();
2219 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002220}
Neal Norwitz84562352005-10-20 04:30:15 +00002221#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002222
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002223
2224static PyObject*
2225DB_set_cachesize(DBObject* self, PyObject* args)
2226{
2227 int err;
2228 int gbytes = 0, bytes = 0, ncache = 0;
2229
2230 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2231 &gbytes,&bytes,&ncache))
2232 return NULL;
2233 CHECK_DB_NOT_CLOSED(self);
2234
2235 MYDB_BEGIN_ALLOW_THREADS;
2236 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2237 MYDB_END_ALLOW_THREADS;
2238 RETURN_IF_ERR();
2239 RETURN_NONE();
2240}
2241
2242
2243static PyObject*
2244DB_set_flags(DBObject* self, PyObject* args)
2245{
2246 int err, flags;
2247
2248 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2249 return NULL;
2250 CHECK_DB_NOT_CLOSED(self);
2251
2252 MYDB_BEGIN_ALLOW_THREADS;
2253 err = self->db->set_flags(self->db, flags);
2254 MYDB_END_ALLOW_THREADS;
2255 RETURN_IF_ERR();
2256
2257 self->setflags |= flags;
2258 RETURN_NONE();
2259}
2260
2261
2262static PyObject*
2263DB_set_h_ffactor(DBObject* self, PyObject* args)
2264{
2265 int err, ffactor;
2266
2267 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2268 return NULL;
2269 CHECK_DB_NOT_CLOSED(self);
2270
2271 MYDB_BEGIN_ALLOW_THREADS;
2272 err = self->db->set_h_ffactor(self->db, ffactor);
2273 MYDB_END_ALLOW_THREADS;
2274 RETURN_IF_ERR();
2275 RETURN_NONE();
2276}
2277
2278
2279static PyObject*
2280DB_set_h_nelem(DBObject* self, PyObject* args)
2281{
2282 int err, nelem;
2283
2284 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2285 return NULL;
2286 CHECK_DB_NOT_CLOSED(self);
2287
2288 MYDB_BEGIN_ALLOW_THREADS;
2289 err = self->db->set_h_nelem(self->db, nelem);
2290 MYDB_END_ALLOW_THREADS;
2291 RETURN_IF_ERR();
2292 RETURN_NONE();
2293}
2294
2295
2296static PyObject*
2297DB_set_lorder(DBObject* self, PyObject* args)
2298{
2299 int err, lorder;
2300
2301 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2302 return NULL;
2303 CHECK_DB_NOT_CLOSED(self);
2304
2305 MYDB_BEGIN_ALLOW_THREADS;
2306 err = self->db->set_lorder(self->db, lorder);
2307 MYDB_END_ALLOW_THREADS;
2308 RETURN_IF_ERR();
2309 RETURN_NONE();
2310}
2311
2312
2313static PyObject*
2314DB_set_pagesize(DBObject* self, PyObject* args)
2315{
2316 int err, pagesize;
2317
2318 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2319 return NULL;
2320 CHECK_DB_NOT_CLOSED(self);
2321
2322 MYDB_BEGIN_ALLOW_THREADS;
2323 err = self->db->set_pagesize(self->db, pagesize);
2324 MYDB_END_ALLOW_THREADS;
2325 RETURN_IF_ERR();
2326 RETURN_NONE();
2327}
2328
2329
2330static PyObject*
2331DB_set_re_delim(DBObject* self, PyObject* args)
2332{
2333 int err;
2334 char delim;
2335
2336 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2337 PyErr_Clear();
2338 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2339 return NULL;
2340 }
2341
2342 CHECK_DB_NOT_CLOSED(self);
2343
2344 MYDB_BEGIN_ALLOW_THREADS;
2345 err = self->db->set_re_delim(self->db, delim);
2346 MYDB_END_ALLOW_THREADS;
2347 RETURN_IF_ERR();
2348 RETURN_NONE();
2349}
2350
2351static PyObject*
2352DB_set_re_len(DBObject* self, PyObject* args)
2353{
2354 int err, len;
2355
2356 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2357 return NULL;
2358 CHECK_DB_NOT_CLOSED(self);
2359
2360 MYDB_BEGIN_ALLOW_THREADS;
2361 err = self->db->set_re_len(self->db, len);
2362 MYDB_END_ALLOW_THREADS;
2363 RETURN_IF_ERR();
2364 RETURN_NONE();
2365}
2366
2367
2368static PyObject*
2369DB_set_re_pad(DBObject* self, PyObject* args)
2370{
2371 int err;
2372 char pad;
2373
2374 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2375 PyErr_Clear();
2376 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2377 return NULL;
2378 }
2379 CHECK_DB_NOT_CLOSED(self);
2380
2381 MYDB_BEGIN_ALLOW_THREADS;
2382 err = self->db->set_re_pad(self->db, pad);
2383 MYDB_END_ALLOW_THREADS;
2384 RETURN_IF_ERR();
2385 RETURN_NONE();
2386}
2387
2388
2389static PyObject*
2390DB_set_re_source(DBObject* self, PyObject* args)
2391{
2392 int err;
2393 char *re_source;
2394
2395 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2396 return NULL;
2397 CHECK_DB_NOT_CLOSED(self);
2398
2399 MYDB_BEGIN_ALLOW_THREADS;
2400 err = self->db->set_re_source(self->db, re_source);
2401 MYDB_END_ALLOW_THREADS;
2402 RETURN_IF_ERR();
2403 RETURN_NONE();
2404}
2405
2406
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002407static PyObject*
2408DB_set_q_extentsize(DBObject* self, PyObject* args)
2409{
2410 int err;
2411 int extentsize;
2412
2413 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2414 return NULL;
2415 CHECK_DB_NOT_CLOSED(self);
2416
2417 MYDB_BEGIN_ALLOW_THREADS;
2418 err = self->db->set_q_extentsize(self->db, extentsize);
2419 MYDB_END_ALLOW_THREADS;
2420 RETURN_IF_ERR();
2421 RETURN_NONE();
2422}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002423
2424static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002425DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426{
2427 int err, flags = 0, type;
2428 void* sp;
2429 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430#if (DBVER >= 43)
2431 PyObject* txnobj = NULL;
2432 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002433 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002435 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002436#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002437
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438#if (DBVER >= 43)
2439 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2440 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002442 if (!checkTxnObj(txnobj, &txn))
2443 return NULL;
2444#else
2445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2446 return NULL;
2447#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002448 CHECK_DB_NOT_CLOSED(self);
2449
2450 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002451#if (DBVER >= 43)
2452 err = self->db->stat(self->db, txn, &sp, flags);
2453#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002454 err = self->db->stat(self->db, &sp, flags);
2455#else
2456 err = self->db->stat(self->db, &sp, NULL, flags);
2457#endif
2458 MYDB_END_ALLOW_THREADS;
2459 RETURN_IF_ERR();
2460
2461 self->haveStat = 1;
2462
2463 /* Turn the stat structure into a dictionary */
2464 type = _DB_get_type(self);
2465 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2466 free(sp);
2467 return NULL;
2468 }
2469
2470#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2471#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2472#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2473
2474 switch (type) {
2475 case DB_HASH:
2476 MAKE_HASH_ENTRY(magic);
2477 MAKE_HASH_ENTRY(version);
2478 MAKE_HASH_ENTRY(nkeys);
2479 MAKE_HASH_ENTRY(ndata);
2480 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002481#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002482 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002483#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002484 MAKE_HASH_ENTRY(ffactor);
2485 MAKE_HASH_ENTRY(buckets);
2486 MAKE_HASH_ENTRY(free);
2487 MAKE_HASH_ENTRY(bfree);
2488 MAKE_HASH_ENTRY(bigpages);
2489 MAKE_HASH_ENTRY(big_bfree);
2490 MAKE_HASH_ENTRY(overflows);
2491 MAKE_HASH_ENTRY(ovfl_free);
2492 MAKE_HASH_ENTRY(dup);
2493 MAKE_HASH_ENTRY(dup_free);
2494 break;
2495
2496 case DB_BTREE:
2497 case DB_RECNO:
2498 MAKE_BT_ENTRY(magic);
2499 MAKE_BT_ENTRY(version);
2500 MAKE_BT_ENTRY(nkeys);
2501 MAKE_BT_ENTRY(ndata);
2502 MAKE_BT_ENTRY(pagesize);
2503 MAKE_BT_ENTRY(minkey);
2504 MAKE_BT_ENTRY(re_len);
2505 MAKE_BT_ENTRY(re_pad);
2506 MAKE_BT_ENTRY(levels);
2507 MAKE_BT_ENTRY(int_pg);
2508 MAKE_BT_ENTRY(leaf_pg);
2509 MAKE_BT_ENTRY(dup_pg);
2510 MAKE_BT_ENTRY(over_pg);
2511 MAKE_BT_ENTRY(free);
2512 MAKE_BT_ENTRY(int_pgfree);
2513 MAKE_BT_ENTRY(leaf_pgfree);
2514 MAKE_BT_ENTRY(dup_pgfree);
2515 MAKE_BT_ENTRY(over_pgfree);
2516 break;
2517
2518 case DB_QUEUE:
2519 MAKE_QUEUE_ENTRY(magic);
2520 MAKE_QUEUE_ENTRY(version);
2521 MAKE_QUEUE_ENTRY(nkeys);
2522 MAKE_QUEUE_ENTRY(ndata);
2523 MAKE_QUEUE_ENTRY(pagesize);
2524 MAKE_QUEUE_ENTRY(pages);
2525 MAKE_QUEUE_ENTRY(re_len);
2526 MAKE_QUEUE_ENTRY(re_pad);
2527 MAKE_QUEUE_ENTRY(pgfree);
2528#if (DBVER == 31)
2529 MAKE_QUEUE_ENTRY(start);
2530#endif
2531 MAKE_QUEUE_ENTRY(first_recno);
2532 MAKE_QUEUE_ENTRY(cur_recno);
2533 break;
2534
2535 default:
2536 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2537 Py_DECREF(d);
2538 d = NULL;
2539 }
2540
2541#undef MAKE_HASH_ENTRY
2542#undef MAKE_BT_ENTRY
2543#undef MAKE_QUEUE_ENTRY
2544
2545 free(sp);
2546 return d;
2547}
2548
2549static PyObject*
2550DB_sync(DBObject* self, PyObject* args)
2551{
2552 int err;
2553 int flags = 0;
2554
2555 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2556 return NULL;
2557 CHECK_DB_NOT_CLOSED(self);
2558
2559 MYDB_BEGIN_ALLOW_THREADS;
2560 err = self->db->sync(self->db, flags);
2561 MYDB_END_ALLOW_THREADS;
2562 RETURN_IF_ERR();
2563 RETURN_NONE();
2564}
2565
2566
2567#if (DBVER >= 33)
2568static PyObject*
2569DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2570{
2571 int err, flags=0;
2572 u_int32_t count=0;
2573 PyObject* txnobj = NULL;
2574 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002575 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002576
2577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2578 &txnobj, &flags))
2579 return NULL;
2580 CHECK_DB_NOT_CLOSED(self);
2581 if (!checkTxnObj(txnobj, &txn))
2582 return NULL;
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->truncate(self->db, txn, &count, flags);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00002588 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002589}
2590#endif
2591
2592
2593static PyObject*
2594DB_upgrade(DBObject* self, PyObject* args)
2595{
2596 int err, flags=0;
2597 char *filename;
2598
2599 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2600 return NULL;
2601 CHECK_DB_NOT_CLOSED(self);
2602
2603 MYDB_BEGIN_ALLOW_THREADS;
2604 err = self->db->upgrade(self->db, filename, flags);
2605 MYDB_END_ALLOW_THREADS;
2606 RETURN_IF_ERR();
2607 RETURN_NONE();
2608}
2609
2610
2611static PyObject*
2612DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2613{
2614 int err, flags=0;
2615 char* fileName;
2616 char* dbName=NULL;
2617 char* outFileName=NULL;
2618 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002619 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002620 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002621
2622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2623 &fileName, &dbName, &outFileName, &flags))
2624 return NULL;
2625
2626 CHECK_DB_NOT_CLOSED(self);
2627 if (outFileName)
2628 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002629 /* XXX(nnorwitz): it should probably be an exception if outFile
2630 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002631
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2634 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002635 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002637
2638 /* DB.verify acts as a DB handle destructor (like close); this was
2639 * documented in BerkeleyDB 4.2 but had the undocumented effect
2640 * of not being safe in prior versions while still requiring an explicit
2641 * DB.close call afterwards. Lets call close for the user to emulate
2642 * the safe 4.2 behaviour. */
2643#if (DBVER <= 41)
2644 self->db->close(self->db, 0);
2645#endif
2646 self->db = NULL;
2647
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002648 RETURN_IF_ERR();
2649 RETURN_NONE();
2650}
2651
2652
2653static PyObject*
2654DB_set_get_returns_none(DBObject* self, PyObject* args)
2655{
2656 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002657 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658
2659 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2660 return NULL;
2661 CHECK_DB_NOT_CLOSED(self);
2662
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002663 if (self->moduleFlags.getReturnsNone)
2664 ++oldValue;
2665 if (self->moduleFlags.cursorSetReturnsNone)
2666 ++oldValue;
2667 self->moduleFlags.getReturnsNone = (flags >= 1);
2668 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00002669 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002670}
2671
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002672#if (DBVER >= 41)
2673static PyObject*
2674DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2675{
2676 int err;
2677 u_int32_t flags=0;
2678 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002679 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002680
2681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2682 &passwd, &flags)) {
2683 return NULL;
2684 }
2685
2686 MYDB_BEGIN_ALLOW_THREADS;
2687 err = self->db->set_encrypt(self->db, passwd, flags);
2688 MYDB_END_ALLOW_THREADS;
2689
2690 RETURN_IF_ERR();
2691 RETURN_NONE();
2692}
2693#endif /* DBVER >= 41 */
2694
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695
2696/*-------------------------------------------------------------- */
2697/* Mapping and Dictionary-like access routines */
2698
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002699Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700{
2701 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002702 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703 int flags = 0;
2704 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002705 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706
2707 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002708 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2709 PyErr_SetObject(DBError, t);
2710 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002711 return -1;
2712 }
2713
2714 if (self->haveStat) { /* Has the stat function been called recently? If
2715 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002716 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717 }
2718
2719 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002720redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002721#if (DBVER >= 43)
2722 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2723#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002724 err = self->db->stat(self->db, &sp, flags);
2725#else
2726 err = self->db->stat(self->db, &sp, NULL, flags);
2727#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002728
2729 /* All the stat structures have matching fields upto the ndata field,
2730 so we can use any of them for the type cast */
2731 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2732
2733 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2734 * redo a full stat to make sure.
2735 * Fixes SF python bug 1493322, pybsddb bug 1184012
2736 */
2737 if (size == 0 && (flags & DB_FAST_STAT)) {
2738 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002739 if (!err)
2740 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002741 goto redo_stat_for_length;
2742 }
2743
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 MYDB_END_ALLOW_THREADS;
2745
2746 if (err)
2747 return -1;
2748
2749 self->haveStat = 1;
2750
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002751 free(sp);
2752 return size;
2753}
2754
2755
2756PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2757{
2758 int err;
2759 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002760 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002761 DBT key;
2762 DBT data;
2763
2764 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002765 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002766 return NULL;
2767
2768 CLEAR_DBT(data);
2769 if (CHECK_DBFLAG(self, DB_THREAD)) {
2770 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2771 data.flags = DB_DBT_MALLOC;
2772 }
2773 MYDB_BEGIN_ALLOW_THREADS;
2774 err = self->db->get(self->db, NULL, &key, &data, 0);
2775 MYDB_END_ALLOW_THREADS;
2776 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2777 PyErr_SetObject(PyExc_KeyError, keyobj);
2778 retval = NULL;
2779 }
2780 else if (makeDBError(err)) {
2781 retval = NULL;
2782 }
2783 else {
Guido van Rossum98297ee2007-11-06 21:34:58 +00002784 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002785 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 }
2787
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002788 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002789 return retval;
2790}
2791
2792
2793static int
2794DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2795{
2796 DBT key, data;
2797 int retval;
2798 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002799 Py_buffer *data_buf_view = NULL;
2800 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801
2802 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002803 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2804 PyErr_SetObject(DBError, t);
2805 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806 return -1;
2807 }
2808
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002809 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002810 return -1;
2811
2812 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002813 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002814 retval = -1;
2815 else {
2816 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002817 /* dictionaries shouldn't have duplicate keys */
2818 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002819 retval = _DB_put(self, NULL, &key, &data, flags);
2820
2821 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002822 /* try deleting any old record that matches and then PUT it
2823 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824 _DB_delete(self, NULL, &key, 0);
2825 PyErr_Clear();
2826 retval = _DB_put(self, NULL, &key, &data, flags);
2827 }
2828 }
2829 }
2830 else {
2831 /* dataobj == NULL, so delete the key */
2832 retval = _DB_delete(self, NULL, &key, 0);
2833 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002834 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2835 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836 return retval;
2837}
2838
2839
2840static PyObject*
2841DB_has_key(DBObject* self, PyObject* args)
2842{
2843 int err;
2844 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002845 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 DBT key, data;
2847 PyObject* txnobj = NULL;
2848 DB_TXN *txn = NULL;
2849
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002850 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 return NULL;
2852 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002853 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002855 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002856 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002858 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002859
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002860 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 it has a record but can't allocate a buffer for the data. This saves
2862 having to deal with data we won't be using.
2863 */
2864 CLEAR_DBT(data);
2865 data.flags = DB_DBT_USERMEM;
2866
2867 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002868 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002870 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002871
2872 if (err == DB_BUFFER_SMALL || err == 0) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002873 return PyLong_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002874 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002875 return PyLong_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002876 }
2877
2878 makeDBError(err);
2879 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880}
2881
2882
2883#define _KEYS_LIST 1
2884#define _VALUES_LIST 2
2885#define _ITEMS_LIST 3
2886
2887static PyObject*
2888_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2889{
2890 int err, dbtype;
2891 DBT key;
2892 DBT data;
2893 DBC *cursor;
2894 PyObject* list;
2895 PyObject* item = NULL;
2896
2897 CHECK_DB_NOT_CLOSED(self);
2898 CLEAR_DBT(key);
2899 CLEAR_DBT(data);
2900
2901 dbtype = _DB_get_type(self);
2902 if (dbtype == -1)
2903 return NULL;
2904
2905 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002906 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002908
2909 /* get a cursor */
2910 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002911 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002912 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002913 if (makeDBError(err)) {
2914 Py_DECREF(list);
2915 return NULL;
2916 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002917
2918 if (CHECK_DBFLAG(self, DB_THREAD)) {
2919 key.flags = DB_DBT_REALLOC;
2920 data.flags = DB_DBT_REALLOC;
2921 }
2922
2923 while (1) { /* use the cursor to traverse the DB, collecting items */
2924 MYDB_BEGIN_ALLOW_THREADS;
2925 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2926 MYDB_END_ALLOW_THREADS;
2927
2928 if (err) {
2929 /* for any error, break out of the loop */
2930 break;
2931 }
2932
2933 switch (type) {
2934 case _KEYS_LIST:
2935 switch(dbtype) {
2936 case DB_BTREE:
2937 case DB_HASH:
2938 default:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002939 item = PyString_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002940 break;
2941 case DB_RECNO:
2942 case DB_QUEUE:
Christian Heimes217cfd12007-12-02 14:31:20 +00002943 item = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002944 break;
2945 }
2946 break;
2947
2948 case _VALUES_LIST:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002949 item = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002950 break;
2951
2952 case _ITEMS_LIST:
2953 switch(dbtype) {
2954 case DB_BTREE:
2955 case DB_HASH:
2956 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002957 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002958 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002959 break;
2960 case DB_RECNO:
2961 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002962 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002963 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002964 break;
2965 }
2966 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002967 default:
2968 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2969 item = NULL;
2970 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971 }
2972 if (item == NULL) {
2973 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002974 list = NULL;
2975 goto done;
2976 }
2977 PyList_Append(list, item);
2978 Py_DECREF(item);
2979 }
2980
Gregory P. Smithe9477062005-06-04 06:46:59 +00002981 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2982 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983 Py_DECREF(list);
2984 list = NULL;
2985 }
2986
2987 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002988 free_dbt(&key);
2989 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990 MYDB_BEGIN_ALLOW_THREADS;
2991 cursor->c_close(cursor);
2992 MYDB_END_ALLOW_THREADS;
2993 return list;
2994}
2995
2996
2997static PyObject*
2998DB_keys(DBObject* self, PyObject* args)
2999{
3000 PyObject* txnobj = NULL;
3001 DB_TXN *txn = NULL;
3002
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003003 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003004 return NULL;
3005 if (!checkTxnObj(txnobj, &txn))
3006 return NULL;
3007 return _DB_make_list(self, txn, _KEYS_LIST);
3008}
3009
3010
3011static PyObject*
3012DB_items(DBObject* self, PyObject* args)
3013{
3014 PyObject* txnobj = NULL;
3015 DB_TXN *txn = NULL;
3016
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003017 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003018 return NULL;
3019 if (!checkTxnObj(txnobj, &txn))
3020 return NULL;
3021 return _DB_make_list(self, txn, _ITEMS_LIST);
3022}
3023
3024
3025static PyObject*
3026DB_values(DBObject* self, PyObject* args)
3027{
3028 PyObject* txnobj = NULL;
3029 DB_TXN *txn = NULL;
3030
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003031 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003032 return NULL;
3033 if (!checkTxnObj(txnobj, &txn))
3034 return NULL;
3035 return _DB_make_list(self, txn, _VALUES_LIST);
3036}
3037
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003038/* --------------------------------------------------------------------- */
3039/* DBCursor methods */
3040
3041
3042static PyObject*
3043DBC_close(DBCursorObject* self, PyObject* args)
3044{
3045 int err = 0;
3046
3047 if (!PyArg_ParseTuple(args, ":close"))
3048 return NULL;
3049
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 if (self->dbc != NULL) {
3051 MYDB_BEGIN_ALLOW_THREADS;
3052 err = self->dbc->c_close(self->dbc);
3053 self->dbc = NULL;
3054 MYDB_END_ALLOW_THREADS;
3055 }
3056 RETURN_IF_ERR();
3057 RETURN_NONE();
3058}
3059
3060
3061static PyObject*
3062DBC_count(DBCursorObject* self, PyObject* args)
3063{
3064 int err = 0;
3065 db_recno_t count;
3066 int flags = 0;
3067
3068 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3069 return NULL;
3070
3071 CHECK_CURSOR_NOT_CLOSED(self);
3072
3073 MYDB_BEGIN_ALLOW_THREADS;
3074 err = self->dbc->c_count(self->dbc, &count, flags);
3075 MYDB_END_ALLOW_THREADS;
3076 RETURN_IF_ERR();
3077
Christian Heimes217cfd12007-12-02 14:31:20 +00003078 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079}
3080
3081
3082static PyObject*
3083DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3084{
3085 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3086}
3087
3088
3089static PyObject*
3090DBC_delete(DBCursorObject* self, PyObject* args)
3091{
3092 int err, flags=0;
3093
3094 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3095 return NULL;
3096
3097 CHECK_CURSOR_NOT_CLOSED(self);
3098
3099 MYDB_BEGIN_ALLOW_THREADS;
3100 err = self->dbc->c_del(self->dbc, flags);
3101 MYDB_END_ALLOW_THREADS;
3102 RETURN_IF_ERR();
3103
3104 self->mydb->haveStat = 0;
3105 RETURN_NONE();
3106}
3107
3108
3109static PyObject*
3110DBC_dup(DBCursorObject* self, PyObject* args)
3111{
3112 int err, flags =0;
3113 DBC* dbc = NULL;
3114
3115 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3116 return NULL;
3117
3118 CHECK_CURSOR_NOT_CLOSED(self);
3119
3120 MYDB_BEGIN_ALLOW_THREADS;
3121 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3122 MYDB_END_ALLOW_THREADS;
3123 RETURN_IF_ERR();
3124
3125 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3126}
3127
3128static PyObject*
3129DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3130{
3131 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3132}
3133
3134
3135static PyObject*
3136DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3137{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003138 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003139 PyObject* keyobj = NULL;
3140 PyObject* dataobj = NULL;
3141 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003142 Py_buffer* data_buf_view = NULL;
3143 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003144 int dlen = -1;
3145 int doff = -1;
3146 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003147 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003148 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149
3150 CLEAR_DBT(key);
3151 CLEAR_DBT(data);
3152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003153 &flags, &dlen, &doff))
3154 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003155 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003156 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3157 &kwnames[1],
3158 &keyobj, &flags, &dlen, &doff))
3159 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003160 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3162 kwnames, &keyobj, &dataobj,
3163 &flags, &dlen, &doff))
3164 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 return NULL;
3166 }
3167 }
3168 }
3169
3170 CHECK_CURSOR_NOT_CLOSED(self);
3171
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003172 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003174 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003175 (!add_partial_dbt(&data, dlen, doff)) )
3176 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003177 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3178 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003180 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003181
3182 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3183 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003184 if (!(key.flags & DB_DBT_REALLOC)) {
3185 key.flags |= DB_DBT_MALLOC;
3186 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003187 }
3188
3189 MYDB_BEGIN_ALLOW_THREADS;
3190 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3191 MYDB_END_ALLOW_THREADS;
3192
Gregory P. Smithe9477062005-06-04 06:46:59 +00003193 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3194 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003195 Py_INCREF(Py_None);
3196 retval = Py_None;
3197 }
3198 else if (makeDBError(err)) {
3199 retval = NULL;
3200 }
3201 else {
3202 switch (_DB_get_type(self->mydb)) {
3203 case -1:
3204 retval = NULL;
3205 break;
3206 case DB_BTREE:
3207 case DB_HASH:
3208 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003209 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 data.data, data.size);
3211 break;
3212 case DB_RECNO:
3213 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003214 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003215 data.data, data.size);
3216 break;
3217 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003218 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003219 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003220 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3221 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003222 return retval;
3223}
3224
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003225#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003226static PyObject*
3227DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3228{
3229 int err, flags=0;
3230 PyObject* keyobj = NULL;
3231 PyObject* dataobj = NULL;
3232 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003233 Py_buffer* data_buf_view = NULL;
3234 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003235 int dlen = -1;
3236 int doff = -1;
3237 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003238 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3239 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003240
3241 CLEAR_DBT(key);
3242 CLEAR_DBT(data);
3243 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3244 &flags, &dlen, &doff))
3245 {
3246 PyErr_Clear();
3247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003248 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003249 &keyobj, &flags, &dlen, &doff))
3250 {
3251 PyErr_Clear();
3252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3253 kwnames, &keyobj, &dataobj,
3254 &flags, &dlen, &doff))
3255 {
3256 return NULL;
3257 }
3258 }
3259 }
3260
3261 CHECK_CURSOR_NOT_CLOSED(self);
3262
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003263 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003264 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003265 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003266 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003267 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3268 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003269 return NULL;
3270 }
3271
3272 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3273 data.flags = DB_DBT_MALLOC;
3274 if (!(key.flags & DB_DBT_REALLOC)) {
3275 key.flags |= DB_DBT_MALLOC;
3276 }
3277 }
3278
3279 CLEAR_DBT(pkey);
3280 pkey.flags = DB_DBT_MALLOC;
3281
3282 MYDB_BEGIN_ALLOW_THREADS;
3283 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3284 MYDB_END_ALLOW_THREADS;
3285
Gregory P. Smithe9477062005-06-04 06:46:59 +00003286 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3287 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003288 Py_INCREF(Py_None);
3289 retval = Py_None;
3290 }
3291 else if (makeDBError(err)) {
3292 retval = NULL;
3293 }
3294 else {
3295 PyObject *pkeyObj;
3296 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00003297 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003298
3299 if (self->mydb->primaryDBType == DB_RECNO ||
3300 self->mydb->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003301 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003303 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003304
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003305 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003306 {
3307 PyObject *keyObj;
3308 int type = _DB_get_type(self->mydb);
3309 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003310 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003312 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003313 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003314 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315 }
3316 else /* return just the pkey and data */
3317 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003318 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003319 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003320 Py_DECREF(dataObj);
3321 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003322 free_dbt(&pkey);
3323 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003324 }
3325 /* the only time REALLOC should be set is if we used an integer
3326 * key that make_key_dbt malloc'd for us. always free these. */
3327 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003328 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003329 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003330 free_buf_view(keyobj, key_buf_view);
3331 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003332 return retval;
3333}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003334#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003335
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003336
3337static PyObject*
3338DBC_get_recno(DBCursorObject* self, PyObject* args)
3339{
3340 int err;
3341 db_recno_t recno;
3342 DBT key;
3343 DBT data;
3344
3345 if (!PyArg_ParseTuple(args, ":get_recno"))
3346 return NULL;
3347
3348 CHECK_CURSOR_NOT_CLOSED(self);
3349
3350 CLEAR_DBT(key);
3351 CLEAR_DBT(data);
3352 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3353 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3354 data.flags = DB_DBT_MALLOC;
3355 key.flags = DB_DBT_MALLOC;
3356 }
3357
3358 MYDB_BEGIN_ALLOW_THREADS;
3359 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3360 MYDB_END_ALLOW_THREADS;
3361 RETURN_IF_ERR();
3362
3363 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003364 free_dbt(&key);
3365 free_dbt(&data);
Christian Heimes217cfd12007-12-02 14:31:20 +00003366 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003367}
3368
3369
3370static PyObject*
3371DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3372{
3373 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3374}
3375
3376
3377static PyObject*
3378DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3379{
3380 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3381}
3382
3383
3384static PyObject*
3385DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3386{
3387 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3388}
3389
3390
3391static PyObject*
3392DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3393{
3394 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003395 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003396 Py_buffer *data_buf_view = NULL;
3397 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003398 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003399 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003400 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003401 int dlen = -1;
3402 int doff = -1;
3403
3404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3405 &keyobj, &dataobj, &flags, &dlen, &doff))
3406 return NULL;
3407
3408 CHECK_CURSOR_NOT_CLOSED(self);
3409
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003410 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003412 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003413 !add_partial_dbt(&data, dlen, doff) )
3414 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003415 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3416 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419
3420 MYDB_BEGIN_ALLOW_THREADS;
3421 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3422 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003423 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3424 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003425 RETURN_IF_ERR();
3426 self->mydb->haveStat = 0;
3427 RETURN_NONE();
3428}
3429
3430
3431static PyObject*
3432DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3433{
3434 int err, flags = 0;
3435 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003436 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003437 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003438 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003439 int dlen = -1;
3440 int doff = -1;
3441
3442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3443 &keyobj, &flags, &dlen, &doff))
3444 return NULL;
3445
3446 CHECK_CURSOR_NOT_CLOSED(self);
3447
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003448 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 return NULL;
3450
3451 CLEAR_DBT(data);
3452 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3453 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3454 data.flags = DB_DBT_MALLOC;
3455 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003456 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003457 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003458 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003459 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461 MYDB_BEGIN_ALLOW_THREADS;
3462 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3463 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003464 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3465 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003466 Py_INCREF(Py_None);
3467 retval = Py_None;
3468 }
3469 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470 retval = NULL;
3471 }
3472 else {
3473 switch (_DB_get_type(self->mydb)) {
3474 case -1:
3475 retval = NULL;
3476 break;
3477 case DB_BTREE:
3478 case DB_HASH:
3479 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003480 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 data.data, data.size);
3482 break;
3483 case DB_RECNO:
3484 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003485 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003486 data.data, data.size);
3487 break;
3488 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003489 free_dbt(&data);
3490 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003491 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003492 /* the only time REALLOC should be set is if we used an integer
3493 * key that make_key_dbt malloc'd for us. always free these. */
3494 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003495 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003496 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003497 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498
3499 return retval;
3500}
3501
3502
3503static PyObject*
3504DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3505{
3506 int err, flags = 0;
3507 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003508 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003509 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003510 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003511 int dlen = -1;
3512 int doff = -1;
3513
3514 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3515 &keyobj, &flags, &dlen, &doff))
3516 return NULL;
3517
3518 CHECK_CURSOR_NOT_CLOSED(self);
3519
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003520 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003521 return NULL;
3522
3523 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003524 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003525 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003526 return NULL;
3527 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003528 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3529 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003530 data.flags |= DB_DBT_MALLOC;
3531 /* only BTREE databases will return anything in the key */
3532 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3533 key.flags |= DB_DBT_MALLOC;
3534 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 MYDB_BEGIN_ALLOW_THREADS;
3537 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3538 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003539 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3540 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003541 Py_INCREF(Py_None);
3542 retval = Py_None;
3543 }
3544 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545 retval = NULL;
3546 }
3547 else {
3548 switch (_DB_get_type(self->mydb)) {
3549 case -1:
3550 retval = NULL;
3551 break;
3552 case DB_BTREE:
3553 case DB_HASH:
3554 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003555 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556 data.data, data.size);
3557 break;
3558 case DB_RECNO:
3559 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003560 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003561 data.data, data.size);
3562 break;
3563 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003564 free_dbt(&key);
3565 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003567 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003568 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003569 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003570 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003571 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003572 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573
3574 return retval;
3575}
3576
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003578_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3579 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003581 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003583 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003584 Py_buffer *data_buf_view = NULL;
3585 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586
Gregory P. Smith7441e652003-11-03 21:35:31 +00003587 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003588 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003590 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3591 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594
3595 MYDB_BEGIN_ALLOW_THREADS;
3596 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3597 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003598 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003599 Py_INCREF(Py_None);
3600 retval = Py_None;
3601 }
3602 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003603 retval = NULL;
3604 }
3605 else {
3606 switch (_DB_get_type(self->mydb)) {
3607 case -1:
3608 retval = NULL;
3609 break;
3610 case DB_BTREE:
3611 case DB_HASH:
3612 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003613 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003614 data.data, data.size);
3615 break;
3616 case DB_RECNO:
3617 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003618 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619 data.data, data.size);
3620 break;
3621 }
3622 }
3623
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003624 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3625 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003626 return retval;
3627}
3628
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003629static PyObject*
3630DBC_get_both(DBCursorObject* self, PyObject* args)
3631{
3632 int flags=0;
3633 PyObject *keyobj, *dataobj;
3634
3635 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3636 return NULL;
3637
Gregory P. Smith7441e652003-11-03 21:35:31 +00003638 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003639 CHECK_CURSOR_NOT_CLOSED(self);
3640
3641 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3642 self->mydb->moduleFlags.getReturnsNone);
3643}
3644
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003645/* Return size of entry */
3646static PyObject*
3647DBC_get_current_size(DBCursorObject* self, PyObject* args)
3648{
3649 int err, flags=DB_CURRENT;
3650 PyObject* retval = NULL;
3651 DBT key, data;
3652
3653 if (!PyArg_ParseTuple(args, ":get_current_size"))
3654 return NULL;
3655 CHECK_CURSOR_NOT_CLOSED(self);
3656 CLEAR_DBT(key);
3657 CLEAR_DBT(data);
3658
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003659 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003660 getting the record size. */
3661 data.flags = DB_DBT_USERMEM;
3662 data.ulen = 0;
3663 MYDB_BEGIN_ALLOW_THREADS;
3664 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3665 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003666 if (err == DB_BUFFER_SMALL || !err) {
3667 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Christian Heimes217cfd12007-12-02 14:31:20 +00003668 retval = PyLong_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003669 err = 0;
3670 }
3671
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003672 free_dbt(&key);
3673 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003674 RETURN_IF_ERR();
3675 return retval;
3676}
3677
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003678static PyObject*
3679DBC_set_both(DBCursorObject* self, PyObject* args)
3680{
3681 int flags=0;
3682 PyObject *keyobj, *dataobj;
3683
3684 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3685 return NULL;
3686
Gregory P. Smith7441e652003-11-03 21:35:31 +00003687 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 CHECK_CURSOR_NOT_CLOSED(self);
3689
3690 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3691 self->mydb->moduleFlags.cursorSetReturnsNone);
3692}
3693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694
3695static PyObject*
3696DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3697{
3698 int err, irecno, flags=0;
3699 db_recno_t recno;
3700 DBT key, data;
3701 PyObject* retval;
3702 int dlen = -1;
3703 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003704 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003705
3706 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3707 &irecno, &flags, &dlen, &doff))
3708 return NULL;
3709
3710 CHECK_CURSOR_NOT_CLOSED(self);
3711
3712 CLEAR_DBT(key);
3713 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003714 /* use allocated space so DB will be able to realloc room for the real
3715 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 key.data = malloc(sizeof(db_recno_t));
3717 if (key.data == NULL) {
3718 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3719 return NULL;
3720 }
3721 key.size = sizeof(db_recno_t);
3722 key.ulen = key.size;
3723 memcpy(key.data, &recno, sizeof(db_recno_t));
3724 key.flags = DB_DBT_REALLOC;
3725
3726 CLEAR_DBT(data);
3727 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3728 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3729 data.flags = DB_DBT_MALLOC;
3730 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003731 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003732 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003733 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003734 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003735
3736 MYDB_BEGIN_ALLOW_THREADS;
3737 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3738 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003739 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3740 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003741 Py_INCREF(Py_None);
3742 retval = Py_None;
3743 }
3744 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745 retval = NULL;
3746 }
3747 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003748 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003750 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003751 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003752 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003753
3754 return retval;
3755}
3756
3757
3758static PyObject*
3759DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3760{
3761 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3762}
3763
3764
3765static PyObject*
3766DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3767{
3768 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3769}
3770
3771
3772static PyObject*
3773DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3774{
3775 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3776}
3777
3778
3779static PyObject*
3780DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3781{
3782 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3783}
3784
3785
3786static PyObject*
3787DBC_join_item(DBCursorObject* self, PyObject* args)
3788{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003789 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790 DBT key, data;
3791 PyObject* retval;
3792
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794 return NULL;
3795
3796 CHECK_CURSOR_NOT_CLOSED(self);
3797
3798 CLEAR_DBT(key);
3799 CLEAR_DBT(data);
3800 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3801 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3802 key.flags = DB_DBT_MALLOC;
3803 }
3804
3805 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003806 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003807 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003808 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3809 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003810 Py_INCREF(Py_None);
3811 retval = Py_None;
3812 }
3813 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003814 retval = NULL;
3815 }
3816 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003817 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003818 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003819 }
3820
3821 return retval;
3822}
3823
3824
3825
3826/* --------------------------------------------------------------------- */
3827/* DBEnv methods */
3828
3829
3830static PyObject*
3831DBEnv_close(DBEnvObject* self, PyObject* args)
3832{
3833 int err, flags = 0;
3834
3835 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3836 return NULL;
3837 if (!self->closed) { /* Don't close more than once */
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->close(self->db_env, flags);
3840 MYDB_END_ALLOW_THREADS;
3841 /* after calling DBEnv->close, regardless of error, this DBEnv
3842 * may not be accessed again (BerkeleyDB docs). */
3843 self->closed = 1;
3844 self->db_env = NULL;
3845 RETURN_IF_ERR();
3846 }
3847 RETURN_NONE();
3848}
3849
3850
3851static PyObject*
3852DBEnv_open(DBEnvObject* self, PyObject* args)
3853{
3854 int err, flags=0, mode=0660;
3855 char *db_home;
3856
3857 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3858 return NULL;
3859
3860 CHECK_ENV_NOT_CLOSED(self);
3861
3862 MYDB_BEGIN_ALLOW_THREADS;
3863 err = self->db_env->open(self->db_env, db_home, flags, mode);
3864 MYDB_END_ALLOW_THREADS;
3865 RETURN_IF_ERR();
3866 self->closed = 0;
3867 self->flags = flags;
3868 RETURN_NONE();
3869}
3870
3871
3872static PyObject*
3873DBEnv_remove(DBEnvObject* self, PyObject* args)
3874{
3875 int err, flags=0;
3876 char *db_home;
3877
3878 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3879 return NULL;
3880 CHECK_ENV_NOT_CLOSED(self);
3881 MYDB_BEGIN_ALLOW_THREADS;
3882 err = self->db_env->remove(self->db_env, db_home, flags);
3883 MYDB_END_ALLOW_THREADS;
3884 RETURN_IF_ERR();
3885 RETURN_NONE();
3886}
3887
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003888#if (DBVER >= 41)
3889static PyObject*
3890DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3891{
3892 int err;
3893 u_int32_t flags=0;
3894 char *file = NULL;
3895 char *database = NULL;
3896 PyObject *txnobj = NULL;
3897 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003898 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003899 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003900
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003902 &file, &database, &txnobj, &flags)) {
3903 return NULL;
3904 }
3905 if (!checkTxnObj(txnobj, &txn)) {
3906 return NULL;
3907 }
3908 CHECK_ENV_NOT_CLOSED(self);
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3914}
3915
3916static PyObject*
3917DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3918{
3919 int err;
3920 u_int32_t flags=0;
3921 char *file = NULL;
3922 char *database = NULL;
3923 char *newname = NULL;
3924 PyObject *txnobj = NULL;
3925 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003926 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003927 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003928
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003930 &file, &database, &newname, &txnobj, &flags)) {
3931 return NULL;
3932 }
3933 if (!checkTxnObj(txnobj, &txn)) {
3934 return NULL;
3935 }
3936 CHECK_ENV_NOT_CLOSED(self);
3937 MYDB_BEGIN_ALLOW_THREADS;
3938 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3939 flags);
3940 MYDB_END_ALLOW_THREADS;
3941 RETURN_IF_ERR();
3942 RETURN_NONE();
3943}
3944
3945static PyObject*
3946DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3947{
3948 int err;
3949 u_int32_t flags=0;
3950 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003951 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003952
3953 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3954 &passwd, &flags)) {
3955 return NULL;
3956 }
3957
3958 MYDB_BEGIN_ALLOW_THREADS;
3959 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3960 MYDB_END_ALLOW_THREADS;
3961
3962 RETURN_IF_ERR();
3963 RETURN_NONE();
3964}
3965#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003966
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003967#if (DBVER >= 40)
3968static PyObject*
3969DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3970{
3971 int err;
3972 u_int32_t flags=0;
3973 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003974 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003975
3976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3977 &timeout, &flags)) {
3978 return NULL;
3979 }
3980
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3983 MYDB_END_ALLOW_THREADS;
3984
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988#endif /* DBVER >= 40 */
3989
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003990static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003991DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3992{
3993 int err;
3994 long shm_key = 0;
3995
3996 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
3999
4000 err = self->db_env->set_shm_key(self->db_env, shm_key);
4001 RETURN_IF_ERR();
4002 RETURN_NONE();
4003}
4004
4005static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004006DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4007{
4008 int err, gbytes=0, bytes=0, ncache=0;
4009
4010 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4011 &gbytes, &bytes, &ncache))
4012 return NULL;
4013 CHECK_ENV_NOT_CLOSED(self);
4014
4015 MYDB_BEGIN_ALLOW_THREADS;
4016 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4017 MYDB_END_ALLOW_THREADS;
4018 RETURN_IF_ERR();
4019 RETURN_NONE();
4020}
4021
4022
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004023static PyObject*
4024DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4025{
4026 int err, flags=0, onoff=0;
4027
4028 if (!PyArg_ParseTuple(args, "ii:set_flags",
4029 &flags, &onoff))
4030 return NULL;
4031 CHECK_ENV_NOT_CLOSED(self);
4032
4033 MYDB_BEGIN_ALLOW_THREADS;
4034 err = self->db_env->set_flags(self->db_env, flags, onoff);
4035 MYDB_END_ALLOW_THREADS;
4036 RETURN_IF_ERR();
4037 RETURN_NONE();
4038}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004039
4040
4041static PyObject*
4042DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4043{
4044 int err;
4045 char *dir;
4046
4047 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4048 return NULL;
4049 CHECK_ENV_NOT_CLOSED(self);
4050
4051 MYDB_BEGIN_ALLOW_THREADS;
4052 err = self->db_env->set_data_dir(self->db_env, dir);
4053 MYDB_END_ALLOW_THREADS;
4054 RETURN_IF_ERR();
4055 RETURN_NONE();
4056}
4057
4058
4059static PyObject*
4060DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4061{
4062 int err, lg_bsize;
4063
4064 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4065 return NULL;
4066 CHECK_ENV_NOT_CLOSED(self);
4067
4068 MYDB_BEGIN_ALLOW_THREADS;
4069 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4070 MYDB_END_ALLOW_THREADS;
4071 RETURN_IF_ERR();
4072 RETURN_NONE();
4073}
4074
4075
4076static PyObject*
4077DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4078{
4079 int err;
4080 char *dir;
4081
4082 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4083 return NULL;
4084 CHECK_ENV_NOT_CLOSED(self);
4085
4086 MYDB_BEGIN_ALLOW_THREADS;
4087 err = self->db_env->set_lg_dir(self->db_env, dir);
4088 MYDB_END_ALLOW_THREADS;
4089 RETURN_IF_ERR();
4090 RETURN_NONE();
4091}
4092
4093static PyObject*
4094DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4095{
4096 int err, lg_max;
4097
4098 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4101
4102 MYDB_BEGIN_ALLOW_THREADS;
4103 err = self->db_env->set_lg_max(self->db_env, lg_max);
4104 MYDB_END_ALLOW_THREADS;
4105 RETURN_IF_ERR();
4106 RETURN_NONE();
4107}
4108
4109
Neal Norwitz84562352005-10-20 04:30:15 +00004110#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004111static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004112DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4113{
4114 int err, lg_max;
4115
4116 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4117 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4119
4120 MYDB_BEGIN_ALLOW_THREADS;
4121 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4122 MYDB_END_ALLOW_THREADS;
4123 RETURN_IF_ERR();
4124 RETURN_NONE();
4125}
Neal Norwitz84562352005-10-20 04:30:15 +00004126#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004127
4128
4129static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004130DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4131{
4132 int err, lk_detect;
4133
4134 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4135 return NULL;
4136 CHECK_ENV_NOT_CLOSED(self);
4137
4138 MYDB_BEGIN_ALLOW_THREADS;
4139 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4140 MYDB_END_ALLOW_THREADS;
4141 RETURN_IF_ERR();
4142 RETURN_NONE();
4143}
4144
4145
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004146#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004147static PyObject*
4148DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4149{
4150 int err, max;
4151
4152 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4153 return NULL;
4154 CHECK_ENV_NOT_CLOSED(self);
4155
4156 MYDB_BEGIN_ALLOW_THREADS;
4157 err = self->db_env->set_lk_max(self->db_env, max);
4158 MYDB_END_ALLOW_THREADS;
4159 RETURN_IF_ERR();
4160 RETURN_NONE();
4161}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004162#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004163
4164
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004165
4166static PyObject*
4167DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4168{
4169 int err, max;
4170
4171 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4172 return NULL;
4173 CHECK_ENV_NOT_CLOSED(self);
4174
4175 MYDB_BEGIN_ALLOW_THREADS;
4176 err = self->db_env->set_lk_max_locks(self->db_env, max);
4177 MYDB_END_ALLOW_THREADS;
4178 RETURN_IF_ERR();
4179 RETURN_NONE();
4180}
4181
4182
4183static PyObject*
4184DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4185{
4186 int err, max;
4187
4188 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4189 return NULL;
4190 CHECK_ENV_NOT_CLOSED(self);
4191
4192 MYDB_BEGIN_ALLOW_THREADS;
4193 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4194 MYDB_END_ALLOW_THREADS;
4195 RETURN_IF_ERR();
4196 RETURN_NONE();
4197}
4198
4199
4200static PyObject*
4201DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4202{
4203 int err, max;
4204
4205 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4206 return NULL;
4207 CHECK_ENV_NOT_CLOSED(self);
4208
4209 MYDB_BEGIN_ALLOW_THREADS;
4210 err = self->db_env->set_lk_max_objects(self->db_env, max);
4211 MYDB_END_ALLOW_THREADS;
4212 RETURN_IF_ERR();
4213 RETURN_NONE();
4214}
4215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004216
4217static PyObject*
4218DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4219{
4220 int err, mp_mmapsize;
4221
4222 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4223 return NULL;
4224 CHECK_ENV_NOT_CLOSED(self);
4225
4226 MYDB_BEGIN_ALLOW_THREADS;
4227 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4228 MYDB_END_ALLOW_THREADS;
4229 RETURN_IF_ERR();
4230 RETURN_NONE();
4231}
4232
4233
4234static PyObject*
4235DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4236{
4237 int err;
4238 char *dir;
4239
4240 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4241 return NULL;
4242 CHECK_ENV_NOT_CLOSED(self);
4243
4244 MYDB_BEGIN_ALLOW_THREADS;
4245 err = self->db_env->set_tmp_dir(self->db_env, dir);
4246 MYDB_END_ALLOW_THREADS;
4247 RETURN_IF_ERR();
4248 RETURN_NONE();
4249}
4250
4251
4252static PyObject*
4253DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4254{
4255 int flags = 0;
4256 PyObject* txnobj = NULL;
4257 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004258 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004259
4260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4261 &txnobj, &flags))
4262 return NULL;
4263
4264 if (!checkTxnObj(txnobj, &txn))
4265 return NULL;
4266 CHECK_ENV_NOT_CLOSED(self);
4267
4268 return (PyObject*)newDBTxnObject(self, txn, flags);
4269}
4270
4271
4272static PyObject*
4273DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4274{
4275 int err, kbyte=0, min=0, flags=0;
4276
4277 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4278 return NULL;
4279 CHECK_ENV_NOT_CLOSED(self);
4280
4281 MYDB_BEGIN_ALLOW_THREADS;
4282#if (DBVER >= 40)
4283 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4284#else
4285 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4286#endif
4287 MYDB_END_ALLOW_THREADS;
4288 RETURN_IF_ERR();
4289 RETURN_NONE();
4290}
4291
4292
4293static PyObject*
4294DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4295{
4296 int err, max;
4297
4298 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4299 return NULL;
4300 CHECK_ENV_NOT_CLOSED(self);
4301
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004302 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004303 RETURN_IF_ERR();
4304 RETURN_NONE();
4305}
4306
4307
4308static PyObject*
4309DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4310{
4311 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004312 long stamp;
4313 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004314
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004315 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004316 return NULL;
4317 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004318 timestamp = (time_t)stamp;
4319 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004320 RETURN_IF_ERR();
4321 RETURN_NONE();
4322}
4323
4324
4325static PyObject*
4326DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4327{
4328 int err, atype, flags=0;
4329 int aborted = 0;
4330
4331 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4332 return NULL;
4333 CHECK_ENV_NOT_CLOSED(self);
4334
4335 MYDB_BEGIN_ALLOW_THREADS;
4336#if (DBVER >= 40)
4337 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4338#else
4339 err = lock_detect(self->db_env, flags, atype, &aborted);
4340#endif
4341 MYDB_END_ALLOW_THREADS;
4342 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00004343 return PyLong_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004344}
4345
4346
4347static PyObject*
4348DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4349{
4350 int flags=0;
4351 int locker, lock_mode;
4352 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004353 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004354 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004355
4356 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4357 return NULL;
4358
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004359 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004360 return NULL;
4361
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004362 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4363 free_buf_view(objobj, obj_buf_view);
4364 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004365}
4366
4367
4368static PyObject*
4369DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4370{
4371 int err;
4372 u_int32_t theID;
4373
4374 if (!PyArg_ParseTuple(args, ":lock_id"))
4375 return NULL;
4376
4377 CHECK_ENV_NOT_CLOSED(self);
4378 MYDB_BEGIN_ALLOW_THREADS;
4379#if (DBVER >= 40)
4380 err = self->db_env->lock_id(self->db_env, &theID);
4381#else
4382 err = lock_id(self->db_env, &theID);
4383#endif
4384 MYDB_END_ALLOW_THREADS;
4385 RETURN_IF_ERR();
4386
Christian Heimes217cfd12007-12-02 14:31:20 +00004387 return PyLong_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004388}
4389
Guido van Rossum77677112007-11-05 19:43:04 +00004390#if (DBVER >= 40)
4391static PyObject*
4392DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4393{
4394 int err;
4395 u_int32_t theID;
4396
4397 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4398 return NULL;
4399
4400 CHECK_ENV_NOT_CLOSED(self);
4401 MYDB_BEGIN_ALLOW_THREADS;
4402 err = self->db_env->lock_id_free(self->db_env, theID);
4403 MYDB_END_ALLOW_THREADS;
4404 RETURN_IF_ERR();
4405 RETURN_NONE();
4406}
4407#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004408
4409static PyObject*
4410DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4411{
4412 int err;
4413 DBLockObject* dblockobj;
4414
4415 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4416 return NULL;
4417
4418 CHECK_ENV_NOT_CLOSED(self);
4419 MYDB_BEGIN_ALLOW_THREADS;
4420#if (DBVER >= 40)
4421 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4422#else
4423 err = lock_put(self->db_env, &dblockobj->lock);
4424#endif
4425 MYDB_END_ALLOW_THREADS;
4426 RETURN_IF_ERR();
4427 RETURN_NONE();
4428}
4429
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004430#if (DBVER >= 44)
4431static PyObject*
4432DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4433{
4434 int err;
4435 char *file;
4436 u_int32_t flags = 0;
4437 static char* kwnames[] = { "file", "flags", NULL};
4438
4439 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4440 &file, &flags))
4441 return NULL;
4442 CHECK_ENV_NOT_CLOSED(self);
4443
4444 MYDB_BEGIN_ALLOW_THREADS;
4445 err = self->db_env->lsn_reset(self->db_env, file, flags);
4446 MYDB_END_ALLOW_THREADS;
4447 RETURN_IF_ERR();
4448 RETURN_NONE();
4449}
4450#endif /* DBVER >= 4.4 */
4451
4452#if (DBVER >= 40)
4453static PyObject*
4454DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4455{
4456 int err;
4457 DB_LOG_STAT* statp = NULL;
4458 PyObject* d = NULL;
4459 u_int32_t flags = 0;
4460
4461 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4462 return NULL;
4463 CHECK_ENV_NOT_CLOSED(self);
4464
4465 MYDB_BEGIN_ALLOW_THREADS;
4466 err = self->db_env->log_stat(self->db_env, &statp, flags);
4467 MYDB_END_ALLOW_THREADS;
4468 RETURN_IF_ERR();
4469
4470 /* Turn the stat structure into a dictionary */
4471 d = PyDict_New();
4472 if (d == NULL) {
4473 if (statp)
4474 free(statp);
4475 return NULL;
4476 }
4477
4478#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4479
4480 MAKE_ENTRY(magic);
4481 MAKE_ENTRY(version);
4482 MAKE_ENTRY(mode);
4483 MAKE_ENTRY(lg_bsize);
4484#if (DBVER >= 44)
4485 MAKE_ENTRY(lg_size);
4486 MAKE_ENTRY(record);
4487#endif
4488#if (DBVER <= 40)
4489 MAKE_ENTRY(lg_max);
4490#endif
4491 MAKE_ENTRY(w_mbytes);
4492 MAKE_ENTRY(w_bytes);
4493 MAKE_ENTRY(wc_mbytes);
4494 MAKE_ENTRY(wc_bytes);
4495 MAKE_ENTRY(wcount);
4496 MAKE_ENTRY(wcount_fill);
4497#if (DBVER >= 44)
4498 MAKE_ENTRY(rcount);
4499#endif
4500 MAKE_ENTRY(scount);
4501 MAKE_ENTRY(cur_file);
4502 MAKE_ENTRY(cur_offset);
4503 MAKE_ENTRY(disk_file);
4504 MAKE_ENTRY(disk_offset);
4505 MAKE_ENTRY(maxcommitperflush);
4506 MAKE_ENTRY(mincommitperflush);
4507 MAKE_ENTRY(regsize);
4508 MAKE_ENTRY(region_wait);
4509 MAKE_ENTRY(region_nowait);
4510
4511#undef MAKE_ENTRY
4512 free(statp);
4513 return d;
4514} /* DBEnv_log_stat */
4515#endif /* DBVER >= 4.0 for log_stat method */
4516
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004517
4518static PyObject*
4519DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4520{
4521 int err;
4522 DB_LOCK_STAT* sp;
4523 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004524 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004525
4526 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4527 return NULL;
4528 CHECK_ENV_NOT_CLOSED(self);
4529
4530 MYDB_BEGIN_ALLOW_THREADS;
4531#if (DBVER >= 40)
4532 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4533#else
4534#if (DBVER >= 33)
4535 err = lock_stat(self->db_env, &sp);
4536#else
4537 err = lock_stat(self->db_env, &sp, NULL);
4538#endif
4539#endif
4540 MYDB_END_ALLOW_THREADS;
4541 RETURN_IF_ERR();
4542
4543 /* Turn the stat structure into a dictionary */
4544 d = PyDict_New();
4545 if (d == NULL) {
4546 free(sp);
4547 return NULL;
4548 }
4549
4550#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4551
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004552#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004553 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004554#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004555 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004556 MAKE_ENTRY(maxlocks);
4557 MAKE_ENTRY(maxlockers);
4558 MAKE_ENTRY(maxobjects);
4559 MAKE_ENTRY(nlocks);
4560 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561 MAKE_ENTRY(nlockers);
4562 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 MAKE_ENTRY(nobjects);
4564 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004565 MAKE_ENTRY(nrequests);
4566 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004567#if (DBVER < 44)
4568 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004569 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004570#else
4571 MAKE_ENTRY(lock_nowait);
4572 MAKE_ENTRY(lock_wait);
4573#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004574 MAKE_ENTRY(ndeadlocks);
4575 MAKE_ENTRY(regsize);
4576 MAKE_ENTRY(region_wait);
4577 MAKE_ENTRY(region_nowait);
4578
4579#undef MAKE_ENTRY
4580 free(sp);
4581 return d;
4582}
4583
4584
4585static PyObject*
4586DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4587{
4588 int flags=0;
4589 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004590 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004591 PyObject* list;
4592 PyObject* item = NULL;
4593
4594 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4595 return NULL;
4596
4597 CHECK_ENV_NOT_CLOSED(self);
4598 MYDB_BEGIN_ALLOW_THREADS;
4599#if (DBVER >= 40)
4600 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4601#elif (DBVER == 33)
4602 err = log_archive(self->db_env, &log_list, flags);
4603#else
4604 err = log_archive(self->db_env, &log_list, flags, NULL);
4605#endif
4606 MYDB_END_ALLOW_THREADS;
4607 RETURN_IF_ERR();
4608
4609 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004610 if (list == NULL) {
4611 if (log_list)
4612 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004614 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615
4616 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004617 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004618 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004619 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004620 if (item == NULL) {
4621 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004622 list = NULL;
4623 break;
4624 }
4625 PyList_Append(list, item);
4626 Py_DECREF(item);
4627 }
4628 free(log_list_start);
4629 }
4630 return list;
4631}
4632
4633
4634static PyObject*
4635DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4636{
4637 int err;
4638 DB_TXN_STAT* sp;
4639 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004640 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004641
4642 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4643 return NULL;
4644 CHECK_ENV_NOT_CLOSED(self);
4645
4646 MYDB_BEGIN_ALLOW_THREADS;
4647#if (DBVER >= 40)
4648 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4649#elif (DBVER == 33)
4650 err = txn_stat(self->db_env, &sp);
4651#else
4652 err = txn_stat(self->db_env, &sp, NULL);
4653#endif
4654 MYDB_END_ALLOW_THREADS;
4655 RETURN_IF_ERR();
4656
4657 /* Turn the stat structure into a dictionary */
4658 d = PyDict_New();
4659 if (d == NULL) {
4660 free(sp);
4661 return NULL;
4662 }
4663
4664#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004665#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004666
Guido van Rossumd8faa362007-04-27 19:54:29 +00004667 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004668 MAKE_ENTRY(last_txnid);
4669 MAKE_ENTRY(maxtxns);
4670 MAKE_ENTRY(nactive);
4671 MAKE_ENTRY(maxnactive);
4672 MAKE_ENTRY(nbegins);
4673 MAKE_ENTRY(naborts);
4674 MAKE_ENTRY(ncommits);
4675 MAKE_ENTRY(regsize);
4676 MAKE_ENTRY(region_wait);
4677 MAKE_ENTRY(region_nowait);
4678
4679#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004680#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004681 free(sp);
4682 return d;
4683}
4684
4685
4686static PyObject*
4687DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4688{
4689 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004690 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691
4692 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4693 return NULL;
4694 CHECK_ENV_NOT_CLOSED(self);
4695
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004696 if (self->moduleFlags.getReturnsNone)
4697 ++oldValue;
4698 if (self->moduleFlags.cursorSetReturnsNone)
4699 ++oldValue;
4700 self->moduleFlags.getReturnsNone = (flags >= 1);
4701 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00004702 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004703}
4704
4705
4706/* --------------------------------------------------------------------- */
4707/* DBTxn methods */
4708
4709
4710static PyObject*
4711DBTxn_commit(DBTxnObject* self, PyObject* args)
4712{
4713 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004714 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004715
4716 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4717 return NULL;
4718
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004719 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004720 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4721 "after txn_commit or txn_abort");
4722 PyErr_SetObject(DBError, t);
4723 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004724 return NULL;
4725 }
4726 txn = self->txn;
4727 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004728 MYDB_BEGIN_ALLOW_THREADS;
4729#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004730 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004731#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004732 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004733#endif
4734 MYDB_END_ALLOW_THREADS;
4735 RETURN_IF_ERR();
4736 RETURN_NONE();
4737}
4738
4739static PyObject*
4740DBTxn_prepare(DBTxnObject* self, PyObject* args)
4741{
4742#if (DBVER >= 33)
4743 int err;
4744 char* gid=NULL;
4745 int gid_size=0;
4746
Gregory P. Smith361ed152007-08-23 07:32:27 +00004747 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004748 return NULL;
4749
4750 if (gid_size != DB_XIDDATASIZE) {
4751 PyErr_SetString(PyExc_TypeError,
4752 "gid must be DB_XIDDATASIZE bytes long");
4753 return NULL;
4754 }
4755
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004756 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004757 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4758 "after txn_commit or txn_abort");
4759 PyErr_SetObject(DBError, t);
4760 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004761 return NULL;
4762 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004763 MYDB_BEGIN_ALLOW_THREADS;
4764#if (DBVER >= 40)
4765 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4766#else
4767 err = txn_prepare(self->txn, (u_int8_t*)gid);
4768#endif
4769 MYDB_END_ALLOW_THREADS;
4770 RETURN_IF_ERR();
4771 RETURN_NONE();
4772#else
4773 int err;
4774
4775 if (!PyArg_ParseTuple(args, ":prepare"))
4776 return NULL;
4777
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004778 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004779 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4780 "after txn_commit or txn_abort");
4781 PyErr_SetObject(DBError, t);
4782 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004783 return NULL;
4784 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 MYDB_BEGIN_ALLOW_THREADS;
4786 err = txn_prepare(self->txn);
4787 MYDB_END_ALLOW_THREADS;
4788 RETURN_IF_ERR();
4789 RETURN_NONE();
4790#endif
4791}
4792
4793
4794static PyObject*
4795DBTxn_abort(DBTxnObject* self, PyObject* args)
4796{
4797 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004798 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004799
4800 if (!PyArg_ParseTuple(args, ":abort"))
4801 return NULL;
4802
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004803 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004804 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4805 "after txn_commit or txn_abort");
4806 PyErr_SetObject(DBError, t);
4807 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004808 return NULL;
4809 }
4810 txn = self->txn;
4811 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004812 MYDB_BEGIN_ALLOW_THREADS;
4813#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004814 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004815#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004816 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004817#endif
4818 MYDB_END_ALLOW_THREADS;
4819 RETURN_IF_ERR();
4820 RETURN_NONE();
4821}
4822
4823
4824static PyObject*
4825DBTxn_id(DBTxnObject* self, PyObject* args)
4826{
4827 int id;
4828
4829 if (!PyArg_ParseTuple(args, ":id"))
4830 return NULL;
4831
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004832 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004833 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4834 "after txn_commit or txn_abort");
4835 PyErr_SetObject(DBError, t);
4836 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004837 return NULL;
4838 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004839 MYDB_BEGIN_ALLOW_THREADS;
4840#if (DBVER >= 40)
4841 id = self->txn->id(self->txn);
4842#else
4843 id = txn_id(self->txn);
4844#endif
4845 MYDB_END_ALLOW_THREADS;
Christian Heimes217cfd12007-12-02 14:31:20 +00004846 return PyLong_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004847}
4848
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004849#if (DBVER >= 43)
4850/* --------------------------------------------------------------------- */
4851/* DBSequence methods */
4852
4853
4854static PyObject*
4855DBSequence_close(DBSequenceObject* self, PyObject* args)
4856{
4857 int err, flags=0;
4858 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4859 return NULL;
4860 CHECK_SEQUENCE_NOT_CLOSED(self)
4861
4862 MYDB_BEGIN_ALLOW_THREADS
4863 err = self->sequence->close(self->sequence, flags);
4864 self->sequence = NULL;
4865 MYDB_END_ALLOW_THREADS
4866
4867 RETURN_IF_ERR();
4868
4869 RETURN_NONE();
4870}
4871
4872static PyObject*
4873DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4874{
4875 int err, flags = 0;
4876 int delta = 1;
4877 db_seq_t value;
4878 PyObject *txnobj = NULL;
4879 DB_TXN *txn = NULL;
4880 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4882 return NULL;
4883 CHECK_SEQUENCE_NOT_CLOSED(self)
4884
4885 if (!checkTxnObj(txnobj, &txn))
4886 return NULL;
4887
4888 MYDB_BEGIN_ALLOW_THREADS
4889 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4890 MYDB_END_ALLOW_THREADS
4891
4892 RETURN_IF_ERR();
4893 return PyLong_FromLongLong(value);
4894
4895}
4896
4897static PyObject*
4898DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4899{
4900 if (!PyArg_ParseTuple(args,":get_dbp"))
4901 return NULL;
4902 CHECK_SEQUENCE_NOT_CLOSED(self)
4903 Py_INCREF(self->mydb);
4904 return (PyObject* )self->mydb;
4905}
4906
4907static PyObject*
4908DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4909{
4910 int err;
4911 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004912 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004913 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004914 CHECK_SEQUENCE_NOT_CLOSED(self)
4915 MYDB_BEGIN_ALLOW_THREADS
4916 err = self->sequence->get_key(self->sequence, &key);
4917 MYDB_END_ALLOW_THREADS
4918
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004919 if (!err)
Guido van Rossum98297ee2007-11-06 21:34:58 +00004920 retval = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004921
4922 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004923 RETURN_IF_ERR();
4924
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004925 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004926}
4927
4928static PyObject*
4929DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4930{
4931 int err;
4932 db_seq_t value;
4933 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4934 return NULL;
4935 CHECK_SEQUENCE_NOT_CLOSED(self)
4936
4937 MYDB_BEGIN_ALLOW_THREADS
4938 err = self->sequence->initial_value(self->sequence, value);
4939 MYDB_END_ALLOW_THREADS
4940
4941 RETURN_IF_ERR();
4942
4943 RETURN_NONE();
4944}
4945
4946static PyObject*
4947DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4948{
4949 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004950 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004951 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004952 PyObject *txnobj = NULL;
4953 DB_TXN *txn = NULL;
4954 DBT key;
4955
4956 static char* kwnames[] = {"key", "txn", "flags", NULL };
4957 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4958 return NULL;
4959
4960 if (!checkTxnObj(txnobj, &txn))
4961 return NULL;
4962
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004963 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004964 return NULL;
4965
4966 MYDB_BEGIN_ALLOW_THREADS
4967 err = self->sequence->open(self->sequence, txn, &key, flags);
4968 MYDB_END_ALLOW_THREADS
4969
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004970 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004971 RETURN_IF_ERR();
4972
4973 RETURN_NONE();
4974}
4975
4976static PyObject*
4977DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4978{
4979 int err, flags = 0;
4980 PyObject *txnobj = NULL;
4981 DB_TXN *txn = NULL;
4982
4983 static char* kwnames[] = {"txn", "flags", NULL };
4984 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4985 return NULL;
4986
4987 if (!checkTxnObj(txnobj, &txn))
4988 return NULL;
4989
4990 CHECK_SEQUENCE_NOT_CLOSED(self)
4991
4992 MYDB_BEGIN_ALLOW_THREADS
4993 err = self->sequence->remove(self->sequence, txn, flags);
4994 MYDB_END_ALLOW_THREADS
4995
4996 RETURN_IF_ERR();
4997 RETURN_NONE();
4998}
4999
5000static PyObject*
5001DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5002{
5003 int err, size;
5004 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5005 return NULL;
5006 CHECK_SEQUENCE_NOT_CLOSED(self)
5007
5008 MYDB_BEGIN_ALLOW_THREADS
5009 err = self->sequence->set_cachesize(self->sequence, size);
5010 MYDB_END_ALLOW_THREADS
5011
5012 RETURN_IF_ERR();
5013 RETURN_NONE();
5014}
5015
5016static PyObject*
5017DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5018{
5019 int err, size;
5020 if (!PyArg_ParseTuple(args,":get_cachesize"))
5021 return NULL;
5022 CHECK_SEQUENCE_NOT_CLOSED(self)
5023
5024 MYDB_BEGIN_ALLOW_THREADS
5025 err = self->sequence->get_cachesize(self->sequence, &size);
5026 MYDB_END_ALLOW_THREADS
5027
5028 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005029 return PyLong_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005030}
5031
5032static PyObject*
5033DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5034{
5035 int err, flags = 0;
5036 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5037 return NULL;
5038 CHECK_SEQUENCE_NOT_CLOSED(self)
5039
5040 MYDB_BEGIN_ALLOW_THREADS
5041 err = self->sequence->set_flags(self->sequence, flags);
5042 MYDB_END_ALLOW_THREADS
5043
5044 RETURN_IF_ERR();
5045 RETURN_NONE();
5046
5047}
5048
5049static PyObject*
5050DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5051{
5052 unsigned int flags;
5053 int err;
5054 if (!PyArg_ParseTuple(args,":get_flags"))
5055 return NULL;
5056 CHECK_SEQUENCE_NOT_CLOSED(self)
5057
5058 MYDB_BEGIN_ALLOW_THREADS
5059 err = self->sequence->get_flags(self->sequence, &flags);
5060 MYDB_END_ALLOW_THREADS
5061
5062 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005063 return PyLong_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005064}
5065
5066static PyObject*
5067DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5068{
5069 int err;
5070 db_seq_t min, max;
5071 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5072 return NULL;
5073 CHECK_SEQUENCE_NOT_CLOSED(self)
5074
5075 MYDB_BEGIN_ALLOW_THREADS
5076 err = self->sequence->set_range(self->sequence, min, max);
5077 MYDB_END_ALLOW_THREADS
5078
5079 RETURN_IF_ERR();
5080 RETURN_NONE();
5081}
5082
5083static PyObject*
5084DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5085{
5086 int err;
5087 db_seq_t min, max;
5088 if (!PyArg_ParseTuple(args,":get_range"))
5089 return NULL;
5090 CHECK_SEQUENCE_NOT_CLOSED(self)
5091
5092 MYDB_BEGIN_ALLOW_THREADS
5093 err = self->sequence->get_range(self->sequence, &min, &max);
5094 MYDB_END_ALLOW_THREADS
5095
5096 RETURN_IF_ERR();
5097 return Py_BuildValue("(LL)", min, max);
5098}
5099
5100static PyObject*
5101DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5102{
5103 int err, flags = 0;
5104 DB_SEQUENCE_STAT* sp = NULL;
5105 PyObject* dict_stat;
5106 static char* kwnames[] = {"flags", NULL };
5107 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5108 return NULL;
5109 CHECK_SEQUENCE_NOT_CLOSED(self);
5110
5111 MYDB_BEGIN_ALLOW_THREADS;
5112 err = self->sequence->stat(self->sequence, &sp, flags);
5113 MYDB_END_ALLOW_THREADS;
5114 RETURN_IF_ERR();
5115
5116 if ((dict_stat = PyDict_New()) == NULL) {
5117 free(sp);
5118 return NULL;
5119 }
5120
5121
5122#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5123#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5124
5125 MAKE_INT_ENTRY(wait);
5126 MAKE_INT_ENTRY(nowait);
5127 MAKE_LONG_LONG_ENTRY(current);
5128 MAKE_LONG_LONG_ENTRY(value);
5129 MAKE_LONG_LONG_ENTRY(last_value);
5130 MAKE_LONG_LONG_ENTRY(min);
5131 MAKE_LONG_LONG_ENTRY(max);
5132 MAKE_INT_ENTRY(cache_size);
5133 MAKE_INT_ENTRY(flags);
5134
5135#undef MAKE_INT_ENTRY
5136#undef MAKE_LONG_LONG_ENTRY
5137
5138 free(sp);
5139 return dict_stat;
5140}
5141#endif
5142
5143
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005144/* --------------------------------------------------------------------- */
5145/* Method definition tables and type objects */
5146
5147static PyMethodDef DB_methods[] = {
5148 {"append", (PyCFunction)DB_append, METH_VARARGS},
5149#if (DBVER >= 33)
5150 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5151#endif
5152 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005153 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5154 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005155 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5156 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5157 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5158 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005159#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005160 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005161#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005162 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5163 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5164 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5165 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5166 {"join", (PyCFunction)DB_join, METH_VARARGS},
5167 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5168 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5169 {"items", (PyCFunction)DB_items, METH_VARARGS},
5170 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5171 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5172 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5173 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5174 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5175 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005176#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005177 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005178#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005179 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005180#if (DBVER >= 41)
5181 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5182#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005183 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5184 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5185 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5186 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5187 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5188 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5189 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5190 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5191 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005192 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005193 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005194 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5195#if (DBVER >= 33)
5196 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5197#endif
5198 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5199 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5200 {"values", (PyCFunction)DB_values, METH_VARARGS},
5201 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5202 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5203 {NULL, NULL} /* sentinel */
5204};
5205
5206
5207static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005208 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005209 (binaryfunc)DB_subscript, /*mp_subscript*/
5210 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5211};
5212
5213
5214static PyMethodDef DBCursor_methods[] = {
5215 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5216 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5217 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5218 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5219 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5220 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5221 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005222#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005223 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005224#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005225 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5226 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5227 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5228 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5229 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5230 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5231 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5232 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005233 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005234 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005235 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5236 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5237 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5238 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5239 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5240 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5241 {NULL, NULL} /* sentinel */
5242};
5243
5244
5245static PyMethodDef DBEnv_methods[] = {
5246 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5247 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5248 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005249#if (DBVER >= 41)
5250 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5251 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5252 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5253#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005254#if (DBVER >= 40)
5255 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5256#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005257 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005258 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5259 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005261 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5262 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5263 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005264#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005265 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005266#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005267 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005268#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005269 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005270#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005271 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5272 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5273 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005274 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5275 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5276 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5277 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5278 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5279 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005280 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005281 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5282 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5283 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005284#if (DBVER >= 40)
5285 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005287 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5288 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5289 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005290#if (DBVER >= 40)
5291 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5292#endif
5293#if (DBVER >= 44)
5294 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5295#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005296 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5297 {NULL, NULL} /* sentinel */
5298};
5299
5300
5301static PyMethodDef DBTxn_methods[] = {
5302 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5303 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5304 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5305 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5306 {NULL, NULL} /* sentinel */
5307};
5308
5309
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005310#if (DBVER >= 43)
5311static PyMethodDef DBSequence_methods[] = {
5312 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5313 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5314 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5315 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5316 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5317 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5318 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5319 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5320 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5321 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5322 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5323 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5324 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5325 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5326 {NULL, NULL} /* sentinel */
5327};
5328#endif
5329
5330
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005331static PyObject*
5332DB_getattr(DBObject* self, char *name)
5333{
5334 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5335}
5336
5337
5338static PyObject*
5339DBEnv_getattr(DBEnvObject* self, char *name)
5340{
5341 if (!strcmp(name, "db_home")) {
5342 CHECK_ENV_NOT_CLOSED(self);
5343 if (self->db_env->db_home == NULL) {
5344 RETURN_NONE();
5345 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005346 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005347 }
5348
5349 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5350}
5351
5352
5353static PyObject*
5354DBCursor_getattr(DBCursorObject* self, char *name)
5355{
5356 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5357}
5358
5359static PyObject*
5360DBTxn_getattr(DBTxnObject* self, char *name)
5361{
5362 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5363}
5364
5365static PyObject*
5366DBLock_getattr(DBLockObject* self, char *name)
5367{
5368 return NULL;
5369}
5370
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005371#if (DBVER >= 43)
5372static PyObject*
5373DBSequence_getattr(DBSequenceObject* self, char *name)
5374{
5375 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5376}
5377#endif
5378
Neal Norwitz227b5332006-03-22 09:28:35 +00005379static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005380 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005381 "DB", /*tp_name*/
5382 sizeof(DBObject), /*tp_basicsize*/
5383 0, /*tp_itemsize*/
5384 /* methods */
5385 (destructor)DB_dealloc, /*tp_dealloc*/
5386 0, /*tp_print*/
5387 (getattrfunc)DB_getattr, /*tp_getattr*/
5388 0, /*tp_setattr*/
5389 0, /*tp_compare*/
5390 0, /*tp_repr*/
5391 0, /*tp_as_number*/
5392 0, /*tp_as_sequence*/
5393 &DB_mapping,/*tp_as_mapping*/
5394 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005395 0, /* tp_call */
5396 0, /* tp_str */
5397 0, /* tp_getattro */
5398 0, /* tp_setattro */
5399 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005400 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005401 0, /* tp_doc */
5402 0, /* tp_traverse */
5403 0, /* tp_clear */
5404 0, /* tp_richcompare */
5405 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005406};
5407
5408
Neal Norwitz227b5332006-03-22 09:28:35 +00005409static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005410 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005411 "DBCursor", /*tp_name*/
5412 sizeof(DBCursorObject), /*tp_basicsize*/
5413 0, /*tp_itemsize*/
5414 /* methods */
5415 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5416 0, /*tp_print*/
5417 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5418 0, /*tp_setattr*/
5419 0, /*tp_compare*/
5420 0, /*tp_repr*/
5421 0, /*tp_as_number*/
5422 0, /*tp_as_sequence*/
5423 0, /*tp_as_mapping*/
5424 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005425 0, /* tp_call */
5426 0, /* tp_str */
5427 0, /* tp_getattro */
5428 0, /* tp_setattro */
5429 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005430 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005431 0, /* tp_doc */
5432 0, /* tp_traverse */
5433 0, /* tp_clear */
5434 0, /* tp_richcompare */
5435 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005436};
5437
5438
Neal Norwitz227b5332006-03-22 09:28:35 +00005439static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005440 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005441 "DBEnv", /*tp_name*/
5442 sizeof(DBEnvObject), /*tp_basicsize*/
5443 0, /*tp_itemsize*/
5444 /* methods */
5445 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5446 0, /*tp_print*/
5447 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5448 0, /*tp_setattr*/
5449 0, /*tp_compare*/
5450 0, /*tp_repr*/
5451 0, /*tp_as_number*/
5452 0, /*tp_as_sequence*/
5453 0, /*tp_as_mapping*/
5454 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005455 0, /* tp_call */
5456 0, /* tp_str */
5457 0, /* tp_getattro */
5458 0, /* tp_setattro */
5459 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005460 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005461 0, /* tp_doc */
5462 0, /* tp_traverse */
5463 0, /* tp_clear */
5464 0, /* tp_richcompare */
5465 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005466};
5467
Neal Norwitz227b5332006-03-22 09:28:35 +00005468static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005469 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005470 "DBTxn", /*tp_name*/
5471 sizeof(DBTxnObject), /*tp_basicsize*/
5472 0, /*tp_itemsize*/
5473 /* methods */
5474 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5475 0, /*tp_print*/
5476 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5477 0, /*tp_setattr*/
5478 0, /*tp_compare*/
5479 0, /*tp_repr*/
5480 0, /*tp_as_number*/
5481 0, /*tp_as_sequence*/
5482 0, /*tp_as_mapping*/
5483 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005484 0, /* tp_call */
5485 0, /* tp_str */
5486 0, /* tp_getattro */
5487 0, /* tp_setattro */
5488 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005489 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005490 0, /* tp_doc */
5491 0, /* tp_traverse */
5492 0, /* tp_clear */
5493 0, /* tp_richcompare */
5494 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005495};
5496
5497
Neal Norwitz227b5332006-03-22 09:28:35 +00005498static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005499 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005500 "DBLock", /*tp_name*/
5501 sizeof(DBLockObject), /*tp_basicsize*/
5502 0, /*tp_itemsize*/
5503 /* methods */
5504 (destructor)DBLock_dealloc, /*tp_dealloc*/
5505 0, /*tp_print*/
5506 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5507 0, /*tp_setattr*/
5508 0, /*tp_compare*/
5509 0, /*tp_repr*/
5510 0, /*tp_as_number*/
5511 0, /*tp_as_sequence*/
5512 0, /*tp_as_mapping*/
5513 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005514 0, /* tp_call */
5515 0, /* tp_str */
5516 0, /* tp_getattro */
5517 0, /* tp_setattro */
5518 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005519 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005520 0, /* tp_doc */
5521 0, /* tp_traverse */
5522 0, /* tp_clear */
5523 0, /* tp_richcompare */
5524 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005525};
5526
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005527#if (DBVER >= 43)
5528static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005529 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005530 "DBSequence", /*tp_name*/
5531 sizeof(DBSequenceObject), /*tp_basicsize*/
5532 0, /*tp_itemsize*/
5533 /* methods */
5534 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5535 0, /*tp_print*/
5536 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5537 0, /*tp_setattr*/
5538 0, /*tp_compare*/
5539 0, /*tp_repr*/
5540 0, /*tp_as_number*/
5541 0, /*tp_as_sequence*/
5542 0, /*tp_as_mapping*/
5543 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005544 0, /* tp_call */
5545 0, /* tp_str */
5546 0, /* tp_getattro */
5547 0, /* tp_setattro */
5548 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005549 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005550 0, /* tp_doc */
5551 0, /* tp_traverse */
5552 0, /* tp_clear */
5553 0, /* tp_richcompare */
5554 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005555};
5556#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005557
5558/* --------------------------------------------------------------------- */
5559/* Module-level functions */
5560
5561static PyObject*
5562DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5563{
5564 PyObject* dbenvobj = NULL;
5565 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005566 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005567
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5569 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005570 return NULL;
5571 if (dbenvobj == Py_None)
5572 dbenvobj = NULL;
5573 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5574 makeTypeError("DBEnv", dbenvobj);
5575 return NULL;
5576 }
5577
5578 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5579}
5580
5581
5582static PyObject*
5583DBEnv_construct(PyObject* self, PyObject* args)
5584{
5585 int flags = 0;
5586 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5587 return (PyObject* )newDBEnvObject(flags);
5588}
5589
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005590#if (DBVER >= 43)
5591static PyObject*
5592DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5593{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005594 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005595 int flags = 0;
5596 static char* kwnames[] = { "db", "flags", NULL};
5597
5598 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5599 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005600 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005601 makeTypeError("DB", dbobj);
5602 return NULL;
5603 }
5604 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5605}
5606#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005607
5608static char bsddb_version_doc[] =
5609"Returns a tuple of major, minor, and patch release numbers of the\n\
5610underlying DB library.";
5611
5612static PyObject*
5613bsddb_version(PyObject* self, PyObject* args)
5614{
5615 int major, minor, patch;
5616
5617 if (!PyArg_ParseTuple(args, ":version"))
5618 return NULL;
5619 db_version(&major, &minor, &patch);
5620 return Py_BuildValue("(iii)", major, minor, patch);
5621}
5622
5623
5624/* List of functions defined in the module */
5625
5626static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005627 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5628 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5629#if (DBVER >= 43)
5630 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5631#endif
5632 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633 {NULL, NULL} /* sentinel */
5634};
5635
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005636/* API structure */
5637static BSDDB_api bsddb_api;
5638
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005639
5640/* --------------------------------------------------------------------- */
5641/* Module initialization */
5642
5643
5644/* Convenience routine to export an integer value.
5645 * Errors are silently ignored, for better or for worse...
5646 */
5647#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5648
Gregory P. Smith41631e82003-09-21 00:08:14 +00005649#define MODULE_NAME_MAX_LEN 11
5650static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005651
Neal Norwitzf6657e62006-12-28 04:47:50 +00005652PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653{
5654 PyObject* m;
5655 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005656 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5657 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5658 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005659 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005660
5661 /* Initialize the type of the new type objects here; doing it here
5662 is required for portability to Windows without requiring C++. */
Christian Heimes90aa7642007-12-19 02:45:37 +00005663 Py_TYPE(&DB_Type) = &PyType_Type;
5664 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5665 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5666 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5667 Py_TYPE(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005668#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +00005669 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005670#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005671
5672
Mark Hammonda69d4092003-04-22 23:13:27 +00005673#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005674 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005675 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005676#endif
5677
5678 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005679 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005680 if (m == NULL)
5681 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005682
5683 /* Add some symbolic constants to the module */
5684 d = PyModule_GetDict(m);
5685 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005686 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005687 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5688 Py_DECREF(pybsddb_version_s);
5689 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005690 Py_DECREF(svnid_s);
5691 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005692 Py_DECREF(db_version_s);
5693 db_version_s = NULL;
5694
5695 ADD_INT(d, DB_VERSION_MAJOR);
5696 ADD_INT(d, DB_VERSION_MINOR);
5697 ADD_INT(d, DB_VERSION_PATCH);
5698
5699 ADD_INT(d, DB_MAX_PAGES);
5700 ADD_INT(d, DB_MAX_RECORDS);
5701
Gregory P. Smith41631e82003-09-21 00:08:14 +00005702#if (DBVER >= 42)
5703 ADD_INT(d, DB_RPCCLIENT);
5704#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005705 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005706 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5707 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5708#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005709 ADD_INT(d, DB_XA_CREATE);
5710
5711 ADD_INT(d, DB_CREATE);
5712 ADD_INT(d, DB_NOMMAP);
5713 ADD_INT(d, DB_THREAD);
5714
5715 ADD_INT(d, DB_FORCE);
5716 ADD_INT(d, DB_INIT_CDB);
5717 ADD_INT(d, DB_INIT_LOCK);
5718 ADD_INT(d, DB_INIT_LOG);
5719 ADD_INT(d, DB_INIT_MPOOL);
5720 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005721 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005722
5723 ADD_INT(d, DB_RECOVER);
5724 ADD_INT(d, DB_RECOVER_FATAL);
5725 ADD_INT(d, DB_TXN_NOSYNC);
5726 ADD_INT(d, DB_USE_ENVIRON);
5727 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5728
5729 ADD_INT(d, DB_LOCKDOWN);
5730 ADD_INT(d, DB_PRIVATE);
5731 ADD_INT(d, DB_SYSTEM_MEM);
5732
5733 ADD_INT(d, DB_TXN_SYNC);
5734 ADD_INT(d, DB_TXN_NOWAIT);
5735
5736 ADD_INT(d, DB_EXCL);
5737 ADD_INT(d, DB_FCNTL_LOCKING);
5738 ADD_INT(d, DB_ODDFILESIZE);
5739 ADD_INT(d, DB_RDWRMASTER);
5740 ADD_INT(d, DB_RDONLY);
5741 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005742 ADD_INT(d, DB_EXTENT);
5743 ADD_INT(d, DB_CDB_ALLDB);
5744 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005745 ADD_INT(d, DB_UPGRADE);
5746
5747 ADD_INT(d, DB_AGGRESSIVE);
5748 ADD_INT(d, DB_NOORDERCHK);
5749 ADD_INT(d, DB_ORDERCHKONLY);
5750 ADD_INT(d, DB_PR_PAGE);
5751#if ! (DBVER >= 33)
5752 ADD_INT(d, DB_VRFY_FLAGMASK);
5753 ADD_INT(d, DB_PR_HEADERS);
5754#endif
5755 ADD_INT(d, DB_PR_RECOVERYTEST);
5756 ADD_INT(d, DB_SALVAGE);
5757
5758 ADD_INT(d, DB_LOCK_NORUN);
5759 ADD_INT(d, DB_LOCK_DEFAULT);
5760 ADD_INT(d, DB_LOCK_OLDEST);
5761 ADD_INT(d, DB_LOCK_RANDOM);
5762 ADD_INT(d, DB_LOCK_YOUNGEST);
5763#if (DBVER >= 33)
5764 ADD_INT(d, DB_LOCK_MAXLOCKS);
5765 ADD_INT(d, DB_LOCK_MINLOCKS);
5766 ADD_INT(d, DB_LOCK_MINWRITE);
5767#endif
5768
5769
5770#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005771 /* docs say to use zero instead */
5772 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005773#else
5774 ADD_INT(d, DB_LOCK_CONFLICT);
5775#endif
5776
5777 ADD_INT(d, DB_LOCK_DUMP);
5778 ADD_INT(d, DB_LOCK_GET);
5779 ADD_INT(d, DB_LOCK_INHERIT);
5780 ADD_INT(d, DB_LOCK_PUT);
5781 ADD_INT(d, DB_LOCK_PUT_ALL);
5782 ADD_INT(d, DB_LOCK_PUT_OBJ);
5783
5784 ADD_INT(d, DB_LOCK_NG);
5785 ADD_INT(d, DB_LOCK_READ);
5786 ADD_INT(d, DB_LOCK_WRITE);
5787 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005788 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005789 ADD_INT(d, DB_LOCK_IWRITE);
5790 ADD_INT(d, DB_LOCK_IREAD);
5791 ADD_INT(d, DB_LOCK_IWR);
5792#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005793#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005794 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005795#else
5796 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5797#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005798 ADD_INT(d, DB_LOCK_WWRITE);
5799#endif
5800
5801 ADD_INT(d, DB_LOCK_RECORD);
5802 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005803 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005804#if (DBVER >= 33)
5805 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5806#endif
5807
5808 ADD_INT(d, DB_LOCK_NOWAIT);
5809 ADD_INT(d, DB_LOCK_RECORD);
5810 ADD_INT(d, DB_LOCK_UPGRADE);
5811
5812#if (DBVER >= 33)
5813 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005814#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005815 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005816#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005817 ADD_INT(d, DB_LSTAT_FREE);
5818 ADD_INT(d, DB_LSTAT_HELD);
5819#if (DBVER == 33)
5820 ADD_INT(d, DB_LSTAT_NOGRANT);
5821#endif
5822 ADD_INT(d, DB_LSTAT_PENDING);
5823 ADD_INT(d, DB_LSTAT_WAITING);
5824#endif
5825
5826 ADD_INT(d, DB_ARCH_ABS);
5827 ADD_INT(d, DB_ARCH_DATA);
5828 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005829#if (DBVER >= 42)
5830 ADD_INT(d, DB_ARCH_REMOVE);
5831#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005832
5833 ADD_INT(d, DB_BTREE);
5834 ADD_INT(d, DB_HASH);
5835 ADD_INT(d, DB_RECNO);
5836 ADD_INT(d, DB_QUEUE);
5837 ADD_INT(d, DB_UNKNOWN);
5838
5839 ADD_INT(d, DB_DUP);
5840 ADD_INT(d, DB_DUPSORT);
5841 ADD_INT(d, DB_RECNUM);
5842 ADD_INT(d, DB_RENUMBER);
5843 ADD_INT(d, DB_REVSPLITOFF);
5844 ADD_INT(d, DB_SNAPSHOT);
5845
5846 ADD_INT(d, DB_JOIN_NOSORT);
5847
5848 ADD_INT(d, DB_AFTER);
5849 ADD_INT(d, DB_APPEND);
5850 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005851#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005852 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005853#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005854#if (DBVER >= 41)
5855 _addIntToDict(d, "DB_CHECKPOINT", 0);
5856#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005858 ADD_INT(d, DB_CURLSN);
5859#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005860#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005861 ADD_INT(d, DB_COMMIT);
5862#endif
5863 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005864 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005865 ADD_INT(d, DB_CURRENT);
5866#if (DBVER >= 33)
5867 ADD_INT(d, DB_FAST_STAT);
5868#endif
5869 ADD_INT(d, DB_FIRST);
5870 ADD_INT(d, DB_FLUSH);
5871 ADD_INT(d, DB_GET_BOTH);
5872 ADD_INT(d, DB_GET_RECNO);
5873 ADD_INT(d, DB_JOIN_ITEM);
5874 ADD_INT(d, DB_KEYFIRST);
5875 ADD_INT(d, DB_KEYLAST);
5876 ADD_INT(d, DB_LAST);
5877 ADD_INT(d, DB_NEXT);
5878 ADD_INT(d, DB_NEXT_DUP);
5879 ADD_INT(d, DB_NEXT_NODUP);
5880 ADD_INT(d, DB_NODUPDATA);
5881 ADD_INT(d, DB_NOOVERWRITE);
5882 ADD_INT(d, DB_NOSYNC);
5883 ADD_INT(d, DB_POSITION);
5884 ADD_INT(d, DB_PREV);
5885 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005886#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005887 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005888#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005889 ADD_INT(d, DB_SET);
5890 ADD_INT(d, DB_SET_RANGE);
5891 ADD_INT(d, DB_SET_RECNO);
5892 ADD_INT(d, DB_WRITECURSOR);
5893
5894 ADD_INT(d, DB_OPFLAGS_MASK);
5895 ADD_INT(d, DB_RMW);
5896#if (DBVER >= 33)
5897 ADD_INT(d, DB_DIRTY_READ);
5898 ADD_INT(d, DB_MULTIPLE);
5899 ADD_INT(d, DB_MULTIPLE_KEY);
5900#endif
5901
Gregory P. Smith29602d22006-01-24 09:46:48 +00005902#if (DBVER >= 44)
5903 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5904 ADD_INT(d, DB_READ_COMMITTED);
5905#endif
5906
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005907#if (DBVER >= 33)
5908 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005909 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005910#endif
5911
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005912#if (DBVER >= 41)
5913 _addIntToDict(d, "DB_INCOMPLETE", 0);
5914#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005915 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005916#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005917 ADD_INT(d, DB_KEYEMPTY);
5918 ADD_INT(d, DB_KEYEXIST);
5919 ADD_INT(d, DB_LOCK_DEADLOCK);
5920 ADD_INT(d, DB_LOCK_NOTGRANTED);
5921 ADD_INT(d, DB_NOSERVER);
5922 ADD_INT(d, DB_NOSERVER_HOME);
5923 ADD_INT(d, DB_NOSERVER_ID);
5924 ADD_INT(d, DB_NOTFOUND);
5925 ADD_INT(d, DB_OLD_VERSION);
5926 ADD_INT(d, DB_RUNRECOVERY);
5927 ADD_INT(d, DB_VERIFY_BAD);
5928#if (DBVER >= 33)
5929 ADD_INT(d, DB_PAGE_NOTFOUND);
5930 ADD_INT(d, DB_SECONDARY_BAD);
5931#endif
5932#if (DBVER >= 40)
5933 ADD_INT(d, DB_STAT_CLEAR);
5934 ADD_INT(d, DB_REGION_INIT);
5935 ADD_INT(d, DB_NOLOCKING);
5936 ADD_INT(d, DB_YIELDCPU);
5937 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5938 ADD_INT(d, DB_NOPANIC);
5939#endif
5940
Guido van Rossum2cc30da2007-11-02 23:46:40 +00005941#ifdef DB_REGISTER
5942 ADD_INT(d, DB_REGISTER);
5943#endif
5944
Gregory P. Smith41631e82003-09-21 00:08:14 +00005945#if (DBVER >= 42)
5946 ADD_INT(d, DB_TIME_NOTGRANTED);
5947 ADD_INT(d, DB_TXN_NOT_DURABLE);
5948 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5949 ADD_INT(d, DB_LOG_AUTOREMOVE);
5950 ADD_INT(d, DB_DIRECT_LOG);
5951 ADD_INT(d, DB_DIRECT_DB);
5952 ADD_INT(d, DB_INIT_REP);
5953 ADD_INT(d, DB_ENCRYPT);
5954 ADD_INT(d, DB_CHKSUM);
5955#endif
5956
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005957#if (DBVER >= 43)
5958 ADD_INT(d, DB_LOG_INMEMORY);
5959 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005960 ADD_INT(d, DB_SEQ_DEC);
5961 ADD_INT(d, DB_SEQ_INC);
5962 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005963#endif
5964
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005965#if (DBVER >= 41)
5966 ADD_INT(d, DB_ENCRYPT_AES);
5967 ADD_INT(d, DB_AUTO_COMMIT);
5968#else
5969 /* allow berkeleydb 4.1 aware apps to run on older versions */
5970 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5971#endif
5972
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005973 ADD_INT(d, EINVAL);
5974 ADD_INT(d, EACCES);
5975 ADD_INT(d, ENOSPC);
5976 ADD_INT(d, ENOMEM);
5977 ADD_INT(d, EAGAIN);
5978 ADD_INT(d, EBUSY);
5979 ADD_INT(d, EEXIST);
5980 ADD_INT(d, ENOENT);
5981 ADD_INT(d, EPERM);
5982
Barry Warsaw1baa9822003-03-31 19:51:29 +00005983#if (DBVER >= 40)
5984 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5985 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5986#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005987
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005988 /* The exception name must be correct for pickled exception *
5989 * objects to unpickle properly. */
5990#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5991#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5992#else
5993#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5994#endif
5995
5996 /* All the rest of the exceptions derive only from DBError */
5997#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5998 PyDict_SetItemString(d, #name, name)
5999
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006001 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6002 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006003
Gregory P. Smithe9477062005-06-04 06:46:59 +00006004 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6005 * from both DBError and KeyError, since the API only supports
6006 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006008 {
Georg Brandl1a3284e2007-12-02 09:40:06 +00006009 PyObject *builtin_mod = PyImport_ImportModule("builtins");
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006010 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6011 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006012 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6013 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 Py_file_input, d, d);
6015 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006016 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006017 PyDict_DelItemString(d, "KeyError");
6018
6019
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006020#if !INCOMPLETE_IS_WARNING
6021 MAKE_EX(DBIncompleteError);
6022#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006023 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006024 MAKE_EX(DBKeyEmptyError);
6025 MAKE_EX(DBKeyExistError);
6026 MAKE_EX(DBLockDeadlockError);
6027 MAKE_EX(DBLockNotGrantedError);
6028 MAKE_EX(DBOldVersionError);
6029 MAKE_EX(DBRunRecoveryError);
6030 MAKE_EX(DBVerifyBadError);
6031 MAKE_EX(DBNoServerError);
6032 MAKE_EX(DBNoServerHomeError);
6033 MAKE_EX(DBNoServerIDError);
6034#if (DBVER >= 33)
6035 MAKE_EX(DBPageNotFoundError);
6036 MAKE_EX(DBSecondaryBadError);
6037#endif
6038
6039 MAKE_EX(DBInvalidArgError);
6040 MAKE_EX(DBAccessError);
6041 MAKE_EX(DBNoSpaceError);
6042 MAKE_EX(DBNoMemoryError);
6043 MAKE_EX(DBAgainError);
6044 MAKE_EX(DBBusyError);
6045 MAKE_EX(DBFileExistsError);
6046 MAKE_EX(DBNoSuchFileError);
6047 MAKE_EX(DBPermissionsError);
6048
6049#undef MAKE_EX
6050
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006051 /* Initiliase the C API structure and add it to the module */
6052 bsddb_api.db_type = &DB_Type;
6053 bsddb_api.dbcursor_type = &DBCursor_Type;
6054 bsddb_api.dbenv_type = &DBEnv_Type;
6055 bsddb_api.dbtxn_type = &DBTxn_Type;
6056 bsddb_api.dblock_type = &DBLock_Type;
6057#if (DBVER >= 43)
6058 bsddb_api.dbsequence_type = &DBSequence_Type;
6059#endif
6060 bsddb_api.makeDBError = makeDBError;
6061
6062 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6063 PyDict_SetItemString(d, "api", py_api);
6064 Py_DECREF(py_api);
6065
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006066 /* Check for errors */
6067 if (PyErr_Occurred()) {
6068 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006069 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006070 }
6071}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006072
6073/* allow this module to be named _pybsddb so that it can be installed
6074 * and imported on top of python >= 2.3 that includes its own older
6075 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006076PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006077{
6078 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6079 init_bsddb();
6080}