blob: 02973aab2df367c9bf7dfb80bd17d1ccd80245fd [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 }
Gregory P. Smithc55485b2008-03-17 20:16:47 +0000315 /* We use PyBUF_LOCK to prevent other threads from trashing the data
316 buffer while we release the GIL. http://bugs.python.org/issue1035 */
317 if (PyObject_GetBuffer(obj, view, PyBUF_LOCK) == -1) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000318 PyMem_Free(view);
319 return NULL;
320 }
321 if (view->ndim > 1) {
322 PyErr_SetString(PyExc_BufferError,
323 "buffers must be single dimension");
324 PyObject_ReleaseBuffer(obj, view);
325 PyMem_Free(view);
326 return NULL;
327 }
328 return view;
329}
330
331
332/* Create a DBT structure (containing key and data values) from Python
333 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000334 may be filled with a newly allocated Py_buffer view on success.
335 The caller MUST call free_buf_view() on any returned Py_buffer. */
336static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000337{
Thomas Heller39763a12007-09-24 14:43:56 +0000338 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000339
340 /* simple way to ensure the caller can detect if we've returned a
341 new buffer view or not: require their pointer to start out NULL. */
342 assert(*returned_view_p == NULL);
343
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000344 CLEAR_DBT(*dbt);
345 if (obj == Py_None) {
346 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000347 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000348 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000349 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000350 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000351 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000352 return 0;
353 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000354
355 if ( !(view = _malloc_view(obj)) )
356 return 0;
357
358 dbt->data = view->buf;
359 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
360 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000361 return 1;
362}
363
364
365/* Recno and Queue DBs can have integer keys. This function figures out
366 what's been given, verifies that it's allowed, and then makes the DBT.
367
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000368 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000369 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000370static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000371make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000372 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000373{
374 db_recno_t recno;
375 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000376 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000377
378 /* simple way to ensure the caller can detect if we've returned a
379 new buffer view or not: require their pointer to start out NULL. */
380 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000381
382 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000383 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000384 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000385 if (type == -1)
386 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000387 if (type == DB_RECNO || type == DB_QUEUE) {
388 PyErr_SetString(
389 PyExc_TypeError,
390 "None keys not allowed for Recno and Queue DB's");
391 return 0;
392 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000393 /* no need to do anything, the structure has already been zeroed */
394 }
395
Christian Heimes217cfd12007-12-02 14:31:20 +0000396 else if (PyLong_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000397 /* verify access method type */
398 type = _DB_get_type(self);
399 if (type == -1)
400 return 0;
401 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000402 /* if BTREE then an Integer key is allowed with the
403 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000404 *pflags |= DB_SET_RECNO;
405 }
406 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 PyErr_SetString(
408 PyExc_TypeError,
409 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000410 return 0;
411 }
412
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000413 /* Make a key out of the requested recno, use allocated space so DB
414 * will be able to realloc room for the real key if needed. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000415 recno = PyLong_AS_LONG(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416 key->data = malloc(sizeof(db_recno_t));
417 if (key->data == NULL) {
418 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
419 return 0;
420 }
421 key->ulen = key->size = sizeof(db_recno_t);
422 memcpy(key->data, &recno, sizeof(db_recno_t));
423 key->flags = DB_DBT_REALLOC;
424 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000425
426 else if (PyObject_CheckBuffer(keyobj)) {
427 /* verify access method type */
428 type = _DB_get_type(self);
429 if (type == -1)
430 return 0;
431 if (type == DB_RECNO || type == DB_QUEUE) {
432 PyErr_SetString(
433 PyExc_TypeError,
434 "Non-integer keys not allowed for Recno and Queue DB's");
435 return 0;
436 }
437
438 if ( !(view = _malloc_view(keyobj)) )
439 return 0;
440
Gregory P. Smith568065e2007-11-01 21:55:08 +0000441 /*
442 * NOTE(gps): I don't like doing a data copy here, it seems
443 * wasteful. But without a clean way to tell FREE_DBT if it
444 * should free key->data or not we have to. Other places in
445 * the code check for DB_THREAD and forceably set DBT_MALLOC
446 * when we otherwise would leave flags 0 to indicate that.
447 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000448 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000449 key->data = malloc(key->size);
450 if (key->data == NULL) {
451 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
452 key->size = 0;
453 return 0;
454 }
455 memcpy(key->data, view->buf, key->size);
456 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000457 *returned_view_p = view;
458 }
459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000460 else {
461 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000462 "buffer or int object expected for key, %s found",
Christian Heimes90aa7642007-12-19 02:45:37 +0000463 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000464 return 0;
465 }
466
467 return 1;
468}
469
470
471/* Add partial record access to an existing DBT data struct.
472 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
473 and the data storage/retrieval will be done using dlen and doff. */
474static int add_partial_dbt(DBT* d, int dlen, int doff) {
475 /* if neither were set we do nothing (-1 is the default value) */
476 if ((dlen == -1) && (doff == -1)) {
477 return 1;
478 }
479
480 if ((dlen < 0) || (doff < 0)) {
481 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
482 return 0;
483 }
484
485 d->flags = d->flags | DB_DBT_PARTIAL;
486 d->dlen = (unsigned int) dlen;
487 d->doff = (unsigned int) doff;
488 return 1;
489}
490
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
492/* TODO: make this use the native libc strlcpy() when available (BSD) */
493unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
494{
495 unsigned int srclen, copylen;
496
497 srclen = strlen(src);
498 if (n <= 0)
499 return srclen;
500 copylen = (srclen > n-1) ? n-1 : srclen;
501 /* populate dest[0] thru dest[copylen-1] */
502 memcpy(dest, src, copylen);
503 /* guarantee null termination */
504 dest[copylen] = 0;
505
506 return srclen;
507}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000509/* Callback used to save away more information about errors from the DB
510 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000511static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000512#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514#else
515static void _db_errorCallback(const DB_ENV *db_env,
516 const char* prefix, const char* msg)
517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000519 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520}
521
522
523/* make a nice exception object to raise for errors. */
524static int makeDBError(int err)
525{
526 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000527 PyObject *errObj = NULL;
528 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000529 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000530 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000531
532 switch (err) {
533 case 0: /* successful, no error */ break;
534
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000535#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000536 case DB_INCOMPLETE:
537#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000538 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
539 /* Ensure that bytes_left never goes negative */
540 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
541 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
542 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000543 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000544 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000545 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000546 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000547 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000548
549#else /* do an exception instead */
550 errObj = DBIncompleteError;
551#endif
552 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000553#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000554
555 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
556 case DB_KEYEXIST: errObj = DBKeyExistError; break;
557 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
558 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
559 case DB_NOTFOUND: errObj = DBNotFoundError; break;
560 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
561 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
562 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
563 case DB_NOSERVER: errObj = DBNoServerError; break;
564 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
565 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
566#if (DBVER >= 33)
567 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
568 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
569#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000570 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000571
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000572#if (DBVER >= 43)
573 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
574 case ENOMEM: errObj = PyExc_MemoryError; break;
575#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000576 case EINVAL: errObj = DBInvalidArgError; break;
577 case EACCES: errObj = DBAccessError; break;
578 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000579 case EAGAIN: errObj = DBAgainError; break;
580 case EBUSY : errObj = DBBusyError; break;
581 case EEXIST: errObj = DBFileExistsError; break;
582 case ENOENT: errObj = DBNoSuchFileError; break;
583 case EPERM : errObj = DBPermissionsError; break;
584
585 default: errObj = DBError; break;
586 }
587
588 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000589 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
590 /* Ensure that bytes_left never goes negative */
591 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
592 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
593 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000594 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000597 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000598
599 errTuple = Py_BuildValue("(is)", err, errTxt);
600 PyErr_SetObject(errObj, errTuple);
601 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
603
604 return ((errObj != NULL) || exceptionRaised);
605}
606
607
608
609/* set a type exception */
610static void makeTypeError(char* expected, PyObject* found)
611{
612 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000613 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614}
615
616
617/* verify that an obj is either None or a DBTxn, and set the txn pointer */
618static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
619{
620 if (txnobj == Py_None || txnobj == NULL) {
621 *txn = NULL;
622 return 1;
623 }
624 if (DBTxnObject_Check(txnobj)) {
625 *txn = ((DBTxnObject*)txnobj)->txn;
626 return 1;
627 }
628 else
629 makeTypeError("DBTxn", txnobj);
630 return 0;
631}
632
633
634/* Delete a key from a database
635 Returns 0 on success, -1 on an error. */
636static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
637{
638 int err;
639
640 MYDB_BEGIN_ALLOW_THREADS;
641 err = self->db->del(self->db, txn, key, 0);
642 MYDB_END_ALLOW_THREADS;
643 if (makeDBError(err)) {
644 return -1;
645 }
646 self->haveStat = 0;
647 return 0;
648}
649
650
651/* Store a key into a database
652 Returns 0 on success, -1 on an error. */
653static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
654{
655 int err;
656
657 MYDB_BEGIN_ALLOW_THREADS;
658 err = self->db->put(self->db, txn, key, data, flags);
659 MYDB_END_ALLOW_THREADS;
660 if (makeDBError(err)) {
661 return -1;
662 }
663 self->haveStat = 0;
664 return 0;
665}
666
667/* Get a key/data pair from a cursor */
668static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
669 PyObject *args, PyObject *kwargs, char *format)
670{
671 int err;
672 PyObject* retval = NULL;
673 DBT key, data;
674 int dlen = -1;
675 int doff = -1;
676 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000677 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678
679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
680 &flags, &dlen, &doff))
681 return NULL;
682
683 CHECK_CURSOR_NOT_CLOSED(self);
684
685 flags |= extra_flags;
686 CLEAR_DBT(key);
687 CLEAR_DBT(data);
688 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
689 /* Tell BerkeleyDB to malloc the return value (thread safe) */
690 data.flags = DB_DBT_MALLOC;
691 key.flags = DB_DBT_MALLOC;
692 }
693 if (!add_partial_dbt(&data, dlen, doff))
694 return NULL;
695
696 MYDB_BEGIN_ALLOW_THREADS;
697 err = self->dbc->c_get(self->dbc, &key, &data, flags);
698 MYDB_END_ALLOW_THREADS;
699
Gregory P. Smithe9477062005-06-04 06:46:59 +0000700 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
701 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000702 Py_INCREF(Py_None);
703 retval = Py_None;
704 }
705 else if (makeDBError(err)) {
706 retval = NULL;
707 }
708 else { /* otherwise, success! */
709
710 /* if Recno or Queue, return the key as an Int */
711 switch (_DB_get_type(self->mydb)) {
712 case -1:
713 retval = NULL;
714 break;
715
716 case DB_RECNO:
717 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000718 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000719 data.data, data.size);
720 break;
721 case DB_HASH:
722 case DB_BTREE:
723 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000724 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000725 data.data, data.size);
726 break;
727 }
728 }
729 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000730 free_dbt(&key);
731 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000732 }
733 return retval;
734}
735
736
737/* add an integer to a dictionary using the given name as a key */
738static void _addIntToDict(PyObject* dict, char *name, int value)
739{
Christian Heimes217cfd12007-12-02 14:31:20 +0000740 PyObject* v = PyLong_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000741 if (!v || PyDict_SetItemString(dict, name, v))
742 PyErr_Clear();
743
744 Py_XDECREF(v);
745}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000746
747/* The same, when the value is a time_t */
748static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
749{
750 PyObject* v;
751 /* if the value fits in regular int, use that. */
752#ifdef HAVE_LONG_LONG
753 if (sizeof(time_t) > sizeof(long))
754 v = PyLong_FromLongLong((PY_LONG_LONG) value);
755 else
756#endif
Christian Heimes217cfd12007-12-02 14:31:20 +0000757 v = PyLong_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000758 if (!v || PyDict_SetItemString(dict, name, v))
759 PyErr_Clear();
760
761 Py_XDECREF(v);
762}
763
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000764#if (DBVER >= 43)
765/* add an db_seq_t to a dictionary using the given name as a key */
766static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
767{
768 PyObject* v = PyLong_FromLongLong(value);
769 if (!v || PyDict_SetItemString(dict, name, v))
770 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000771
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000772 Py_XDECREF(v);
773}
774#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000775
776
777
778/* --------------------------------------------------------------------- */
779/* Allocators and deallocators */
780
781static DBObject*
782newDBObject(DBEnvObject* arg, int flags)
783{
784 DBObject* self;
785 DB_ENV* db_env = NULL;
786 int err;
787
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000788 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 if (self == NULL)
790 return NULL;
791
792 self->haveStat = 0;
793 self->flags = 0;
794 self->setflags = 0;
795 self->myenvobj = NULL;
796#if (DBVER >= 33)
797 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000798 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 self->primaryDBType = 0;
800#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000801 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000802
803 /* keep a reference to our python DBEnv object */
804 if (arg) {
805 Py_INCREF(arg);
806 self->myenvobj = arg;
807 db_env = arg->db_env;
808 }
809
810 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000811 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000812 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000813 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
814 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000815
816 MYDB_BEGIN_ALLOW_THREADS;
817 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000818 if (self->db != NULL) {
819 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000820#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000821 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000822#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000823 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000825 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
826 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000827 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 if (makeDBError(err)) {
829 if (self->myenvobj) {
830 Py_DECREF(self->myenvobj);
831 self->myenvobj = NULL;
832 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000833 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 self = NULL;
835 }
836 return self;
837}
838
839
840static void
841DB_dealloc(DBObject* self)
842{
843 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000844 /* avoid closing a DB when its DBEnv has been closed out from under
845 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000847 (self->myenvobj && self->myenvobj->db_env))
848 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000849 MYDB_BEGIN_ALLOW_THREADS;
850 self->db->close(self->db, 0);
851 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000852 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000853 PyErr_WarnEx(PyExc_RuntimeWarning,
854 "DB could not be closed in destructor:"
855 " DBEnv already closed",
856 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 }
858 self->db = NULL;
859 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000860 if (self->in_weakreflist != NULL) {
861 PyObject_ClearWeakRefs((PyObject *) self);
862 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000863 if (self->myenvobj) {
864 Py_DECREF(self->myenvobj);
865 self->myenvobj = NULL;
866 }
867#if (DBVER >= 33)
868 if (self->associateCallback != NULL) {
869 Py_DECREF(self->associateCallback);
870 self->associateCallback = NULL;
871 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000872 if (self->btCompareCallback != NULL) {
873 Py_DECREF(self->btCompareCallback);
874 self->btCompareCallback = NULL;
875 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878}
879
880
881static DBCursorObject*
882newDBCursorObject(DBC* dbc, DBObject* db)
883{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000884 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 if (self == NULL)
886 return NULL;
887
888 self->dbc = dbc;
889 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000890 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000891 Py_INCREF(self->mydb);
892 return self;
893}
894
895
896static void
897DBCursor_dealloc(DBCursorObject* self)
898{
899 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000900
Gregory P. Smitha703a212003-11-03 01:04:41 +0000901 if (self->in_weakreflist != NULL) {
902 PyObject_ClearWeakRefs((PyObject *) self);
903 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000904
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000906 /* If the underlying database has been closed, we don't
907 need to do anything. If the environment has been closed
908 we need to leak, as BerkeleyDB will crash trying to access
909 the environment. There was an exception when the
910 user closed the environment even though there still was
911 a database open. */
912 if (self->mydb->db && self->mydb->myenvobj &&
913 !self->mydb->myenvobj->closed)
Christian Heimes292d3512008-02-03 16:51:08 +0000914 /* test for: open db + no environment or non-closed environment */
915 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
916 !self->mydb->myenvobj->closed))) {
917 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000918 err = self->dbc->c_close(self->dbc);
Christian Heimes292d3512008-02-03 16:51:08 +0000919 MYDB_END_ALLOW_THREADS;
920 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922 }
923 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925}
926
927
928static DBEnvObject*
929newDBEnvObject(int flags)
930{
931 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000932 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000933 if (self == NULL)
934 return NULL;
935
936 self->closed = 1;
937 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000938 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
939 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000940 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941
942 MYDB_BEGIN_ALLOW_THREADS;
943 err = db_env_create(&self->db_env, flags);
944 MYDB_END_ALLOW_THREADS;
945 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000946 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947 self = NULL;
948 }
949 else {
950 self->db_env->set_errcall(self->db_env, _db_errorCallback);
951 }
952 return self;
953}
954
955
956static void
957DBEnv_dealloc(DBEnvObject* self)
958{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000959 if (self->in_weakreflist != NULL) {
960 PyObject_ClearWeakRefs((PyObject *) self);
961 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000962
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000963 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 MYDB_BEGIN_ALLOW_THREADS;
965 self->db_env->close(self->db_env, 0);
966 MYDB_END_ALLOW_THREADS;
967 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969}
970
971
972static DBTxnObject*
973newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
974{
975 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000976 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000977 if (self == NULL)
978 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000979 Py_INCREF(myenv);
980 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000981 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982
983 MYDB_BEGIN_ALLOW_THREADS;
984#if (DBVER >= 40)
985 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#else
987 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
988#endif
989 MYDB_END_ALLOW_THREADS;
990 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000991 Py_DECREF(self->env);
992 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000993 self = NULL;
994 }
995 return self;
996}
997
998
999static void
1000DBTxn_dealloc(DBTxnObject* self)
1001{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001002 if (self->in_weakreflist != NULL) {
1003 PyObject_ClearWeakRefs((PyObject *) self);
1004 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005
Gregory P. Smith31c50652004-06-28 01:20:40 +00001006 if (self->txn) {
1007 /* it hasn't been finalized, abort it! */
1008 MYDB_BEGIN_ALLOW_THREADS;
1009#if (DBVER >= 40)
1010 self->txn->abort(self->txn);
1011#else
1012 txn_abort(self->txn);
1013#endif
1014 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001015 PyErr_WarnEx(PyExc_RuntimeWarning,
1016 "DBTxn aborted in destructor. "
1017 " No prior commit() or abort().",
1018 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001019 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020
Neal Norwitz62a21122006-01-25 05:21:55 +00001021 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023}
1024
1025
1026static DBLockObject*
1027newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1029{
1030 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032 if (self == NULL)
1033 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001034 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001035
1036 MYDB_BEGIN_ALLOW_THREADS;
1037#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001038 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1039 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040#else
1041 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1042#endif
1043 MYDB_END_ALLOW_THREADS;
1044 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001045 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046 self = NULL;
1047 }
1048
1049 return self;
1050}
1051
1052
1053static void
1054DBLock_dealloc(DBLockObject* self)
1055{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001056 if (self->in_weakreflist != NULL) {
1057 PyObject_ClearWeakRefs((PyObject *) self);
1058 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001059 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001061 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062}
1063
1064
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001065#if (DBVER >= 43)
1066static DBSequenceObject*
1067newDBSequenceObject(DBObject* mydb, int flags)
1068{
1069 int err;
1070 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1071 if (self == NULL)
1072 return NULL;
1073 Py_INCREF(mydb);
1074 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001075 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001076
1077
1078 MYDB_BEGIN_ALLOW_THREADS;
1079 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1080 MYDB_END_ALLOW_THREADS;
1081 if (makeDBError(err)) {
1082 Py_DECREF(self->mydb);
1083 PyObject_Del(self);
1084 self = NULL;
1085 }
1086
1087 return self;
1088}
1089
1090
1091static void
1092DBSequence_dealloc(DBSequenceObject* self)
1093{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001094 if (self->in_weakreflist != NULL) {
1095 PyObject_ClearWeakRefs((PyObject *) self);
1096 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001097
1098 Py_DECREF(self->mydb);
1099 PyObject_Del(self);
1100}
1101#endif
1102
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001103/* --------------------------------------------------------------------- */
1104/* DB methods */
1105
1106static PyObject*
1107DB_append(DBObject* self, PyObject* args)
1108{
1109 PyObject* txnobj = NULL;
1110 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001111 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001112 db_recno_t recno;
1113 DBT key, data;
1114 DB_TXN *txn = NULL;
1115
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001116 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001117 return NULL;
1118
1119 CHECK_DB_NOT_CLOSED(self);
1120
1121 /* make a dummy key out of a recno */
1122 recno = 0;
1123 CLEAR_DBT(key);
1124 key.data = &recno;
1125 key.size = sizeof(recno);
1126 key.ulen = key.size;
1127 key.flags = DB_DBT_USERMEM;
1128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001129 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001130 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001131
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001132 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1133 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001134 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001135 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001137 free_buf_view(dataobj, data_buf_view);
Christian Heimes217cfd12007-12-02 14:31:20 +00001138 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001139}
1140
1141
1142#if (DBVER >= 33)
1143
1144static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001145_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1146 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147{
1148 int retval = DB_DONOTINDEX;
1149 DBObject* secondaryDB = (DBObject*)db->app_private;
1150 PyObject* callback = secondaryDB->associateCallback;
1151 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001153 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154
1155
1156 if (callback != NULL) {
1157 MYDB_BEGIN_BLOCK_THREADS;
1158
Thomas Woutersb3153832006-03-08 01:47:19 +00001159 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001160 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001161 priData->data, priData->size);
1162 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001163 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001164 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001165 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001166 result = PyEval_CallObject(callback, args);
1167 }
1168 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169 PyErr_Print();
1170 }
1171 else if (result == Py_None) {
1172 retval = DB_DONOTINDEX;
1173 }
Christian Heimes217cfd12007-12-02 14:31:20 +00001174 else if (PyLong_Check(result)) {
1175 retval = PyLong_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176 }
Guido van Rossum98297ee2007-11-06 21:34:58 +00001177 else if (PyBytes_Check(result) || PyString_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001178 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001179 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001180
1181 CLEAR_DBT(*secKey);
Christian Heimes90aa7642007-12-19 02:45:37 +00001182 size = Py_SIZE(result);
Guido van Rossum98297ee2007-11-06 21:34:58 +00001183 if (PyBytes_Check(result))
1184 data = PyBytes_AS_STRING(result);
1185 else
1186 data = PyString_AS_STRING(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001187 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1188 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001189 if (secKey->data) {
1190 memcpy(secKey->data, data, size);
1191 secKey->size = size;
1192 retval = 0;
1193 }
1194 else {
1195 PyErr_SetString(PyExc_MemoryError,
1196 "malloc failed in _db_associateCallback");
1197 PyErr_Print();
1198 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001199 }
1200 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001201 PyErr_SetString(
1202 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001203 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001204 PyErr_Print();
1205 }
1206
Thomas Woutersb3153832006-03-08 01:47:19 +00001207 Py_XDECREF(args);
1208 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001209
1210 MYDB_END_BLOCK_THREADS;
1211 }
1212 return retval;
1213}
1214
1215
1216static PyObject*
1217DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1218{
1219 int err, flags=0;
1220 DBObject* secondaryDB;
1221 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001222#if (DBVER >= 41)
1223 PyObject *txnobj = NULL;
1224 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001225 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001226 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001227#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001228 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001229#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001230
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001231#if (DBVER >= 41)
1232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1233 &secondaryDB, &callback, &flags,
1234 &txnobj)) {
1235#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237 &secondaryDB, &callback, &flags)) {
1238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001239 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001240 }
1241
1242#if (DBVER >= 41)
1243 if (!checkTxnObj(txnobj, &txn)) return NULL;
1244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245
1246 CHECK_DB_NOT_CLOSED(self);
1247 if (!DBObject_Check(secondaryDB)) {
1248 makeTypeError("DB", (PyObject*)secondaryDB);
1249 return NULL;
1250 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001251 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001252 if (callback == Py_None) {
1253 callback = NULL;
1254 }
1255 else if (!PyCallable_Check(callback)) {
1256 makeTypeError("Callable", callback);
1257 return NULL;
1258 }
1259
1260 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001261 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001262 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001263 secondaryDB->associateCallback = callback;
1264 secondaryDB->primaryDBType = _DB_get_type(self);
1265
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001266 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1267 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1268 * The global interepreter lock is not initialized until the first
1269 * thread is created using thread.start_new_thread() or fork() is
1270 * called. that would cause the ALLOW_THREADS here to segfault due
1271 * to a null pointer reference if no threads or child processes
1272 * have been created. This works around that and is a no-op if
1273 * threads have already been initialized.
1274 * (see pybsddb-users mailing list post on 2002-08-07)
1275 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001276#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001277 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001278#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001279 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001280#if (DBVER >= 41)
1281 err = self->db->associate(self->db,
1282 txn,
1283 secondaryDB->db,
1284 _db_associateCallback,
1285 flags);
1286#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001287 err = self->db->associate(self->db,
1288 secondaryDB->db,
1289 _db_associateCallback,
1290 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001291#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001292 MYDB_END_ALLOW_THREADS;
1293
1294 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001295 Py_XDECREF(secondaryDB->associateCallback);
1296 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 secondaryDB->primaryDBType = 0;
1298 }
1299
1300 RETURN_IF_ERR();
1301 RETURN_NONE();
1302}
1303
1304
1305#endif
1306
1307
1308static PyObject*
1309DB_close(DBObject* self, PyObject* args)
1310{
1311 int err, flags=0;
1312 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1313 return NULL;
1314 if (self->db != NULL) {
1315 if (self->myenvobj)
1316 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001317 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001318 self->db = NULL;
1319 RETURN_IF_ERR();
1320 }
1321 RETURN_NONE();
1322}
1323
1324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001325static PyObject*
1326_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1327{
1328 int err, flags=0, type;
1329 PyObject* txnobj = NULL;
1330 PyObject* retval = NULL;
1331 DBT key, data;
1332 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001333 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001334
1335 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1336 &txnobj, &flags))
1337 return NULL;
1338
1339 CHECK_DB_NOT_CLOSED(self);
1340 type = _DB_get_type(self);
1341 if (type == -1)
1342 return NULL;
1343 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001344 PyErr_SetString(PyExc_TypeError,
1345 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001346 return NULL;
1347 }
1348 if (!checkTxnObj(txnobj, &txn))
1349 return NULL;
1350
1351 CLEAR_DBT(key);
1352 CLEAR_DBT(data);
1353 if (CHECK_DBFLAG(self, DB_THREAD)) {
1354 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1355 data.flags = DB_DBT_MALLOC;
1356 key.flags = DB_DBT_MALLOC;
1357 }
1358
1359 MYDB_BEGIN_ALLOW_THREADS;
1360 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1361 MYDB_END_ALLOW_THREADS;
1362
Gregory P. Smithe9477062005-06-04 06:46:59 +00001363 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1364 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001365 err = 0;
1366 Py_INCREF(Py_None);
1367 retval = Py_None;
1368 }
1369 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001370 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001371 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001372 free_dbt(&key);
1373 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001374 }
1375
1376 RETURN_IF_ERR();
1377 return retval;
1378}
1379
1380static PyObject*
1381DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1382{
1383 return _DB_consume(self, args, kwargs, DB_CONSUME);
1384}
1385
1386static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001387DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1388 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001389{
1390 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1391}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392
1393
1394static PyObject*
1395DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1396{
1397 int err, flags=0;
1398 DBC* dbc;
1399 PyObject* txnobj = NULL;
1400 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001401 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402
1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1404 &txnobj, &flags))
1405 return NULL;
1406 CHECK_DB_NOT_CLOSED(self);
1407 if (!checkTxnObj(txnobj, &txn))
1408 return NULL;
1409
1410 MYDB_BEGIN_ALLOW_THREADS;
1411 err = self->db->cursor(self->db, txn, &dbc, flags);
1412 MYDB_END_ALLOW_THREADS;
1413 RETURN_IF_ERR();
1414 return (PyObject*) newDBCursorObject(dbc, self);
1415}
1416
1417
1418static PyObject*
1419DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1420{
1421 PyObject* txnobj = NULL;
1422 int flags = 0;
1423 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001424 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425 DBT key;
1426 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001427 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428
1429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1430 &keyobj, &txnobj, &flags))
1431 return NULL;
1432 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001433 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001435 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001436 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001438 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001440 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001441 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001443 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001444
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001445 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001446 RETURN_NONE();
1447}
1448
1449
1450static PyObject*
1451DB_fd(DBObject* self, PyObject* args)
1452{
1453 int err, the_fd;
1454
1455 if (!PyArg_ParseTuple(args,":fd"))
1456 return NULL;
1457 CHECK_DB_NOT_CLOSED(self);
1458
1459 MYDB_BEGIN_ALLOW_THREADS;
1460 err = self->db->fd(self->db, &the_fd);
1461 MYDB_END_ALLOW_THREADS;
1462 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00001463 return PyLong_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464}
1465
1466
1467static PyObject*
1468DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1469{
1470 int err, flags=0;
1471 PyObject* txnobj = NULL;
1472 PyObject* keyobj;
1473 PyObject* dfltobj = NULL;
1474 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001475 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476 int dlen = -1;
1477 int doff = -1;
1478 DBT key, data;
1479 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001480 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001481 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001482
1483 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001484 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1485 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001486 return NULL;
1487
1488 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001489 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001490 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001491 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001492 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001494 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001495
1496 CLEAR_DBT(data);
1497 if (CHECK_DBFLAG(self, DB_THREAD)) {
1498 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1499 data.flags = DB_DBT_MALLOC;
1500 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001501 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001502 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001504 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505
1506 MYDB_BEGIN_ALLOW_THREADS;
1507 err = self->db->get(self->db, txn, &key, &data, flags);
1508 MYDB_END_ALLOW_THREADS;
1509
Gregory P. Smithe9477062005-06-04 06:46:59 +00001510 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 err = 0;
1512 Py_INCREF(dfltobj);
1513 retval = dfltobj;
1514 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001515 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1516 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 err = 0;
1518 Py_INCREF(Py_None);
1519 retval = Py_None;
1520 }
1521 else if (!err) {
1522 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001523 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001524 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525 else /* return just the data */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001526 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001527 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001529 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001530
1531 RETURN_IF_ERR();
1532 return retval;
1533}
1534
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001535#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001536static PyObject*
1537DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1538{
1539 int err, flags=0;
1540 PyObject* txnobj = NULL;
1541 PyObject* keyobj;
1542 PyObject* dfltobj = NULL;
1543 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001544 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001545 int dlen = -1;
1546 int doff = -1;
1547 DBT key, pkey, data;
1548 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001549 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001550 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001551
1552 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1553 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1554 &doff))
1555 return NULL;
1556
1557 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001558 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001559 return NULL;
1560 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001561 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001562 return NULL;
1563 }
1564
1565 CLEAR_DBT(data);
1566 if (CHECK_DBFLAG(self, DB_THREAD)) {
1567 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1568 data.flags = DB_DBT_MALLOC;
1569 }
1570 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001571 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001572 return NULL;
1573 }
1574
1575 CLEAR_DBT(pkey);
1576 pkey.flags = DB_DBT_MALLOC;
1577
1578 MYDB_BEGIN_ALLOW_THREADS;
1579 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1580 MYDB_END_ALLOW_THREADS;
1581
Gregory P. Smithe9477062005-06-04 06:46:59 +00001582 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001583 err = 0;
1584 Py_INCREF(dfltobj);
1585 retval = dfltobj;
1586 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001587 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1588 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001589 err = 0;
1590 Py_INCREF(Py_None);
1591 retval = Py_None;
1592 }
1593 else if (!err) {
1594 PyObject *pkeyObj;
1595 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00001596 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001597
1598 if (self->primaryDBType == DB_RECNO ||
1599 self->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001600 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001601 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001602 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001603
1604 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1605 {
1606 PyObject *keyObj;
1607 int type = _DB_get_type(self);
1608 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001609 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001610 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001611 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001612#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001613 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001614#else
1615 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1616#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001617 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001618 }
1619 else /* return just the pkey and data */
1620 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001621#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001622 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001623#else
1624 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1625#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001626 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001627 Py_DECREF(dataObj);
1628 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001629 free_dbt(&pkey);
1630 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001631 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001632 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001633
1634 RETURN_IF_ERR();
1635 return retval;
1636}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001637#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001638
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001639
1640/* Return size of entry */
1641static PyObject*
1642DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1643{
1644 int err, flags=0;
1645 PyObject* txnobj = NULL;
1646 PyObject* keyobj;
1647 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001648 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649 DBT key, data;
1650 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001651 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652
1653 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1654 &keyobj, &txnobj))
1655 return NULL;
1656 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001657 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001659 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001660 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001662 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663 CLEAR_DBT(data);
1664
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001665 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1666 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001667 data.flags = DB_DBT_USERMEM;
1668 data.ulen = 0;
1669 MYDB_BEGIN_ALLOW_THREADS;
1670 err = self->db->get(self->db, txn, &key, &data, flags);
1671 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001672 if (err == DB_BUFFER_SMALL) {
Christian Heimes217cfd12007-12-02 14:31:20 +00001673 retval = PyLong_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001674 err = 0;
1675 }
1676
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001677 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1678 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001679 RETURN_IF_ERR();
1680 return retval;
1681}
1682
1683
1684static PyObject*
1685DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1686{
1687 int err, flags=0;
1688 PyObject* txnobj = NULL;
1689 PyObject* keyobj;
1690 PyObject* dataobj;
1691 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001692 Py_buffer* data_buf_view = NULL;
1693 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001694 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001695 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001697 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001698
1699
1700 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1701 &keyobj, &dataobj, &txnobj, &flags))
1702 return NULL;
1703
1704 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001705 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001707 if ( !checkTxnObj(txnobj, &txn) ||
1708 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001709 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001710 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001711 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001712 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713
1714 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001715 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001716
1717 if (CHECK_DBFLAG(self, DB_THREAD)) {
1718 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001719 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001720 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721 }
1722
1723 MYDB_BEGIN_ALLOW_THREADS;
1724 err = self->db->get(self->db, txn, &key, &data, flags);
1725 MYDB_END_ALLOW_THREADS;
1726
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001727 free_buf_view(dataobj, data_buf_view);
1728
Gregory P. Smithe9477062005-06-04 06:46:59 +00001729 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1730 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001731 err = 0;
1732 Py_INCREF(Py_None);
1733 retval = Py_None;
1734 }
1735 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001736 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001737 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001738 /* XXX(guido) But what if the input is PyString? */
1739 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001740
1741 /* Even though the flags require DB_DBT_MALLOC, data is not always
1742 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1743 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001744 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 }
1746
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001747 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001748 RETURN_IF_ERR();
1749 return retval;
1750}
1751
1752
1753static PyObject*
1754DB_get_byteswapped(DBObject* self, PyObject* args)
1755{
1756#if (DBVER >= 33)
1757 int err = 0;
1758#endif
1759 int retval = -1;
1760
1761 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1762 return NULL;
1763 CHECK_DB_NOT_CLOSED(self);
1764
1765#if (DBVER >= 33)
1766 MYDB_BEGIN_ALLOW_THREADS;
1767 err = self->db->get_byteswapped(self->db, &retval);
1768 MYDB_END_ALLOW_THREADS;
1769 RETURN_IF_ERR();
1770#else
1771 MYDB_BEGIN_ALLOW_THREADS;
1772 retval = self->db->get_byteswapped(self->db);
1773 MYDB_END_ALLOW_THREADS;
1774#endif
Christian Heimes217cfd12007-12-02 14:31:20 +00001775 return PyLong_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001776}
1777
1778
1779static PyObject*
1780DB_get_type(DBObject* self, PyObject* args)
1781{
1782 int type;
1783
1784 if (!PyArg_ParseTuple(args,":get_type"))
1785 return NULL;
1786 CHECK_DB_NOT_CLOSED(self);
1787
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001788 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001789 if (type == -1)
1790 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00001791 return PyLong_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001792}
1793
1794
1795static PyObject*
1796DB_join(DBObject* self, PyObject* args)
1797{
1798 int err, flags=0;
1799 int length, x;
1800 PyObject* cursorsObj;
1801 DBC** cursors;
1802 DBC* dbc;
1803
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001804 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1805 return NULL;
1806
1807 CHECK_DB_NOT_CLOSED(self);
1808
1809 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001810 PyErr_SetString(PyExc_TypeError,
1811 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001812 return NULL;
1813 }
1814
1815 length = PyObject_Length(cursorsObj);
1816 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001817 if (!cursors) {
1818 PyErr_NoMemory();
1819 return NULL;
1820 }
1821
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001822 cursors[length] = NULL;
1823 for (x=0; x<length; x++) {
1824 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001825 if (item == NULL) {
1826 free(cursors);
1827 return NULL;
1828 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001830 PyErr_SetString(PyExc_TypeError,
1831 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001832 free(cursors);
1833 return NULL;
1834 }
1835 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001836 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001837 }
1838
1839 MYDB_BEGIN_ALLOW_THREADS;
1840 err = self->db->join(self->db, cursors, &dbc, flags);
1841 MYDB_END_ALLOW_THREADS;
1842 free(cursors);
1843 RETURN_IF_ERR();
1844
Gregory P. Smith7441e652003-11-03 21:35:31 +00001845 /* FIXME: this is a buggy interface. The returned cursor
1846 contains internal references to the passed in cursors
1847 but does not hold python references to them or prevent
1848 them from being closed prematurely. This can cause
1849 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850 return (PyObject*) newDBCursorObject(dbc, self);
1851}
1852
1853
1854static PyObject*
1855DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1856{
1857 int err, flags=0;
1858 PyObject* txnobj = NULL;
1859 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001860 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 DBT key;
1862 DB_TXN *txn = NULL;
1863 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001864 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865
1866 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1867 &keyobj, &txnobj, &flags))
1868 return NULL;
1869 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001870 if (!checkTxnObj(txnobj, &txn))
1871 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001872 if (!make_dbt(keyobj, &key, &key_buf_view))
1873 /* BTree only, don't need to allow for an int key */
1874 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001875
1876 MYDB_BEGIN_ALLOW_THREADS;
1877 err = self->db->key_range(self->db, txn, &key, &range, flags);
1878 MYDB_END_ALLOW_THREADS;
1879
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001880 free_buf_view(keyobj, key_buf_view);
1881
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001882 RETURN_IF_ERR();
1883 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1884}
1885
1886
1887static PyObject*
1888DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1889{
1890 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1891 char* filename = NULL;
1892 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001893#if (DBVER >= 41)
1894 PyObject *txnobj = NULL;
1895 DB_TXN *txn = NULL;
1896 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001897 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001898 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1899 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001900 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001901 "filename", "dbtype", "flags", "mode", "txn", NULL};
1902#else
1903 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001904 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001905 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1906 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001907 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001908 "filename", "dbtype", "flags", "mode", NULL};
1909#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001910
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001911#if (DBVER >= 41)
1912 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1913 &filename, &dbname, &type, &flags, &mode,
1914 &txnobj))
1915#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001917 &filename, &dbname, &type, &flags,
1918 &mode))
1919#endif
1920 {
1921 PyErr_Clear();
1922 type = DB_UNKNOWN; flags = 0; mode = 0660;
1923 filename = NULL; dbname = NULL;
1924#if (DBVER >= 41)
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1926 kwnames_basic,
1927 &filename, &type, &flags, &mode,
1928 &txnobj))
1929 return NULL;
1930#else
1931 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1932 kwnames_basic,
1933 &filename, &type, &flags, &mode))
1934 return NULL;
1935#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936 }
1937
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001938#if (DBVER >= 41)
1939 if (!checkTxnObj(txnobj, &txn)) return NULL;
1940#endif
1941
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001942 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001943 PyObject *t = Py_BuildValue("(is)", 0,
1944 "Cannot call open() twice for DB object");
1945 PyErr_SetObject(DBError, t);
1946 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 return NULL;
1948 }
1949
1950 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001951#if (DBVER >= 41)
1952 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1953#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001955#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956 MYDB_END_ALLOW_THREADS;
1957 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001958 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001959 self->db = NULL;
1960 return NULL;
1961 }
1962
Guido van Rossum77677112007-11-05 19:43:04 +00001963#if (DBVER >= 42)
1964 self->db->get_flags(self->db, &self->setflags);
1965#endif
1966
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 self->flags = flags;
1968 RETURN_NONE();
1969}
1970
1971
1972static PyObject*
1973DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1974{
1975 int flags=0;
1976 PyObject* txnobj = NULL;
1977 int dlen = -1;
1978 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001979 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001980 Py_buffer *data_buf_view = NULL;
1981 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001982 DBT key, data;
1983 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001984 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001985 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001986
1987 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1988 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1989 return NULL;
1990
1991 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001992 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001993 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001994 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001995 !add_partial_dbt(&data, dlen, doff) ||
1996 !checkTxnObj(txnobj, &txn) )
1997 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001998 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1999 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002000 return NULL;
2001 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002002
2003 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002004 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2005 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002006 return NULL;
2007 }
2008
2009 if (flags & DB_APPEND)
Christian Heimes217cfd12007-12-02 14:31:20 +00002010 retval = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 else {
2012 retval = Py_None;
2013 Py_INCREF(retval);
2014 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002015 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2016 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002017 return retval;
2018}
2019
2020
2021
2022static PyObject*
2023DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2024{
2025 char* filename;
2026 char* database = NULL;
2027 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002028 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002029
2030 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2031 &filename, &database, &flags))
2032 return NULL;
2033 CHECK_DB_NOT_CLOSED(self);
2034
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002036 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002037 RETURN_IF_ERR();
2038 RETURN_NONE();
2039}
2040
2041
2042
2043static PyObject*
2044DB_rename(DBObject* self, PyObject* args)
2045{
2046 char* filename;
2047 char* database;
2048 char* newname;
2049 int err, flags=0;
2050
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002051 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2052 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 return NULL;
2054 CHECK_DB_NOT_CLOSED(self);
2055
2056 MYDB_BEGIN_ALLOW_THREADS;
2057 err = self->db->rename(self->db, filename, database, newname, flags);
2058 MYDB_END_ALLOW_THREADS;
2059 RETURN_IF_ERR();
2060 RETURN_NONE();
2061}
2062
2063
2064static PyObject*
2065DB_set_bt_minkey(DBObject* self, PyObject* args)
2066{
2067 int err, minkey;
2068
2069 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2070 return NULL;
2071 CHECK_DB_NOT_CLOSED(self);
2072
2073 MYDB_BEGIN_ALLOW_THREADS;
2074 err = self->db->set_bt_minkey(self->db, minkey);
2075 MYDB_END_ALLOW_THREADS;
2076 RETURN_IF_ERR();
2077 RETURN_NONE();
2078}
2079
Neal Norwitz84562352005-10-20 04:30:15 +00002080#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002082_default_cmp(const DBT *leftKey,
2083 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002084{
2085 int res;
2086 int lsize = leftKey->size, rsize = rightKey->size;
2087
Georg Brandlef1701f2006-03-07 14:57:48 +00002088 res = memcmp(leftKey->data, rightKey->data,
2089 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002090
2091 if (res == 0) {
2092 if (lsize < rsize) {
2093 res = -1;
2094 }
2095 else if (lsize > rsize) {
2096 res = 1;
2097 }
2098 }
2099 return res;
2100}
2101
2102static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002103_db_compareCallback(DB* db,
2104 const DBT *leftKey,
2105 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002106{
2107 int res = 0;
2108 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002109 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002110 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002111
2112 if (self == NULL || self->btCompareCallback == NULL) {
2113 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002114 PyErr_SetString(PyExc_TypeError,
2115 (self == 0
2116 ? "DB_bt_compare db is NULL."
2117 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002118 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002119 PyErr_Print();
2120 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002121 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002122 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002123 MYDB_BEGIN_BLOCK_THREADS;
2124
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002125 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002126 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002128 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002133 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 PyErr_Print();
2135 res = _default_cmp(leftKey, rightKey);
Christian Heimes217cfd12007-12-02 14:31:20 +00002136 } else if (PyLong_Check(result)) {
2137 res = PyLong_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002138 } else {
2139 PyErr_SetString(PyExc_TypeError,
2140 "DB_bt_compare callback MUST return an int.");
2141 /* we're in a callback within the DB code, we can't raise */
2142 PyErr_Print();
2143 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002144 }
2145
Thomas Woutersb3153832006-03-08 01:47:19 +00002146 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002148
2149 MYDB_END_BLOCK_THREADS;
2150 }
2151 return res;
2152}
2153
2154static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002155DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002156{
2157 int err;
2158 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002159 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160
Georg Brandlef1701f2006-03-07 14:57:48 +00002161 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162 return NULL;
2163
Georg Brandlef1701f2006-03-07 14:57:48 +00002164 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002165
Georg Brandlef1701f2006-03-07 14:57:48 +00002166 if (!PyCallable_Check(comparator)) {
2167 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002168 return NULL;
2169 }
2170
2171 /*
2172 * Perform a test call of the comparator function with two empty
2173 * string objects here. verify that it returns an int (0).
2174 * err if not.
2175 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002176 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002177 result = PyEval_CallObject(comparator, tuple);
2178 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002179 if (result == NULL)
2180 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002181 if (!PyLong_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 PyErr_SetString(PyExc_TypeError,
2183 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002185 } else if (PyLong_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 PyErr_SetString(PyExc_TypeError,
2187 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188 return NULL;
2189 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002190 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002191
2192 /* We don't accept multiple set_bt_compare operations, in order to
2193 * simplify the code. This would have no real use, as one cannot
2194 * change the function once the db is opened anyway */
2195 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002196 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002197 return NULL;
2198 }
2199
Georg Brandlef1701f2006-03-07 14:57:48 +00002200 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002201 self->btCompareCallback = comparator;
2202
2203 /* This is to workaround a problem with un-initialized threads (see
2204 comment in DB_associate) */
2205#ifdef WITH_THREAD
2206 PyEval_InitThreads();
2207#endif
2208
Thomas Woutersb3153832006-03-08 01:47:19 +00002209 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002210
2211 if (err) {
2212 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002213 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002214 self->btCompareCallback = NULL;
2215 }
2216
Georg Brandlef1701f2006-03-07 14:57:48 +00002217 RETURN_IF_ERR();
2218 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219}
Neal Norwitz84562352005-10-20 04:30:15 +00002220#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002221
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002222
2223static PyObject*
2224DB_set_cachesize(DBObject* self, PyObject* args)
2225{
2226 int err;
2227 int gbytes = 0, bytes = 0, ncache = 0;
2228
2229 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2230 &gbytes,&bytes,&ncache))
2231 return NULL;
2232 CHECK_DB_NOT_CLOSED(self);
2233
2234 MYDB_BEGIN_ALLOW_THREADS;
2235 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2236 MYDB_END_ALLOW_THREADS;
2237 RETURN_IF_ERR();
2238 RETURN_NONE();
2239}
2240
2241
2242static PyObject*
2243DB_set_flags(DBObject* self, PyObject* args)
2244{
2245 int err, flags;
2246
2247 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2248 return NULL;
2249 CHECK_DB_NOT_CLOSED(self);
2250
2251 MYDB_BEGIN_ALLOW_THREADS;
2252 err = self->db->set_flags(self->db, flags);
2253 MYDB_END_ALLOW_THREADS;
2254 RETURN_IF_ERR();
2255
2256 self->setflags |= flags;
2257 RETURN_NONE();
2258}
2259
2260
2261static PyObject*
2262DB_set_h_ffactor(DBObject* self, PyObject* args)
2263{
2264 int err, ffactor;
2265
2266 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2267 return NULL;
2268 CHECK_DB_NOT_CLOSED(self);
2269
2270 MYDB_BEGIN_ALLOW_THREADS;
2271 err = self->db->set_h_ffactor(self->db, ffactor);
2272 MYDB_END_ALLOW_THREADS;
2273 RETURN_IF_ERR();
2274 RETURN_NONE();
2275}
2276
2277
2278static PyObject*
2279DB_set_h_nelem(DBObject* self, PyObject* args)
2280{
2281 int err, nelem;
2282
2283 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2284 return NULL;
2285 CHECK_DB_NOT_CLOSED(self);
2286
2287 MYDB_BEGIN_ALLOW_THREADS;
2288 err = self->db->set_h_nelem(self->db, nelem);
2289 MYDB_END_ALLOW_THREADS;
2290 RETURN_IF_ERR();
2291 RETURN_NONE();
2292}
2293
2294
2295static PyObject*
2296DB_set_lorder(DBObject* self, PyObject* args)
2297{
2298 int err, lorder;
2299
2300 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2301 return NULL;
2302 CHECK_DB_NOT_CLOSED(self);
2303
2304 MYDB_BEGIN_ALLOW_THREADS;
2305 err = self->db->set_lorder(self->db, lorder);
2306 MYDB_END_ALLOW_THREADS;
2307 RETURN_IF_ERR();
2308 RETURN_NONE();
2309}
2310
2311
2312static PyObject*
2313DB_set_pagesize(DBObject* self, PyObject* args)
2314{
2315 int err, pagesize;
2316
2317 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2318 return NULL;
2319 CHECK_DB_NOT_CLOSED(self);
2320
2321 MYDB_BEGIN_ALLOW_THREADS;
2322 err = self->db->set_pagesize(self->db, pagesize);
2323 MYDB_END_ALLOW_THREADS;
2324 RETURN_IF_ERR();
2325 RETURN_NONE();
2326}
2327
2328
2329static PyObject*
2330DB_set_re_delim(DBObject* self, PyObject* args)
2331{
2332 int err;
2333 char delim;
2334
2335 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2336 PyErr_Clear();
2337 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2338 return NULL;
2339 }
2340
2341 CHECK_DB_NOT_CLOSED(self);
2342
2343 MYDB_BEGIN_ALLOW_THREADS;
2344 err = self->db->set_re_delim(self->db, delim);
2345 MYDB_END_ALLOW_THREADS;
2346 RETURN_IF_ERR();
2347 RETURN_NONE();
2348}
2349
2350static PyObject*
2351DB_set_re_len(DBObject* self, PyObject* args)
2352{
2353 int err, len;
2354
2355 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2356 return NULL;
2357 CHECK_DB_NOT_CLOSED(self);
2358
2359 MYDB_BEGIN_ALLOW_THREADS;
2360 err = self->db->set_re_len(self->db, len);
2361 MYDB_END_ALLOW_THREADS;
2362 RETURN_IF_ERR();
2363 RETURN_NONE();
2364}
2365
2366
2367static PyObject*
2368DB_set_re_pad(DBObject* self, PyObject* args)
2369{
2370 int err;
2371 char pad;
2372
2373 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2374 PyErr_Clear();
2375 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2376 return NULL;
2377 }
2378 CHECK_DB_NOT_CLOSED(self);
2379
2380 MYDB_BEGIN_ALLOW_THREADS;
2381 err = self->db->set_re_pad(self->db, pad);
2382 MYDB_END_ALLOW_THREADS;
2383 RETURN_IF_ERR();
2384 RETURN_NONE();
2385}
2386
2387
2388static PyObject*
2389DB_set_re_source(DBObject* self, PyObject* args)
2390{
2391 int err;
2392 char *re_source;
2393
2394 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2395 return NULL;
2396 CHECK_DB_NOT_CLOSED(self);
2397
2398 MYDB_BEGIN_ALLOW_THREADS;
2399 err = self->db->set_re_source(self->db, re_source);
2400 MYDB_END_ALLOW_THREADS;
2401 RETURN_IF_ERR();
2402 RETURN_NONE();
2403}
2404
2405
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002406static PyObject*
2407DB_set_q_extentsize(DBObject* self, PyObject* args)
2408{
2409 int err;
2410 int extentsize;
2411
2412 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2413 return NULL;
2414 CHECK_DB_NOT_CLOSED(self);
2415
2416 MYDB_BEGIN_ALLOW_THREADS;
2417 err = self->db->set_q_extentsize(self->db, extentsize);
2418 MYDB_END_ALLOW_THREADS;
2419 RETURN_IF_ERR();
2420 RETURN_NONE();
2421}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002422
2423static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002424DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002425{
2426 int err, flags = 0, type;
2427 void* sp;
2428 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002429#if (DBVER >= 43)
2430 PyObject* txnobj = NULL;
2431 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002432 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002433#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002434 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002436
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002437#if (DBVER >= 43)
2438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2439 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002440 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002441 if (!checkTxnObj(txnobj, &txn))
2442 return NULL;
2443#else
2444 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2445 return NULL;
2446#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002447 CHECK_DB_NOT_CLOSED(self);
2448
2449 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002450#if (DBVER >= 43)
2451 err = self->db->stat(self->db, txn, &sp, flags);
2452#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002453 err = self->db->stat(self->db, &sp, flags);
2454#else
2455 err = self->db->stat(self->db, &sp, NULL, flags);
2456#endif
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459
2460 self->haveStat = 1;
2461
2462 /* Turn the stat structure into a dictionary */
2463 type = _DB_get_type(self);
2464 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2465 free(sp);
2466 return NULL;
2467 }
2468
2469#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2470#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2471#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2472
2473 switch (type) {
2474 case DB_HASH:
2475 MAKE_HASH_ENTRY(magic);
2476 MAKE_HASH_ENTRY(version);
2477 MAKE_HASH_ENTRY(nkeys);
2478 MAKE_HASH_ENTRY(ndata);
2479 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002480#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002481 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002482#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002483 MAKE_HASH_ENTRY(ffactor);
2484 MAKE_HASH_ENTRY(buckets);
2485 MAKE_HASH_ENTRY(free);
2486 MAKE_HASH_ENTRY(bfree);
2487 MAKE_HASH_ENTRY(bigpages);
2488 MAKE_HASH_ENTRY(big_bfree);
2489 MAKE_HASH_ENTRY(overflows);
2490 MAKE_HASH_ENTRY(ovfl_free);
2491 MAKE_HASH_ENTRY(dup);
2492 MAKE_HASH_ENTRY(dup_free);
2493 break;
2494
2495 case DB_BTREE:
2496 case DB_RECNO:
2497 MAKE_BT_ENTRY(magic);
2498 MAKE_BT_ENTRY(version);
2499 MAKE_BT_ENTRY(nkeys);
2500 MAKE_BT_ENTRY(ndata);
2501 MAKE_BT_ENTRY(pagesize);
2502 MAKE_BT_ENTRY(minkey);
2503 MAKE_BT_ENTRY(re_len);
2504 MAKE_BT_ENTRY(re_pad);
2505 MAKE_BT_ENTRY(levels);
2506 MAKE_BT_ENTRY(int_pg);
2507 MAKE_BT_ENTRY(leaf_pg);
2508 MAKE_BT_ENTRY(dup_pg);
2509 MAKE_BT_ENTRY(over_pg);
2510 MAKE_BT_ENTRY(free);
2511 MAKE_BT_ENTRY(int_pgfree);
2512 MAKE_BT_ENTRY(leaf_pgfree);
2513 MAKE_BT_ENTRY(dup_pgfree);
2514 MAKE_BT_ENTRY(over_pgfree);
2515 break;
2516
2517 case DB_QUEUE:
2518 MAKE_QUEUE_ENTRY(magic);
2519 MAKE_QUEUE_ENTRY(version);
2520 MAKE_QUEUE_ENTRY(nkeys);
2521 MAKE_QUEUE_ENTRY(ndata);
2522 MAKE_QUEUE_ENTRY(pagesize);
2523 MAKE_QUEUE_ENTRY(pages);
2524 MAKE_QUEUE_ENTRY(re_len);
2525 MAKE_QUEUE_ENTRY(re_pad);
2526 MAKE_QUEUE_ENTRY(pgfree);
2527#if (DBVER == 31)
2528 MAKE_QUEUE_ENTRY(start);
2529#endif
2530 MAKE_QUEUE_ENTRY(first_recno);
2531 MAKE_QUEUE_ENTRY(cur_recno);
2532 break;
2533
2534 default:
2535 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2536 Py_DECREF(d);
2537 d = NULL;
2538 }
2539
2540#undef MAKE_HASH_ENTRY
2541#undef MAKE_BT_ENTRY
2542#undef MAKE_QUEUE_ENTRY
2543
2544 free(sp);
2545 return d;
2546}
2547
2548static PyObject*
2549DB_sync(DBObject* self, PyObject* args)
2550{
2551 int err;
2552 int flags = 0;
2553
2554 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2555 return NULL;
2556 CHECK_DB_NOT_CLOSED(self);
2557
2558 MYDB_BEGIN_ALLOW_THREADS;
2559 err = self->db->sync(self->db, flags);
2560 MYDB_END_ALLOW_THREADS;
2561 RETURN_IF_ERR();
2562 RETURN_NONE();
2563}
2564
2565
2566#if (DBVER >= 33)
2567static PyObject*
2568DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2569{
2570 int err, flags=0;
2571 u_int32_t count=0;
2572 PyObject* txnobj = NULL;
2573 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002574 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002575
2576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2577 &txnobj, &flags))
2578 return NULL;
2579 CHECK_DB_NOT_CLOSED(self);
2580 if (!checkTxnObj(txnobj, &txn))
2581 return NULL;
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
2584 err = self->db->truncate(self->db, txn, &count, flags);
2585 MYDB_END_ALLOW_THREADS;
2586 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00002587 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002588}
2589#endif
2590
2591
2592static PyObject*
2593DB_upgrade(DBObject* self, PyObject* args)
2594{
2595 int err, flags=0;
2596 char *filename;
2597
2598 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2599 return NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601
2602 MYDB_BEGIN_ALLOW_THREADS;
2603 err = self->db->upgrade(self->db, filename, flags);
2604 MYDB_END_ALLOW_THREADS;
2605 RETURN_IF_ERR();
2606 RETURN_NONE();
2607}
2608
2609
2610static PyObject*
2611DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2612{
2613 int err, flags=0;
2614 char* fileName;
2615 char* dbName=NULL;
2616 char* outFileName=NULL;
2617 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002618 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002619 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002620
2621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2622 &fileName, &dbName, &outFileName, &flags))
2623 return NULL;
2624
2625 CHECK_DB_NOT_CLOSED(self);
2626 if (outFileName)
2627 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002628 /* XXX(nnorwitz): it should probably be an exception if outFile
2629 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002630
2631 MYDB_BEGIN_ALLOW_THREADS;
2632 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2633 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002634 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002635 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002636
2637 /* DB.verify acts as a DB handle destructor (like close); this was
2638 * documented in BerkeleyDB 4.2 but had the undocumented effect
2639 * of not being safe in prior versions while still requiring an explicit
2640 * DB.close call afterwards. Lets call close for the user to emulate
2641 * the safe 4.2 behaviour. */
2642#if (DBVER <= 41)
2643 self->db->close(self->db, 0);
2644#endif
2645 self->db = NULL;
2646
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002647 RETURN_IF_ERR();
2648 RETURN_NONE();
2649}
2650
2651
2652static PyObject*
2653DB_set_get_returns_none(DBObject* self, PyObject* args)
2654{
2655 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002656 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002657
2658 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2659 return NULL;
2660 CHECK_DB_NOT_CLOSED(self);
2661
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002662 if (self->moduleFlags.getReturnsNone)
2663 ++oldValue;
2664 if (self->moduleFlags.cursorSetReturnsNone)
2665 ++oldValue;
2666 self->moduleFlags.getReturnsNone = (flags >= 1);
2667 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00002668 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002669}
2670
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002671#if (DBVER >= 41)
2672static PyObject*
2673DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2674{
2675 int err;
2676 u_int32_t flags=0;
2677 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002678 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002679
2680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2681 &passwd, &flags)) {
2682 return NULL;
2683 }
2684
2685 MYDB_BEGIN_ALLOW_THREADS;
2686 err = self->db->set_encrypt(self->db, passwd, flags);
2687 MYDB_END_ALLOW_THREADS;
2688
2689 RETURN_IF_ERR();
2690 RETURN_NONE();
2691}
2692#endif /* DBVER >= 41 */
2693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002694
2695/*-------------------------------------------------------------- */
2696/* Mapping and Dictionary-like access routines */
2697
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002698Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699{
2700 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002701 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 int flags = 0;
2703 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002704 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002705
2706 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002707 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2708 PyErr_SetObject(DBError, t);
2709 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710 return -1;
2711 }
2712
2713 if (self->haveStat) { /* Has the stat function been called recently? If
2714 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002715 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002716 }
2717
2718 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002719redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002720#if (DBVER >= 43)
2721 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2722#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002723 err = self->db->stat(self->db, &sp, flags);
2724#else
2725 err = self->db->stat(self->db, &sp, NULL, flags);
2726#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002727
2728 /* All the stat structures have matching fields upto the ndata field,
2729 so we can use any of them for the type cast */
2730 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2731
2732 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2733 * redo a full stat to make sure.
2734 * Fixes SF python bug 1493322, pybsddb bug 1184012
2735 */
2736 if (size == 0 && (flags & DB_FAST_STAT)) {
2737 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002738 if (!err)
2739 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002740 goto redo_stat_for_length;
2741 }
2742
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002743 MYDB_END_ALLOW_THREADS;
2744
2745 if (err)
2746 return -1;
2747
2748 self->haveStat = 1;
2749
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750 free(sp);
2751 return size;
2752}
2753
2754
2755PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2756{
2757 int err;
2758 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002759 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002760 DBT key;
2761 DBT data;
2762
2763 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002764 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002765 return NULL;
2766
2767 CLEAR_DBT(data);
2768 if (CHECK_DBFLAG(self, DB_THREAD)) {
2769 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2770 data.flags = DB_DBT_MALLOC;
2771 }
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->get(self->db, NULL, &key, &data, 0);
2774 MYDB_END_ALLOW_THREADS;
2775 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2776 PyErr_SetObject(PyExc_KeyError, keyobj);
2777 retval = NULL;
2778 }
2779 else if (makeDBError(err)) {
2780 retval = NULL;
2781 }
2782 else {
Guido van Rossum98297ee2007-11-06 21:34:58 +00002783 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002784 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002785 }
2786
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002787 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788 return retval;
2789}
2790
2791
2792static int
2793DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2794{
2795 DBT key, data;
2796 int retval;
2797 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002798 Py_buffer *data_buf_view = NULL;
2799 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002800
2801 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002802 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2803 PyErr_SetObject(DBError, t);
2804 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002805 return -1;
2806 }
2807
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002808 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002809 return -1;
2810
2811 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002812 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 retval = -1;
2814 else {
2815 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002816 /* dictionaries shouldn't have duplicate keys */
2817 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002818 retval = _DB_put(self, NULL, &key, &data, flags);
2819
2820 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002821 /* try deleting any old record that matches and then PUT it
2822 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002823 _DB_delete(self, NULL, &key, 0);
2824 PyErr_Clear();
2825 retval = _DB_put(self, NULL, &key, &data, flags);
2826 }
2827 }
2828 }
2829 else {
2830 /* dataobj == NULL, so delete the key */
2831 retval = _DB_delete(self, NULL, &key, 0);
2832 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002833 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2834 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 return retval;
2836}
2837
2838
2839static PyObject*
2840DB_has_key(DBObject* self, PyObject* args)
2841{
2842 int err;
2843 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002844 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002845 DBT key, data;
2846 PyObject* txnobj = NULL;
2847 DB_TXN *txn = NULL;
2848
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002849 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 return NULL;
2851 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002852 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002854 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002855 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002856 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002857 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002859 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860 it has a record but can't allocate a buffer for the data. This saves
2861 having to deal with data we won't be using.
2862 */
2863 CLEAR_DBT(data);
2864 data.flags = DB_DBT_USERMEM;
2865
2866 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002867 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002869 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002870
2871 if (err == DB_BUFFER_SMALL || err == 0) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002872 return PyLong_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002873 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002874 return PyLong_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002875 }
2876
2877 makeDBError(err);
2878 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879}
2880
2881
2882#define _KEYS_LIST 1
2883#define _VALUES_LIST 2
2884#define _ITEMS_LIST 3
2885
2886static PyObject*
2887_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2888{
2889 int err, dbtype;
2890 DBT key;
2891 DBT data;
2892 DBC *cursor;
2893 PyObject* list;
2894 PyObject* item = NULL;
2895
2896 CHECK_DB_NOT_CLOSED(self);
2897 CLEAR_DBT(key);
2898 CLEAR_DBT(data);
2899
2900 dbtype = _DB_get_type(self);
2901 if (dbtype == -1)
2902 return NULL;
2903
2904 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002905 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907
2908 /* get a cursor */
2909 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002910 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002911 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002912 if (makeDBError(err)) {
2913 Py_DECREF(list);
2914 return NULL;
2915 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002916
2917 if (CHECK_DBFLAG(self, DB_THREAD)) {
2918 key.flags = DB_DBT_REALLOC;
2919 data.flags = DB_DBT_REALLOC;
2920 }
2921
2922 while (1) { /* use the cursor to traverse the DB, collecting items */
2923 MYDB_BEGIN_ALLOW_THREADS;
2924 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2925 MYDB_END_ALLOW_THREADS;
2926
2927 if (err) {
2928 /* for any error, break out of the loop */
2929 break;
2930 }
2931
2932 switch (type) {
2933 case _KEYS_LIST:
2934 switch(dbtype) {
2935 case DB_BTREE:
2936 case DB_HASH:
2937 default:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002938 item = PyString_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 break;
2940 case DB_RECNO:
2941 case DB_QUEUE:
Christian Heimes217cfd12007-12-02 14:31:20 +00002942 item = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002943 break;
2944 }
2945 break;
2946
2947 case _VALUES_LIST:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002948 item = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002949 break;
2950
2951 case _ITEMS_LIST:
2952 switch(dbtype) {
2953 case DB_BTREE:
2954 case DB_HASH:
2955 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002956 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002957 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002958 break;
2959 case DB_RECNO:
2960 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002961 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002962 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 break;
2964 }
2965 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002966 default:
2967 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2968 item = NULL;
2969 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002970 }
2971 if (item == NULL) {
2972 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002973 list = NULL;
2974 goto done;
2975 }
2976 PyList_Append(list, item);
2977 Py_DECREF(item);
2978 }
2979
Gregory P. Smithe9477062005-06-04 06:46:59 +00002980 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2981 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 Py_DECREF(list);
2983 list = NULL;
2984 }
2985
2986 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002987 free_dbt(&key);
2988 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002989 MYDB_BEGIN_ALLOW_THREADS;
2990 cursor->c_close(cursor);
2991 MYDB_END_ALLOW_THREADS;
2992 return list;
2993}
2994
2995
2996static PyObject*
2997DB_keys(DBObject* self, PyObject* args)
2998{
2999 PyObject* txnobj = NULL;
3000 DB_TXN *txn = NULL;
3001
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003002 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003003 return NULL;
3004 if (!checkTxnObj(txnobj, &txn))
3005 return NULL;
3006 return _DB_make_list(self, txn, _KEYS_LIST);
3007}
3008
3009
3010static PyObject*
3011DB_items(DBObject* self, PyObject* args)
3012{
3013 PyObject* txnobj = NULL;
3014 DB_TXN *txn = NULL;
3015
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003016 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003017 return NULL;
3018 if (!checkTxnObj(txnobj, &txn))
3019 return NULL;
3020 return _DB_make_list(self, txn, _ITEMS_LIST);
3021}
3022
3023
3024static PyObject*
3025DB_values(DBObject* self, PyObject* args)
3026{
3027 PyObject* txnobj = NULL;
3028 DB_TXN *txn = NULL;
3029
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003030 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031 return NULL;
3032 if (!checkTxnObj(txnobj, &txn))
3033 return NULL;
3034 return _DB_make_list(self, txn, _VALUES_LIST);
3035}
3036
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003037/* --------------------------------------------------------------------- */
3038/* DBCursor methods */
3039
3040
3041static PyObject*
3042DBC_close(DBCursorObject* self, PyObject* args)
3043{
3044 int err = 0;
3045
3046 if (!PyArg_ParseTuple(args, ":close"))
3047 return NULL;
3048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003049 if (self->dbc != NULL) {
3050 MYDB_BEGIN_ALLOW_THREADS;
3051 err = self->dbc->c_close(self->dbc);
3052 self->dbc = NULL;
3053 MYDB_END_ALLOW_THREADS;
3054 }
3055 RETURN_IF_ERR();
3056 RETURN_NONE();
3057}
3058
3059
3060static PyObject*
3061DBC_count(DBCursorObject* self, PyObject* args)
3062{
3063 int err = 0;
3064 db_recno_t count;
3065 int flags = 0;
3066
3067 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3068 return NULL;
3069
3070 CHECK_CURSOR_NOT_CLOSED(self);
3071
3072 MYDB_BEGIN_ALLOW_THREADS;
3073 err = self->dbc->c_count(self->dbc, &count, flags);
3074 MYDB_END_ALLOW_THREADS;
3075 RETURN_IF_ERR();
3076
Christian Heimes217cfd12007-12-02 14:31:20 +00003077 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003078}
3079
3080
3081static PyObject*
3082DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3083{
3084 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3085}
3086
3087
3088static PyObject*
3089DBC_delete(DBCursorObject* self, PyObject* args)
3090{
3091 int err, flags=0;
3092
3093 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3094 return NULL;
3095
3096 CHECK_CURSOR_NOT_CLOSED(self);
3097
3098 MYDB_BEGIN_ALLOW_THREADS;
3099 err = self->dbc->c_del(self->dbc, flags);
3100 MYDB_END_ALLOW_THREADS;
3101 RETURN_IF_ERR();
3102
3103 self->mydb->haveStat = 0;
3104 RETURN_NONE();
3105}
3106
3107
3108static PyObject*
3109DBC_dup(DBCursorObject* self, PyObject* args)
3110{
3111 int err, flags =0;
3112 DBC* dbc = NULL;
3113
3114 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3115 return NULL;
3116
3117 CHECK_CURSOR_NOT_CLOSED(self);
3118
3119 MYDB_BEGIN_ALLOW_THREADS;
3120 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3121 MYDB_END_ALLOW_THREADS;
3122 RETURN_IF_ERR();
3123
3124 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3125}
3126
3127static PyObject*
3128DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3129{
3130 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3131}
3132
3133
3134static PyObject*
3135DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3136{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003137 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003138 PyObject* keyobj = NULL;
3139 PyObject* dataobj = NULL;
3140 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003141 Py_buffer* data_buf_view = NULL;
3142 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003143 int dlen = -1;
3144 int doff = -1;
3145 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003146 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003147 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003148
3149 CLEAR_DBT(key);
3150 CLEAR_DBT(data);
3151 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003152 &flags, &dlen, &doff))
3153 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003154 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003155 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3156 &kwnames[1],
3157 &keyobj, &flags, &dlen, &doff))
3158 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003159 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3161 kwnames, &keyobj, &dataobj,
3162 &flags, &dlen, &doff))
3163 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003164 return NULL;
3165 }
3166 }
3167 }
3168
3169 CHECK_CURSOR_NOT_CLOSED(self);
3170
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003171 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003173 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003174 (!add_partial_dbt(&data, dlen, doff)) )
3175 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003176 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3177 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003178 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003179 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003180
3181 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3182 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003183 if (!(key.flags & DB_DBT_REALLOC)) {
3184 key.flags |= DB_DBT_MALLOC;
3185 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 }
3187
3188 MYDB_BEGIN_ALLOW_THREADS;
3189 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3190 MYDB_END_ALLOW_THREADS;
3191
Gregory P. Smithe9477062005-06-04 06:46:59 +00003192 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3193 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194 Py_INCREF(Py_None);
3195 retval = Py_None;
3196 }
3197 else if (makeDBError(err)) {
3198 retval = NULL;
3199 }
3200 else {
3201 switch (_DB_get_type(self->mydb)) {
3202 case -1:
3203 retval = NULL;
3204 break;
3205 case DB_BTREE:
3206 case DB_HASH:
3207 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003208 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003209 data.data, data.size);
3210 break;
3211 case DB_RECNO:
3212 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003213 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003214 data.data, data.size);
3215 break;
3216 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003217 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003219 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3220 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003221 return retval;
3222}
3223
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003224#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003225static PyObject*
3226DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3227{
3228 int err, flags=0;
3229 PyObject* keyobj = NULL;
3230 PyObject* dataobj = NULL;
3231 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003232 Py_buffer* data_buf_view = NULL;
3233 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003234 int dlen = -1;
3235 int doff = -1;
3236 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003237 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3238 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003239
3240 CLEAR_DBT(key);
3241 CLEAR_DBT(data);
3242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3243 &flags, &dlen, &doff))
3244 {
3245 PyErr_Clear();
3246 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003247 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003248 &keyobj, &flags, &dlen, &doff))
3249 {
3250 PyErr_Clear();
3251 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3252 kwnames, &keyobj, &dataobj,
3253 &flags, &dlen, &doff))
3254 {
3255 return NULL;
3256 }
3257 }
3258 }
3259
3260 CHECK_CURSOR_NOT_CLOSED(self);
3261
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003262 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003263 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003264 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003265 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003266 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3267 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003268 return NULL;
3269 }
3270
3271 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3272 data.flags = DB_DBT_MALLOC;
3273 if (!(key.flags & DB_DBT_REALLOC)) {
3274 key.flags |= DB_DBT_MALLOC;
3275 }
3276 }
3277
3278 CLEAR_DBT(pkey);
3279 pkey.flags = DB_DBT_MALLOC;
3280
3281 MYDB_BEGIN_ALLOW_THREADS;
3282 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3283 MYDB_END_ALLOW_THREADS;
3284
Gregory P. Smithe9477062005-06-04 06:46:59 +00003285 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3286 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003287 Py_INCREF(Py_None);
3288 retval = Py_None;
3289 }
3290 else if (makeDBError(err)) {
3291 retval = NULL;
3292 }
3293 else {
3294 PyObject *pkeyObj;
3295 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00003296 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003297
3298 if (self->mydb->primaryDBType == DB_RECNO ||
3299 self->mydb->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003300 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003302 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003303
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003304 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003305 {
3306 PyObject *keyObj;
3307 int type = _DB_get_type(self->mydb);
3308 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003309 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003310 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003311 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003312 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003313 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003314 }
3315 else /* return just the pkey and data */
3316 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003317 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003318 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003319 Py_DECREF(dataObj);
3320 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003321 free_dbt(&pkey);
3322 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003323 }
3324 /* the only time REALLOC should be set is if we used an integer
3325 * key that make_key_dbt malloc'd for us. always free these. */
3326 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003327 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003328 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003329 free_buf_view(keyobj, key_buf_view);
3330 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003331 return retval;
3332}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003333#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003334
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003335
3336static PyObject*
3337DBC_get_recno(DBCursorObject* self, PyObject* args)
3338{
3339 int err;
3340 db_recno_t recno;
3341 DBT key;
3342 DBT data;
3343
3344 if (!PyArg_ParseTuple(args, ":get_recno"))
3345 return NULL;
3346
3347 CHECK_CURSOR_NOT_CLOSED(self);
3348
3349 CLEAR_DBT(key);
3350 CLEAR_DBT(data);
3351 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3353 data.flags = DB_DBT_MALLOC;
3354 key.flags = DB_DBT_MALLOC;
3355 }
3356
3357 MYDB_BEGIN_ALLOW_THREADS;
3358 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3359 MYDB_END_ALLOW_THREADS;
3360 RETURN_IF_ERR();
3361
3362 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003363 free_dbt(&key);
3364 free_dbt(&data);
Christian Heimes217cfd12007-12-02 14:31:20 +00003365 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003366}
3367
3368
3369static PyObject*
3370DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3371{
3372 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3373}
3374
3375
3376static PyObject*
3377DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3378{
3379 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3380}
3381
3382
3383static PyObject*
3384DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3385{
3386 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3387}
3388
3389
3390static PyObject*
3391DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3392{
3393 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003394 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003395 Py_buffer *data_buf_view = NULL;
3396 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003397 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003398 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003399 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003400 int dlen = -1;
3401 int doff = -1;
3402
3403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3404 &keyobj, &dataobj, &flags, &dlen, &doff))
3405 return NULL;
3406
3407 CHECK_CURSOR_NOT_CLOSED(self);
3408
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003409 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003411 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003412 !add_partial_dbt(&data, dlen, doff) )
3413 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003414 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3415 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003416 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003417 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418
3419 MYDB_BEGIN_ALLOW_THREADS;
3420 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3421 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003422 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3423 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003424 RETURN_IF_ERR();
3425 self->mydb->haveStat = 0;
3426 RETURN_NONE();
3427}
3428
3429
3430static PyObject*
3431DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3432{
3433 int err, flags = 0;
3434 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003435 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003436 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003437 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003438 int dlen = -1;
3439 int doff = -1;
3440
3441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3442 &keyobj, &flags, &dlen, &doff))
3443 return NULL;
3444
3445 CHECK_CURSOR_NOT_CLOSED(self);
3446
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003447 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448 return NULL;
3449
3450 CLEAR_DBT(data);
3451 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3452 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3453 data.flags = DB_DBT_MALLOC;
3454 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003455 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003456 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003458 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459
3460 MYDB_BEGIN_ALLOW_THREADS;
3461 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3462 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003463 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3464 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003465 Py_INCREF(Py_None);
3466 retval = Py_None;
3467 }
3468 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 retval = NULL;
3470 }
3471 else {
3472 switch (_DB_get_type(self->mydb)) {
3473 case -1:
3474 retval = NULL;
3475 break;
3476 case DB_BTREE:
3477 case DB_HASH:
3478 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003479 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 data.data, data.size);
3481 break;
3482 case DB_RECNO:
3483 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003484 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003485 data.data, data.size);
3486 break;
3487 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003488 free_dbt(&data);
3489 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003490 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003491 /* the only time REALLOC should be set is if we used an integer
3492 * key that make_key_dbt malloc'd for us. always free these. */
3493 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003494 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003495 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003496 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003497
3498 return retval;
3499}
3500
3501
3502static PyObject*
3503DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3504{
3505 int err, flags = 0;
3506 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003507 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003508 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003509 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003510 int dlen = -1;
3511 int doff = -1;
3512
3513 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3514 &keyobj, &flags, &dlen, &doff))
3515 return NULL;
3516
3517 CHECK_CURSOR_NOT_CLOSED(self);
3518
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003519 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003520 return NULL;
3521
3522 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003523 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003524 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003525 return NULL;
3526 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003527 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3528 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003529 data.flags |= DB_DBT_MALLOC;
3530 /* only BTREE databases will return anything in the key */
3531 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3532 key.flags |= DB_DBT_MALLOC;
3533 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003534 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 MYDB_BEGIN_ALLOW_THREADS;
3536 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3537 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003538 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3539 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003540 Py_INCREF(Py_None);
3541 retval = Py_None;
3542 }
3543 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544 retval = NULL;
3545 }
3546 else {
3547 switch (_DB_get_type(self->mydb)) {
3548 case -1:
3549 retval = NULL;
3550 break;
3551 case DB_BTREE:
3552 case DB_HASH:
3553 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003554 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003555 data.data, data.size);
3556 break;
3557 case DB_RECNO:
3558 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003559 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003560 data.data, data.size);
3561 break;
3562 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003563 free_dbt(&key);
3564 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003566 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003567 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003568 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003569 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003570 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003571 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003572
3573 return retval;
3574}
3575
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003577_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3578 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003580 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003582 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003583 Py_buffer *data_buf_view = NULL;
3584 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585
Gregory P. Smith7441e652003-11-03 21:35:31 +00003586 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003587 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003589 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3590 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003591 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003592 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003593
3594 MYDB_BEGIN_ALLOW_THREADS;
3595 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3596 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003597 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003598 Py_INCREF(Py_None);
3599 retval = Py_None;
3600 }
3601 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602 retval = NULL;
3603 }
3604 else {
3605 switch (_DB_get_type(self->mydb)) {
3606 case -1:
3607 retval = NULL;
3608 break;
3609 case DB_BTREE:
3610 case DB_HASH:
3611 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003612 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613 data.data, data.size);
3614 break;
3615 case DB_RECNO:
3616 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003617 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003618 data.data, data.size);
3619 break;
3620 }
3621 }
3622
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003623 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3624 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003625 return retval;
3626}
3627
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003628static PyObject*
3629DBC_get_both(DBCursorObject* self, PyObject* args)
3630{
3631 int flags=0;
3632 PyObject *keyobj, *dataobj;
3633
3634 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3635 return NULL;
3636
Gregory P. Smith7441e652003-11-03 21:35:31 +00003637 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003638 CHECK_CURSOR_NOT_CLOSED(self);
3639
3640 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3641 self->mydb->moduleFlags.getReturnsNone);
3642}
3643
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003644/* Return size of entry */
3645static PyObject*
3646DBC_get_current_size(DBCursorObject* self, PyObject* args)
3647{
3648 int err, flags=DB_CURRENT;
3649 PyObject* retval = NULL;
3650 DBT key, data;
3651
3652 if (!PyArg_ParseTuple(args, ":get_current_size"))
3653 return NULL;
3654 CHECK_CURSOR_NOT_CLOSED(self);
3655 CLEAR_DBT(key);
3656 CLEAR_DBT(data);
3657
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003658 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003659 getting the record size. */
3660 data.flags = DB_DBT_USERMEM;
3661 data.ulen = 0;
3662 MYDB_BEGIN_ALLOW_THREADS;
3663 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3664 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003665 if (err == DB_BUFFER_SMALL || !err) {
3666 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Christian Heimes217cfd12007-12-02 14:31:20 +00003667 retval = PyLong_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003668 err = 0;
3669 }
3670
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003671 free_dbt(&key);
3672 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003673 RETURN_IF_ERR();
3674 return retval;
3675}
3676
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003677static PyObject*
3678DBC_set_both(DBCursorObject* self, PyObject* args)
3679{
3680 int flags=0;
3681 PyObject *keyobj, *dataobj;
3682
3683 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3684 return NULL;
3685
Gregory P. Smith7441e652003-11-03 21:35:31 +00003686 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003687 CHECK_CURSOR_NOT_CLOSED(self);
3688
3689 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3690 self->mydb->moduleFlags.cursorSetReturnsNone);
3691}
3692
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003693
3694static PyObject*
3695DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3696{
3697 int err, irecno, flags=0;
3698 db_recno_t recno;
3699 DBT key, data;
3700 PyObject* retval;
3701 int dlen = -1;
3702 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003703 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704
3705 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3706 &irecno, &flags, &dlen, &doff))
3707 return NULL;
3708
3709 CHECK_CURSOR_NOT_CLOSED(self);
3710
3711 CLEAR_DBT(key);
3712 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003713 /* use allocated space so DB will be able to realloc room for the real
3714 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003715 key.data = malloc(sizeof(db_recno_t));
3716 if (key.data == NULL) {
3717 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3718 return NULL;
3719 }
3720 key.size = sizeof(db_recno_t);
3721 key.ulen = key.size;
3722 memcpy(key.data, &recno, sizeof(db_recno_t));
3723 key.flags = DB_DBT_REALLOC;
3724
3725 CLEAR_DBT(data);
3726 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3727 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3728 data.flags = DB_DBT_MALLOC;
3729 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003730 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003731 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003733 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003734
3735 MYDB_BEGIN_ALLOW_THREADS;
3736 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3737 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003738 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3739 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003740 Py_INCREF(Py_None);
3741 retval = Py_None;
3742 }
3743 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003744 retval = NULL;
3745 }
3746 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003747 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003748 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003749 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003751 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003752
3753 return retval;
3754}
3755
3756
3757static PyObject*
3758DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3759{
3760 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3761}
3762
3763
3764static PyObject*
3765DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3766{
3767 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3768}
3769
3770
3771static PyObject*
3772DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3773{
3774 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3775}
3776
3777
3778static PyObject*
3779DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3780{
3781 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3782}
3783
3784
3785static PyObject*
3786DBC_join_item(DBCursorObject* self, PyObject* args)
3787{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003788 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789 DBT key, data;
3790 PyObject* retval;
3791
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003793 return NULL;
3794
3795 CHECK_CURSOR_NOT_CLOSED(self);
3796
3797 CLEAR_DBT(key);
3798 CLEAR_DBT(data);
3799 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3800 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3801 key.flags = DB_DBT_MALLOC;
3802 }
3803
3804 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003805 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003806 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003807 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3808 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003809 Py_INCREF(Py_None);
3810 retval = Py_None;
3811 }
3812 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813 retval = NULL;
3814 }
3815 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003816 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003817 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 }
3819
3820 return retval;
3821}
3822
3823
3824
3825/* --------------------------------------------------------------------- */
3826/* DBEnv methods */
3827
3828
3829static PyObject*
3830DBEnv_close(DBEnvObject* self, PyObject* args)
3831{
3832 int err, flags = 0;
3833
3834 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3835 return NULL;
3836 if (!self->closed) { /* Don't close more than once */
3837 MYDB_BEGIN_ALLOW_THREADS;
3838 err = self->db_env->close(self->db_env, flags);
3839 MYDB_END_ALLOW_THREADS;
3840 /* after calling DBEnv->close, regardless of error, this DBEnv
3841 * may not be accessed again (BerkeleyDB docs). */
3842 self->closed = 1;
3843 self->db_env = NULL;
3844 RETURN_IF_ERR();
3845 }
3846 RETURN_NONE();
3847}
3848
3849
3850static PyObject*
3851DBEnv_open(DBEnvObject* self, PyObject* args)
3852{
3853 int err, flags=0, mode=0660;
3854 char *db_home;
3855
3856 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3857 return NULL;
3858
3859 CHECK_ENV_NOT_CLOSED(self);
3860
3861 MYDB_BEGIN_ALLOW_THREADS;
3862 err = self->db_env->open(self->db_env, db_home, flags, mode);
3863 MYDB_END_ALLOW_THREADS;
3864 RETURN_IF_ERR();
3865 self->closed = 0;
3866 self->flags = flags;
3867 RETURN_NONE();
3868}
3869
3870
3871static PyObject*
3872DBEnv_remove(DBEnvObject* self, PyObject* args)
3873{
3874 int err, flags=0;
3875 char *db_home;
3876
3877 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3878 return NULL;
3879 CHECK_ENV_NOT_CLOSED(self);
3880 MYDB_BEGIN_ALLOW_THREADS;
3881 err = self->db_env->remove(self->db_env, db_home, flags);
3882 MYDB_END_ALLOW_THREADS;
3883 RETURN_IF_ERR();
3884 RETURN_NONE();
3885}
3886
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003887#if (DBVER >= 41)
3888static PyObject*
3889DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3890{
3891 int err;
3892 u_int32_t flags=0;
3893 char *file = NULL;
3894 char *database = NULL;
3895 PyObject *txnobj = NULL;
3896 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003897 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003898 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003899
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003900 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003901 &file, &database, &txnobj, &flags)) {
3902 return NULL;
3903 }
3904 if (!checkTxnObj(txnobj, &txn)) {
3905 return NULL;
3906 }
3907 CHECK_ENV_NOT_CLOSED(self);
3908 MYDB_BEGIN_ALLOW_THREADS;
3909 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3910 MYDB_END_ALLOW_THREADS;
3911 RETURN_IF_ERR();
3912 RETURN_NONE();
3913}
3914
3915static PyObject*
3916DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3917{
3918 int err;
3919 u_int32_t flags=0;
3920 char *file = NULL;
3921 char *database = NULL;
3922 char *newname = NULL;
3923 PyObject *txnobj = NULL;
3924 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003925 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003926 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003927
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003929 &file, &database, &newname, &txnobj, &flags)) {
3930 return NULL;
3931 }
3932 if (!checkTxnObj(txnobj, &txn)) {
3933 return NULL;
3934 }
3935 CHECK_ENV_NOT_CLOSED(self);
3936 MYDB_BEGIN_ALLOW_THREADS;
3937 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3938 flags);
3939 MYDB_END_ALLOW_THREADS;
3940 RETURN_IF_ERR();
3941 RETURN_NONE();
3942}
3943
3944static PyObject*
3945DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3946{
3947 int err;
3948 u_int32_t flags=0;
3949 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003950 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003951
3952 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3953 &passwd, &flags)) {
3954 return NULL;
3955 }
3956
3957 MYDB_BEGIN_ALLOW_THREADS;
3958 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3959 MYDB_END_ALLOW_THREADS;
3960
3961 RETURN_IF_ERR();
3962 RETURN_NONE();
3963}
3964#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003965
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003966#if (DBVER >= 40)
3967static PyObject*
3968DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3969{
3970 int err;
3971 u_int32_t flags=0;
3972 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003973 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003974
3975 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3976 &timeout, &flags)) {
3977 return NULL;
3978 }
3979
3980 MYDB_BEGIN_ALLOW_THREADS;
3981 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3982 MYDB_END_ALLOW_THREADS;
3983
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3986}
3987#endif /* DBVER >= 40 */
3988
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003990DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3991{
3992 int err;
3993 long shm_key = 0;
3994
3995 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3998
3999 err = self->db_env->set_shm_key(self->db_env, shm_key);
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4002}
4003
4004static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004005DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4006{
4007 int err, gbytes=0, bytes=0, ncache=0;
4008
4009 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4010 &gbytes, &bytes, &ncache))
4011 return NULL;
4012 CHECK_ENV_NOT_CLOSED(self);
4013
4014 MYDB_BEGIN_ALLOW_THREADS;
4015 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4016 MYDB_END_ALLOW_THREADS;
4017 RETURN_IF_ERR();
4018 RETURN_NONE();
4019}
4020
4021
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004022static PyObject*
4023DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4024{
4025 int err, flags=0, onoff=0;
4026
4027 if (!PyArg_ParseTuple(args, "ii:set_flags",
4028 &flags, &onoff))
4029 return NULL;
4030 CHECK_ENV_NOT_CLOSED(self);
4031
4032 MYDB_BEGIN_ALLOW_THREADS;
4033 err = self->db_env->set_flags(self->db_env, flags, onoff);
4034 MYDB_END_ALLOW_THREADS;
4035 RETURN_IF_ERR();
4036 RETURN_NONE();
4037}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004038
4039
4040static PyObject*
4041DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4042{
4043 int err;
4044 char *dir;
4045
4046 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4047 return NULL;
4048 CHECK_ENV_NOT_CLOSED(self);
4049
4050 MYDB_BEGIN_ALLOW_THREADS;
4051 err = self->db_env->set_data_dir(self->db_env, dir);
4052 MYDB_END_ALLOW_THREADS;
4053 RETURN_IF_ERR();
4054 RETURN_NONE();
4055}
4056
4057
4058static PyObject*
4059DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4060{
4061 int err, lg_bsize;
4062
4063 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4064 return NULL;
4065 CHECK_ENV_NOT_CLOSED(self);
4066
4067 MYDB_BEGIN_ALLOW_THREADS;
4068 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4069 MYDB_END_ALLOW_THREADS;
4070 RETURN_IF_ERR();
4071 RETURN_NONE();
4072}
4073
4074
4075static PyObject*
4076DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4077{
4078 int err;
4079 char *dir;
4080
4081 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4082 return NULL;
4083 CHECK_ENV_NOT_CLOSED(self);
4084
4085 MYDB_BEGIN_ALLOW_THREADS;
4086 err = self->db_env->set_lg_dir(self->db_env, dir);
4087 MYDB_END_ALLOW_THREADS;
4088 RETURN_IF_ERR();
4089 RETURN_NONE();
4090}
4091
4092static PyObject*
4093DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4094{
4095 int err, lg_max;
4096
4097 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4098 return NULL;
4099 CHECK_ENV_NOT_CLOSED(self);
4100
4101 MYDB_BEGIN_ALLOW_THREADS;
4102 err = self->db_env->set_lg_max(self->db_env, lg_max);
4103 MYDB_END_ALLOW_THREADS;
4104 RETURN_IF_ERR();
4105 RETURN_NONE();
4106}
4107
4108
Neal Norwitz84562352005-10-20 04:30:15 +00004109#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004110static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004111DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4112{
4113 int err, lg_max;
4114
4115 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4116 return NULL;
4117 CHECK_ENV_NOT_CLOSED(self);
4118
4119 MYDB_BEGIN_ALLOW_THREADS;
4120 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4121 MYDB_END_ALLOW_THREADS;
4122 RETURN_IF_ERR();
4123 RETURN_NONE();
4124}
Neal Norwitz84562352005-10-20 04:30:15 +00004125#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004126
4127
4128static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004129DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4130{
4131 int err, lk_detect;
4132
4133 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4134 return NULL;
4135 CHECK_ENV_NOT_CLOSED(self);
4136
4137 MYDB_BEGIN_ALLOW_THREADS;
4138 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4139 MYDB_END_ALLOW_THREADS;
4140 RETURN_IF_ERR();
4141 RETURN_NONE();
4142}
4143
4144
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004145#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004146static PyObject*
4147DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4148{
4149 int err, max;
4150
4151 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4152 return NULL;
4153 CHECK_ENV_NOT_CLOSED(self);
4154
4155 MYDB_BEGIN_ALLOW_THREADS;
4156 err = self->db_env->set_lk_max(self->db_env, max);
4157 MYDB_END_ALLOW_THREADS;
4158 RETURN_IF_ERR();
4159 RETURN_NONE();
4160}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004161#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004162
4163
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004164
4165static PyObject*
4166DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4167{
4168 int err, max;
4169
4170 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4171 return NULL;
4172 CHECK_ENV_NOT_CLOSED(self);
4173
4174 MYDB_BEGIN_ALLOW_THREADS;
4175 err = self->db_env->set_lk_max_locks(self->db_env, max);
4176 MYDB_END_ALLOW_THREADS;
4177 RETURN_IF_ERR();
4178 RETURN_NONE();
4179}
4180
4181
4182static PyObject*
4183DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4184{
4185 int err, max;
4186
4187 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4188 return NULL;
4189 CHECK_ENV_NOT_CLOSED(self);
4190
4191 MYDB_BEGIN_ALLOW_THREADS;
4192 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4193 MYDB_END_ALLOW_THREADS;
4194 RETURN_IF_ERR();
4195 RETURN_NONE();
4196}
4197
4198
4199static PyObject*
4200DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4201{
4202 int err, max;
4203
4204 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4207
4208 MYDB_BEGIN_ALLOW_THREADS;
4209 err = self->db_env->set_lk_max_objects(self->db_env, max);
4210 MYDB_END_ALLOW_THREADS;
4211 RETURN_IF_ERR();
4212 RETURN_NONE();
4213}
4214
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004215
4216static PyObject*
4217DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4218{
4219 int err, mp_mmapsize;
4220
4221 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4222 return NULL;
4223 CHECK_ENV_NOT_CLOSED(self);
4224
4225 MYDB_BEGIN_ALLOW_THREADS;
4226 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4227 MYDB_END_ALLOW_THREADS;
4228 RETURN_IF_ERR();
4229 RETURN_NONE();
4230}
4231
4232
4233static PyObject*
4234DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4235{
4236 int err;
4237 char *dir;
4238
4239 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4240 return NULL;
4241 CHECK_ENV_NOT_CLOSED(self);
4242
4243 MYDB_BEGIN_ALLOW_THREADS;
4244 err = self->db_env->set_tmp_dir(self->db_env, dir);
4245 MYDB_END_ALLOW_THREADS;
4246 RETURN_IF_ERR();
4247 RETURN_NONE();
4248}
4249
4250
4251static PyObject*
4252DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4253{
4254 int flags = 0;
4255 PyObject* txnobj = NULL;
4256 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004257 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004258
4259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4260 &txnobj, &flags))
4261 return NULL;
4262
4263 if (!checkTxnObj(txnobj, &txn))
4264 return NULL;
4265 CHECK_ENV_NOT_CLOSED(self);
4266
4267 return (PyObject*)newDBTxnObject(self, txn, flags);
4268}
4269
4270
4271static PyObject*
4272DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4273{
4274 int err, kbyte=0, min=0, flags=0;
4275
4276 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4277 return NULL;
4278 CHECK_ENV_NOT_CLOSED(self);
4279
4280 MYDB_BEGIN_ALLOW_THREADS;
4281#if (DBVER >= 40)
4282 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4283#else
4284 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4285#endif
4286 MYDB_END_ALLOW_THREADS;
4287 RETURN_IF_ERR();
4288 RETURN_NONE();
4289}
4290
4291
4292static PyObject*
4293DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4294{
4295 int err, max;
4296
4297 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4298 return NULL;
4299 CHECK_ENV_NOT_CLOSED(self);
4300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004301 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004302 RETURN_IF_ERR();
4303 RETURN_NONE();
4304}
4305
4306
4307static PyObject*
4308DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4309{
4310 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004311 long stamp;
4312 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004313
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004314 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004315 return NULL;
4316 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004317 timestamp = (time_t)stamp;
4318 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004319 RETURN_IF_ERR();
4320 RETURN_NONE();
4321}
4322
4323
4324static PyObject*
4325DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4326{
4327 int err, atype, flags=0;
4328 int aborted = 0;
4329
4330 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4331 return NULL;
4332 CHECK_ENV_NOT_CLOSED(self);
4333
4334 MYDB_BEGIN_ALLOW_THREADS;
4335#if (DBVER >= 40)
4336 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4337#else
4338 err = lock_detect(self->db_env, flags, atype, &aborted);
4339#endif
4340 MYDB_END_ALLOW_THREADS;
4341 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00004342 return PyLong_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004343}
4344
4345
4346static PyObject*
4347DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4348{
4349 int flags=0;
4350 int locker, lock_mode;
4351 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004352 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004353 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004354
4355 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4356 return NULL;
4357
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004358 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004359 return NULL;
4360
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004361 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4362 free_buf_view(objobj, obj_buf_view);
4363 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004364}
4365
4366
4367static PyObject*
4368DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4369{
4370 int err;
4371 u_int32_t theID;
4372
4373 if (!PyArg_ParseTuple(args, ":lock_id"))
4374 return NULL;
4375
4376 CHECK_ENV_NOT_CLOSED(self);
4377 MYDB_BEGIN_ALLOW_THREADS;
4378#if (DBVER >= 40)
4379 err = self->db_env->lock_id(self->db_env, &theID);
4380#else
4381 err = lock_id(self->db_env, &theID);
4382#endif
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385
Christian Heimes217cfd12007-12-02 14:31:20 +00004386 return PyLong_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004387}
4388
Guido van Rossum77677112007-11-05 19:43:04 +00004389#if (DBVER >= 40)
4390static PyObject*
4391DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4392{
4393 int err;
4394 u_int32_t theID;
4395
4396 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4397 return NULL;
4398
4399 CHECK_ENV_NOT_CLOSED(self);
4400 MYDB_BEGIN_ALLOW_THREADS;
4401 err = self->db_env->lock_id_free(self->db_env, theID);
4402 MYDB_END_ALLOW_THREADS;
4403 RETURN_IF_ERR();
4404 RETURN_NONE();
4405}
4406#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004407
4408static PyObject*
4409DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4410{
4411 int err;
4412 DBLockObject* dblockobj;
4413
4414 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4415 return NULL;
4416
4417 CHECK_ENV_NOT_CLOSED(self);
4418 MYDB_BEGIN_ALLOW_THREADS;
4419#if (DBVER >= 40)
4420 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4421#else
4422 err = lock_put(self->db_env, &dblockobj->lock);
4423#endif
4424 MYDB_END_ALLOW_THREADS;
4425 RETURN_IF_ERR();
4426 RETURN_NONE();
4427}
4428
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004429#if (DBVER >= 44)
4430static PyObject*
4431DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4432{
4433 int err;
4434 char *file;
4435 u_int32_t flags = 0;
4436 static char* kwnames[] = { "file", "flags", NULL};
4437
4438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4439 &file, &flags))
4440 return NULL;
4441 CHECK_ENV_NOT_CLOSED(self);
4442
4443 MYDB_BEGIN_ALLOW_THREADS;
4444 err = self->db_env->lsn_reset(self->db_env, file, flags);
4445 MYDB_END_ALLOW_THREADS;
4446 RETURN_IF_ERR();
4447 RETURN_NONE();
4448}
4449#endif /* DBVER >= 4.4 */
4450
4451#if (DBVER >= 40)
4452static PyObject*
4453DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4454{
4455 int err;
4456 DB_LOG_STAT* statp = NULL;
4457 PyObject* d = NULL;
4458 u_int32_t flags = 0;
4459
4460 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4461 return NULL;
4462 CHECK_ENV_NOT_CLOSED(self);
4463
4464 MYDB_BEGIN_ALLOW_THREADS;
4465 err = self->db_env->log_stat(self->db_env, &statp, flags);
4466 MYDB_END_ALLOW_THREADS;
4467 RETURN_IF_ERR();
4468
4469 /* Turn the stat structure into a dictionary */
4470 d = PyDict_New();
4471 if (d == NULL) {
4472 if (statp)
4473 free(statp);
4474 return NULL;
4475 }
4476
4477#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4478
4479 MAKE_ENTRY(magic);
4480 MAKE_ENTRY(version);
4481 MAKE_ENTRY(mode);
4482 MAKE_ENTRY(lg_bsize);
4483#if (DBVER >= 44)
4484 MAKE_ENTRY(lg_size);
4485 MAKE_ENTRY(record);
4486#endif
4487#if (DBVER <= 40)
4488 MAKE_ENTRY(lg_max);
4489#endif
4490 MAKE_ENTRY(w_mbytes);
4491 MAKE_ENTRY(w_bytes);
4492 MAKE_ENTRY(wc_mbytes);
4493 MAKE_ENTRY(wc_bytes);
4494 MAKE_ENTRY(wcount);
4495 MAKE_ENTRY(wcount_fill);
4496#if (DBVER >= 44)
4497 MAKE_ENTRY(rcount);
4498#endif
4499 MAKE_ENTRY(scount);
4500 MAKE_ENTRY(cur_file);
4501 MAKE_ENTRY(cur_offset);
4502 MAKE_ENTRY(disk_file);
4503 MAKE_ENTRY(disk_offset);
4504 MAKE_ENTRY(maxcommitperflush);
4505 MAKE_ENTRY(mincommitperflush);
4506 MAKE_ENTRY(regsize);
4507 MAKE_ENTRY(region_wait);
4508 MAKE_ENTRY(region_nowait);
4509
4510#undef MAKE_ENTRY
4511 free(statp);
4512 return d;
4513} /* DBEnv_log_stat */
4514#endif /* DBVER >= 4.0 for log_stat method */
4515
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004516
4517static PyObject*
4518DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4519{
4520 int err;
4521 DB_LOCK_STAT* sp;
4522 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004523 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004524
4525 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4526 return NULL;
4527 CHECK_ENV_NOT_CLOSED(self);
4528
4529 MYDB_BEGIN_ALLOW_THREADS;
4530#if (DBVER >= 40)
4531 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4532#else
4533#if (DBVER >= 33)
4534 err = lock_stat(self->db_env, &sp);
4535#else
4536 err = lock_stat(self->db_env, &sp, NULL);
4537#endif
4538#endif
4539 MYDB_END_ALLOW_THREADS;
4540 RETURN_IF_ERR();
4541
4542 /* Turn the stat structure into a dictionary */
4543 d = PyDict_New();
4544 if (d == NULL) {
4545 free(sp);
4546 return NULL;
4547 }
4548
4549#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4550
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004551#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004552 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004553#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004554 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004555 MAKE_ENTRY(maxlocks);
4556 MAKE_ENTRY(maxlockers);
4557 MAKE_ENTRY(maxobjects);
4558 MAKE_ENTRY(nlocks);
4559 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560 MAKE_ENTRY(nlockers);
4561 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 MAKE_ENTRY(nobjects);
4563 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004564 MAKE_ENTRY(nrequests);
4565 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004566#if (DBVER < 44)
4567 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004568 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004569#else
4570 MAKE_ENTRY(lock_nowait);
4571 MAKE_ENTRY(lock_wait);
4572#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004573 MAKE_ENTRY(ndeadlocks);
4574 MAKE_ENTRY(regsize);
4575 MAKE_ENTRY(region_wait);
4576 MAKE_ENTRY(region_nowait);
4577
4578#undef MAKE_ENTRY
4579 free(sp);
4580 return d;
4581}
4582
4583
4584static PyObject*
4585DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4586{
4587 int flags=0;
4588 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004589 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004590 PyObject* list;
4591 PyObject* item = NULL;
4592
4593 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4594 return NULL;
4595
4596 CHECK_ENV_NOT_CLOSED(self);
4597 MYDB_BEGIN_ALLOW_THREADS;
4598#if (DBVER >= 40)
4599 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4600#elif (DBVER == 33)
4601 err = log_archive(self->db_env, &log_list, flags);
4602#else
4603 err = log_archive(self->db_env, &log_list, flags, NULL);
4604#endif
4605 MYDB_END_ALLOW_THREADS;
4606 RETURN_IF_ERR();
4607
4608 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004609 if (list == NULL) {
4610 if (log_list)
4611 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004613 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614
4615 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004616 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004617 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004618 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004619 if (item == NULL) {
4620 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004621 list = NULL;
4622 break;
4623 }
4624 PyList_Append(list, item);
4625 Py_DECREF(item);
4626 }
4627 free(log_list_start);
4628 }
4629 return list;
4630}
4631
4632
4633static PyObject*
4634DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4635{
4636 int err;
4637 DB_TXN_STAT* sp;
4638 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004639 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004640
4641 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4642 return NULL;
4643 CHECK_ENV_NOT_CLOSED(self);
4644
4645 MYDB_BEGIN_ALLOW_THREADS;
4646#if (DBVER >= 40)
4647 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4648#elif (DBVER == 33)
4649 err = txn_stat(self->db_env, &sp);
4650#else
4651 err = txn_stat(self->db_env, &sp, NULL);
4652#endif
4653 MYDB_END_ALLOW_THREADS;
4654 RETURN_IF_ERR();
4655
4656 /* Turn the stat structure into a dictionary */
4657 d = PyDict_New();
4658 if (d == NULL) {
4659 free(sp);
4660 return NULL;
4661 }
4662
4663#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004664#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004665
Guido van Rossumd8faa362007-04-27 19:54:29 +00004666 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004667 MAKE_ENTRY(last_txnid);
4668 MAKE_ENTRY(maxtxns);
4669 MAKE_ENTRY(nactive);
4670 MAKE_ENTRY(maxnactive);
4671 MAKE_ENTRY(nbegins);
4672 MAKE_ENTRY(naborts);
4673 MAKE_ENTRY(ncommits);
4674 MAKE_ENTRY(regsize);
4675 MAKE_ENTRY(region_wait);
4676 MAKE_ENTRY(region_nowait);
4677
4678#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004679#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680 free(sp);
4681 return d;
4682}
4683
4684
4685static PyObject*
4686DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4687{
4688 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004689 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004690
4691 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4692 return NULL;
4693 CHECK_ENV_NOT_CLOSED(self);
4694
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004695 if (self->moduleFlags.getReturnsNone)
4696 ++oldValue;
4697 if (self->moduleFlags.cursorSetReturnsNone)
4698 ++oldValue;
4699 self->moduleFlags.getReturnsNone = (flags >= 1);
4700 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00004701 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702}
4703
4704
4705/* --------------------------------------------------------------------- */
4706/* DBTxn methods */
4707
4708
4709static PyObject*
4710DBTxn_commit(DBTxnObject* self, PyObject* args)
4711{
4712 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004713 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004714
4715 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4716 return NULL;
4717
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004718 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004719 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4720 "after txn_commit or txn_abort");
4721 PyErr_SetObject(DBError, t);
4722 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004723 return NULL;
4724 }
4725 txn = self->txn;
4726 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004727 MYDB_BEGIN_ALLOW_THREADS;
4728#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004729 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004731 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004732#endif
4733 MYDB_END_ALLOW_THREADS;
4734 RETURN_IF_ERR();
4735 RETURN_NONE();
4736}
4737
4738static PyObject*
4739DBTxn_prepare(DBTxnObject* self, PyObject* args)
4740{
4741#if (DBVER >= 33)
4742 int err;
4743 char* gid=NULL;
4744 int gid_size=0;
4745
Gregory P. Smith361ed152007-08-23 07:32:27 +00004746 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004747 return NULL;
4748
4749 if (gid_size != DB_XIDDATASIZE) {
4750 PyErr_SetString(PyExc_TypeError,
4751 "gid must be DB_XIDDATASIZE bytes long");
4752 return NULL;
4753 }
4754
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004755 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004756 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4757 "after txn_commit or txn_abort");
4758 PyErr_SetObject(DBError, t);
4759 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004760 return NULL;
4761 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004762 MYDB_BEGIN_ALLOW_THREADS;
4763#if (DBVER >= 40)
4764 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4765#else
4766 err = txn_prepare(self->txn, (u_int8_t*)gid);
4767#endif
4768 MYDB_END_ALLOW_THREADS;
4769 RETURN_IF_ERR();
4770 RETURN_NONE();
4771#else
4772 int err;
4773
4774 if (!PyArg_ParseTuple(args, ":prepare"))
4775 return NULL;
4776
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004777 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004778 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4779 "after txn_commit or txn_abort");
4780 PyErr_SetObject(DBError, t);
4781 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004782 return NULL;
4783 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004784 MYDB_BEGIN_ALLOW_THREADS;
4785 err = txn_prepare(self->txn);
4786 MYDB_END_ALLOW_THREADS;
4787 RETURN_IF_ERR();
4788 RETURN_NONE();
4789#endif
4790}
4791
4792
4793static PyObject*
4794DBTxn_abort(DBTxnObject* self, PyObject* args)
4795{
4796 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004797 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004798
4799 if (!PyArg_ParseTuple(args, ":abort"))
4800 return NULL;
4801
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004802 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004803 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4804 "after txn_commit or txn_abort");
4805 PyErr_SetObject(DBError, t);
4806 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004807 return NULL;
4808 }
4809 txn = self->txn;
4810 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004811 MYDB_BEGIN_ALLOW_THREADS;
4812#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004813 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004814#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004815 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004816#endif
4817 MYDB_END_ALLOW_THREADS;
4818 RETURN_IF_ERR();
4819 RETURN_NONE();
4820}
4821
4822
4823static PyObject*
4824DBTxn_id(DBTxnObject* self, PyObject* args)
4825{
4826 int id;
4827
4828 if (!PyArg_ParseTuple(args, ":id"))
4829 return NULL;
4830
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004831 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004832 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4833 "after txn_commit or txn_abort");
4834 PyErr_SetObject(DBError, t);
4835 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004836 return NULL;
4837 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004838 MYDB_BEGIN_ALLOW_THREADS;
4839#if (DBVER >= 40)
4840 id = self->txn->id(self->txn);
4841#else
4842 id = txn_id(self->txn);
4843#endif
4844 MYDB_END_ALLOW_THREADS;
Christian Heimes217cfd12007-12-02 14:31:20 +00004845 return PyLong_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004846}
4847
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004848#if (DBVER >= 43)
4849/* --------------------------------------------------------------------- */
4850/* DBSequence methods */
4851
4852
4853static PyObject*
4854DBSequence_close(DBSequenceObject* self, PyObject* args)
4855{
4856 int err, flags=0;
4857 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4858 return NULL;
4859 CHECK_SEQUENCE_NOT_CLOSED(self)
4860
4861 MYDB_BEGIN_ALLOW_THREADS
4862 err = self->sequence->close(self->sequence, flags);
4863 self->sequence = NULL;
4864 MYDB_END_ALLOW_THREADS
4865
4866 RETURN_IF_ERR();
4867
4868 RETURN_NONE();
4869}
4870
4871static PyObject*
4872DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4873{
4874 int err, flags = 0;
4875 int delta = 1;
4876 db_seq_t value;
4877 PyObject *txnobj = NULL;
4878 DB_TXN *txn = NULL;
4879 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4880 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4881 return NULL;
4882 CHECK_SEQUENCE_NOT_CLOSED(self)
4883
4884 if (!checkTxnObj(txnobj, &txn))
4885 return NULL;
4886
4887 MYDB_BEGIN_ALLOW_THREADS
4888 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4889 MYDB_END_ALLOW_THREADS
4890
4891 RETURN_IF_ERR();
4892 return PyLong_FromLongLong(value);
4893
4894}
4895
4896static PyObject*
4897DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4898{
4899 if (!PyArg_ParseTuple(args,":get_dbp"))
4900 return NULL;
4901 CHECK_SEQUENCE_NOT_CLOSED(self)
4902 Py_INCREF(self->mydb);
4903 return (PyObject* )self->mydb;
4904}
4905
4906static PyObject*
4907DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4908{
4909 int err;
4910 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004911 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004912 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004913 CHECK_SEQUENCE_NOT_CLOSED(self)
4914 MYDB_BEGIN_ALLOW_THREADS
4915 err = self->sequence->get_key(self->sequence, &key);
4916 MYDB_END_ALLOW_THREADS
4917
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004918 if (!err)
Guido van Rossum98297ee2007-11-06 21:34:58 +00004919 retval = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004920
4921 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004922 RETURN_IF_ERR();
4923
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004924 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004925}
4926
4927static PyObject*
4928DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4929{
4930 int err;
4931 db_seq_t value;
4932 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4933 return NULL;
4934 CHECK_SEQUENCE_NOT_CLOSED(self)
4935
4936 MYDB_BEGIN_ALLOW_THREADS
4937 err = self->sequence->initial_value(self->sequence, value);
4938 MYDB_END_ALLOW_THREADS
4939
4940 RETURN_IF_ERR();
4941
4942 RETURN_NONE();
4943}
4944
4945static PyObject*
4946DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4947{
4948 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004949 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004950 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004951 PyObject *txnobj = NULL;
4952 DB_TXN *txn = NULL;
4953 DBT key;
4954
4955 static char* kwnames[] = {"key", "txn", "flags", NULL };
4956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4957 return NULL;
4958
4959 if (!checkTxnObj(txnobj, &txn))
4960 return NULL;
4961
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004962 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004963 return NULL;
4964
4965 MYDB_BEGIN_ALLOW_THREADS
4966 err = self->sequence->open(self->sequence, txn, &key, flags);
4967 MYDB_END_ALLOW_THREADS
4968
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004969 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004970 RETURN_IF_ERR();
4971
4972 RETURN_NONE();
4973}
4974
4975static PyObject*
4976DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4977{
4978 int err, flags = 0;
4979 PyObject *txnobj = NULL;
4980 DB_TXN *txn = NULL;
4981
4982 static char* kwnames[] = {"txn", "flags", NULL };
4983 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4984 return NULL;
4985
4986 if (!checkTxnObj(txnobj, &txn))
4987 return NULL;
4988
4989 CHECK_SEQUENCE_NOT_CLOSED(self)
4990
4991 MYDB_BEGIN_ALLOW_THREADS
4992 err = self->sequence->remove(self->sequence, txn, flags);
4993 MYDB_END_ALLOW_THREADS
4994
4995 RETURN_IF_ERR();
4996 RETURN_NONE();
4997}
4998
4999static PyObject*
5000DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5001{
5002 int err, size;
5003 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5004 return NULL;
5005 CHECK_SEQUENCE_NOT_CLOSED(self)
5006
5007 MYDB_BEGIN_ALLOW_THREADS
5008 err = self->sequence->set_cachesize(self->sequence, size);
5009 MYDB_END_ALLOW_THREADS
5010
5011 RETURN_IF_ERR();
5012 RETURN_NONE();
5013}
5014
5015static PyObject*
5016DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5017{
5018 int err, size;
5019 if (!PyArg_ParseTuple(args,":get_cachesize"))
5020 return NULL;
5021 CHECK_SEQUENCE_NOT_CLOSED(self)
5022
5023 MYDB_BEGIN_ALLOW_THREADS
5024 err = self->sequence->get_cachesize(self->sequence, &size);
5025 MYDB_END_ALLOW_THREADS
5026
5027 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005028 return PyLong_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005029}
5030
5031static PyObject*
5032DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5033{
5034 int err, flags = 0;
5035 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5036 return NULL;
5037 CHECK_SEQUENCE_NOT_CLOSED(self)
5038
5039 MYDB_BEGIN_ALLOW_THREADS
5040 err = self->sequence->set_flags(self->sequence, flags);
5041 MYDB_END_ALLOW_THREADS
5042
5043 RETURN_IF_ERR();
5044 RETURN_NONE();
5045
5046}
5047
5048static PyObject*
5049DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5050{
5051 unsigned int flags;
5052 int err;
5053 if (!PyArg_ParseTuple(args,":get_flags"))
5054 return NULL;
5055 CHECK_SEQUENCE_NOT_CLOSED(self)
5056
5057 MYDB_BEGIN_ALLOW_THREADS
5058 err = self->sequence->get_flags(self->sequence, &flags);
5059 MYDB_END_ALLOW_THREADS
5060
5061 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005062 return PyLong_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005063}
5064
5065static PyObject*
5066DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5067{
5068 int err;
5069 db_seq_t min, max;
5070 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5071 return NULL;
5072 CHECK_SEQUENCE_NOT_CLOSED(self)
5073
5074 MYDB_BEGIN_ALLOW_THREADS
5075 err = self->sequence->set_range(self->sequence, min, max);
5076 MYDB_END_ALLOW_THREADS
5077
5078 RETURN_IF_ERR();
5079 RETURN_NONE();
5080}
5081
5082static PyObject*
5083DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5084{
5085 int err;
5086 db_seq_t min, max;
5087 if (!PyArg_ParseTuple(args,":get_range"))
5088 return NULL;
5089 CHECK_SEQUENCE_NOT_CLOSED(self)
5090
5091 MYDB_BEGIN_ALLOW_THREADS
5092 err = self->sequence->get_range(self->sequence, &min, &max);
5093 MYDB_END_ALLOW_THREADS
5094
5095 RETURN_IF_ERR();
5096 return Py_BuildValue("(LL)", min, max);
5097}
5098
5099static PyObject*
5100DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5101{
5102 int err, flags = 0;
5103 DB_SEQUENCE_STAT* sp = NULL;
5104 PyObject* dict_stat;
5105 static char* kwnames[] = {"flags", NULL };
5106 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5107 return NULL;
5108 CHECK_SEQUENCE_NOT_CLOSED(self);
5109
5110 MYDB_BEGIN_ALLOW_THREADS;
5111 err = self->sequence->stat(self->sequence, &sp, flags);
5112 MYDB_END_ALLOW_THREADS;
5113 RETURN_IF_ERR();
5114
5115 if ((dict_stat = PyDict_New()) == NULL) {
5116 free(sp);
5117 return NULL;
5118 }
5119
5120
5121#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5122#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5123
5124 MAKE_INT_ENTRY(wait);
5125 MAKE_INT_ENTRY(nowait);
5126 MAKE_LONG_LONG_ENTRY(current);
5127 MAKE_LONG_LONG_ENTRY(value);
5128 MAKE_LONG_LONG_ENTRY(last_value);
5129 MAKE_LONG_LONG_ENTRY(min);
5130 MAKE_LONG_LONG_ENTRY(max);
5131 MAKE_INT_ENTRY(cache_size);
5132 MAKE_INT_ENTRY(flags);
5133
5134#undef MAKE_INT_ENTRY
5135#undef MAKE_LONG_LONG_ENTRY
5136
5137 free(sp);
5138 return dict_stat;
5139}
5140#endif
5141
5142
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005143/* --------------------------------------------------------------------- */
5144/* Method definition tables and type objects */
5145
5146static PyMethodDef DB_methods[] = {
5147 {"append", (PyCFunction)DB_append, METH_VARARGS},
5148#if (DBVER >= 33)
5149 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5150#endif
5151 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005152 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5153 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005154 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5155 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5156 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5157 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005158#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005159 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005160#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005161 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5162 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5163 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5164 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5165 {"join", (PyCFunction)DB_join, METH_VARARGS},
5166 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5167 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5168 {"items", (PyCFunction)DB_items, METH_VARARGS},
5169 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5170 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5171 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5172 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5173 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5174 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005175#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005176 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005177#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005178 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005179#if (DBVER >= 41)
5180 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5181#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005182 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5183 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5184 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5185 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5186 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5187 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5188 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5189 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5190 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005191 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005192 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005193 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5194#if (DBVER >= 33)
5195 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5196#endif
5197 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5198 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5199 {"values", (PyCFunction)DB_values, METH_VARARGS},
5200 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5201 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5202 {NULL, NULL} /* sentinel */
5203};
5204
5205
5206static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005207 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005208 (binaryfunc)DB_subscript, /*mp_subscript*/
5209 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5210};
5211
5212
5213static PyMethodDef DBCursor_methods[] = {
5214 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5215 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5216 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5217 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5218 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5219 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5220 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005221#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005222 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005223#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005224 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5225 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5226 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5227 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5228 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5229 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5230 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5231 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005232 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005233 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005234 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5235 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5236 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5237 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5238 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5239 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5240 {NULL, NULL} /* sentinel */
5241};
5242
5243
5244static PyMethodDef DBEnv_methods[] = {
5245 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5246 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5247 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005248#if (DBVER >= 41)
5249 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5250 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5251 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5252#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005253#if (DBVER >= 40)
5254 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5255#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005256 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005257 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5258 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5261 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5262 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005263#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005264 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005265#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005267#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005268 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005269#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005270 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5271 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5272 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005273 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5274 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5275 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5276 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5277 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5278 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005279 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005280 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5281 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5282 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005283#if (DBVER >= 40)
5284 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5285#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005286 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5287 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5288 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005289#if (DBVER >= 40)
5290 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5291#endif
5292#if (DBVER >= 44)
5293 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5294#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005295 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5296 {NULL, NULL} /* sentinel */
5297};
5298
5299
5300static PyMethodDef DBTxn_methods[] = {
5301 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5302 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5303 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5304 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5305 {NULL, NULL} /* sentinel */
5306};
5307
5308
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005309#if (DBVER >= 43)
5310static PyMethodDef DBSequence_methods[] = {
5311 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5312 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5313 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5314 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5315 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5316 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5317 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5318 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5319 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5320 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5321 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5322 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5323 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5324 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5325 {NULL, NULL} /* sentinel */
5326};
5327#endif
5328
5329
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005330static PyObject*
5331DB_getattr(DBObject* self, char *name)
5332{
5333 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5334}
5335
5336
5337static PyObject*
5338DBEnv_getattr(DBEnvObject* self, char *name)
5339{
5340 if (!strcmp(name, "db_home")) {
5341 CHECK_ENV_NOT_CLOSED(self);
5342 if (self->db_env->db_home == NULL) {
5343 RETURN_NONE();
5344 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005345 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005346 }
5347
5348 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5349}
5350
5351
5352static PyObject*
5353DBCursor_getattr(DBCursorObject* self, char *name)
5354{
5355 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5356}
5357
5358static PyObject*
5359DBTxn_getattr(DBTxnObject* self, char *name)
5360{
5361 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5362}
5363
5364static PyObject*
5365DBLock_getattr(DBLockObject* self, char *name)
5366{
5367 return NULL;
5368}
5369
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005370#if (DBVER >= 43)
5371static PyObject*
5372DBSequence_getattr(DBSequenceObject* self, char *name)
5373{
5374 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5375}
5376#endif
5377
Neal Norwitz227b5332006-03-22 09:28:35 +00005378static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005379 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005380 "DB", /*tp_name*/
5381 sizeof(DBObject), /*tp_basicsize*/
5382 0, /*tp_itemsize*/
5383 /* methods */
5384 (destructor)DB_dealloc, /*tp_dealloc*/
5385 0, /*tp_print*/
5386 (getattrfunc)DB_getattr, /*tp_getattr*/
5387 0, /*tp_setattr*/
5388 0, /*tp_compare*/
5389 0, /*tp_repr*/
5390 0, /*tp_as_number*/
5391 0, /*tp_as_sequence*/
5392 &DB_mapping,/*tp_as_mapping*/
5393 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005394 0, /* tp_call */
5395 0, /* tp_str */
5396 0, /* tp_getattro */
5397 0, /* tp_setattro */
5398 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005399 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005400 0, /* tp_doc */
5401 0, /* tp_traverse */
5402 0, /* tp_clear */
5403 0, /* tp_richcompare */
5404 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005405};
5406
5407
Neal Norwitz227b5332006-03-22 09:28:35 +00005408static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005409 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005410 "DBCursor", /*tp_name*/
5411 sizeof(DBCursorObject), /*tp_basicsize*/
5412 0, /*tp_itemsize*/
5413 /* methods */
5414 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5415 0, /*tp_print*/
5416 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5417 0, /*tp_setattr*/
5418 0, /*tp_compare*/
5419 0, /*tp_repr*/
5420 0, /*tp_as_number*/
5421 0, /*tp_as_sequence*/
5422 0, /*tp_as_mapping*/
5423 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005424 0, /* tp_call */
5425 0, /* tp_str */
5426 0, /* tp_getattro */
5427 0, /* tp_setattro */
5428 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005429 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005430 0, /* tp_doc */
5431 0, /* tp_traverse */
5432 0, /* tp_clear */
5433 0, /* tp_richcompare */
5434 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005435};
5436
5437
Neal Norwitz227b5332006-03-22 09:28:35 +00005438static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005439 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005440 "DBEnv", /*tp_name*/
5441 sizeof(DBEnvObject), /*tp_basicsize*/
5442 0, /*tp_itemsize*/
5443 /* methods */
5444 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5445 0, /*tp_print*/
5446 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5447 0, /*tp_setattr*/
5448 0, /*tp_compare*/
5449 0, /*tp_repr*/
5450 0, /*tp_as_number*/
5451 0, /*tp_as_sequence*/
5452 0, /*tp_as_mapping*/
5453 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005454 0, /* tp_call */
5455 0, /* tp_str */
5456 0, /* tp_getattro */
5457 0, /* tp_setattro */
5458 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005459 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005460 0, /* tp_doc */
5461 0, /* tp_traverse */
5462 0, /* tp_clear */
5463 0, /* tp_richcompare */
5464 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005465};
5466
Neal Norwitz227b5332006-03-22 09:28:35 +00005467static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005468 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005469 "DBTxn", /*tp_name*/
5470 sizeof(DBTxnObject), /*tp_basicsize*/
5471 0, /*tp_itemsize*/
5472 /* methods */
5473 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5474 0, /*tp_print*/
5475 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5476 0, /*tp_setattr*/
5477 0, /*tp_compare*/
5478 0, /*tp_repr*/
5479 0, /*tp_as_number*/
5480 0, /*tp_as_sequence*/
5481 0, /*tp_as_mapping*/
5482 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005483 0, /* tp_call */
5484 0, /* tp_str */
5485 0, /* tp_getattro */
5486 0, /* tp_setattro */
5487 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005488 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005489 0, /* tp_doc */
5490 0, /* tp_traverse */
5491 0, /* tp_clear */
5492 0, /* tp_richcompare */
5493 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005494};
5495
5496
Neal Norwitz227b5332006-03-22 09:28:35 +00005497static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005498 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005499 "DBLock", /*tp_name*/
5500 sizeof(DBLockObject), /*tp_basicsize*/
5501 0, /*tp_itemsize*/
5502 /* methods */
5503 (destructor)DBLock_dealloc, /*tp_dealloc*/
5504 0, /*tp_print*/
5505 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5506 0, /*tp_setattr*/
5507 0, /*tp_compare*/
5508 0, /*tp_repr*/
5509 0, /*tp_as_number*/
5510 0, /*tp_as_sequence*/
5511 0, /*tp_as_mapping*/
5512 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005513 0, /* tp_call */
5514 0, /* tp_str */
5515 0, /* tp_getattro */
5516 0, /* tp_setattro */
5517 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005518 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005519 0, /* tp_doc */
5520 0, /* tp_traverse */
5521 0, /* tp_clear */
5522 0, /* tp_richcompare */
5523 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005524};
5525
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005526#if (DBVER >= 43)
5527static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005528 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005529 "DBSequence", /*tp_name*/
5530 sizeof(DBSequenceObject), /*tp_basicsize*/
5531 0, /*tp_itemsize*/
5532 /* methods */
5533 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5534 0, /*tp_print*/
5535 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5536 0, /*tp_setattr*/
5537 0, /*tp_compare*/
5538 0, /*tp_repr*/
5539 0, /*tp_as_number*/
5540 0, /*tp_as_sequence*/
5541 0, /*tp_as_mapping*/
5542 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005543 0, /* tp_call */
5544 0, /* tp_str */
5545 0, /* tp_getattro */
5546 0, /* tp_setattro */
5547 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005548 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005549 0, /* tp_doc */
5550 0, /* tp_traverse */
5551 0, /* tp_clear */
5552 0, /* tp_richcompare */
5553 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005554};
5555#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005556
5557/* --------------------------------------------------------------------- */
5558/* Module-level functions */
5559
5560static PyObject*
5561DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5562{
5563 PyObject* dbenvobj = NULL;
5564 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005565 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005566
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5568 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005569 return NULL;
5570 if (dbenvobj == Py_None)
5571 dbenvobj = NULL;
5572 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5573 makeTypeError("DBEnv", dbenvobj);
5574 return NULL;
5575 }
5576
5577 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5578}
5579
5580
5581static PyObject*
5582DBEnv_construct(PyObject* self, PyObject* args)
5583{
5584 int flags = 0;
5585 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5586 return (PyObject* )newDBEnvObject(flags);
5587}
5588
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005589#if (DBVER >= 43)
5590static PyObject*
5591DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5592{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005593 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005594 int flags = 0;
5595 static char* kwnames[] = { "db", "flags", NULL};
5596
5597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5598 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005599 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005600 makeTypeError("DB", dbobj);
5601 return NULL;
5602 }
5603 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5604}
5605#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005606
5607static char bsddb_version_doc[] =
5608"Returns a tuple of major, minor, and patch release numbers of the\n\
5609underlying DB library.";
5610
5611static PyObject*
5612bsddb_version(PyObject* self, PyObject* args)
5613{
5614 int major, minor, patch;
5615
5616 if (!PyArg_ParseTuple(args, ":version"))
5617 return NULL;
5618 db_version(&major, &minor, &patch);
5619 return Py_BuildValue("(iii)", major, minor, patch);
5620}
5621
5622
5623/* List of functions defined in the module */
5624
5625static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005626 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5627 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5628#if (DBVER >= 43)
5629 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5630#endif
5631 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005632 {NULL, NULL} /* sentinel */
5633};
5634
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005635/* API structure */
5636static BSDDB_api bsddb_api;
5637
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638
5639/* --------------------------------------------------------------------- */
5640/* Module initialization */
5641
5642
5643/* Convenience routine to export an integer value.
5644 * Errors are silently ignored, for better or for worse...
5645 */
5646#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5647
Gregory P. Smith41631e82003-09-21 00:08:14 +00005648#define MODULE_NAME_MAX_LEN 11
5649static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005650
Neal Norwitzf6657e62006-12-28 04:47:50 +00005651PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005652{
5653 PyObject* m;
5654 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005655 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5656 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5657 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005658 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005659
5660 /* Initialize the type of the new type objects here; doing it here
5661 is required for portability to Windows without requiring C++. */
Christian Heimes90aa7642007-12-19 02:45:37 +00005662 Py_TYPE(&DB_Type) = &PyType_Type;
5663 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5664 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5665 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5666 Py_TYPE(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005667#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +00005668 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005669#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005670
5671
Mark Hammonda69d4092003-04-22 23:13:27 +00005672#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005674 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675#endif
5676
5677 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005678 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005679 if (m == NULL)
5680 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005681
5682 /* Add some symbolic constants to the module */
5683 d = PyModule_GetDict(m);
5684 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005685 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005686 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5687 Py_DECREF(pybsddb_version_s);
5688 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005689 Py_DECREF(svnid_s);
5690 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005691 Py_DECREF(db_version_s);
5692 db_version_s = NULL;
5693
5694 ADD_INT(d, DB_VERSION_MAJOR);
5695 ADD_INT(d, DB_VERSION_MINOR);
5696 ADD_INT(d, DB_VERSION_PATCH);
5697
5698 ADD_INT(d, DB_MAX_PAGES);
5699 ADD_INT(d, DB_MAX_RECORDS);
5700
Gregory P. Smith41631e82003-09-21 00:08:14 +00005701#if (DBVER >= 42)
5702 ADD_INT(d, DB_RPCCLIENT);
5703#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005704 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005705 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5706 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5707#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005708 ADD_INT(d, DB_XA_CREATE);
5709
5710 ADD_INT(d, DB_CREATE);
5711 ADD_INT(d, DB_NOMMAP);
5712 ADD_INT(d, DB_THREAD);
5713
5714 ADD_INT(d, DB_FORCE);
5715 ADD_INT(d, DB_INIT_CDB);
5716 ADD_INT(d, DB_INIT_LOCK);
5717 ADD_INT(d, DB_INIT_LOG);
5718 ADD_INT(d, DB_INIT_MPOOL);
5719 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005720 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005721
5722 ADD_INT(d, DB_RECOVER);
5723 ADD_INT(d, DB_RECOVER_FATAL);
5724 ADD_INT(d, DB_TXN_NOSYNC);
5725 ADD_INT(d, DB_USE_ENVIRON);
5726 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5727
5728 ADD_INT(d, DB_LOCKDOWN);
5729 ADD_INT(d, DB_PRIVATE);
5730 ADD_INT(d, DB_SYSTEM_MEM);
5731
5732 ADD_INT(d, DB_TXN_SYNC);
5733 ADD_INT(d, DB_TXN_NOWAIT);
5734
5735 ADD_INT(d, DB_EXCL);
5736 ADD_INT(d, DB_FCNTL_LOCKING);
5737 ADD_INT(d, DB_ODDFILESIZE);
5738 ADD_INT(d, DB_RDWRMASTER);
5739 ADD_INT(d, DB_RDONLY);
5740 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005741 ADD_INT(d, DB_EXTENT);
5742 ADD_INT(d, DB_CDB_ALLDB);
5743 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005744 ADD_INT(d, DB_UPGRADE);
5745
5746 ADD_INT(d, DB_AGGRESSIVE);
5747 ADD_INT(d, DB_NOORDERCHK);
5748 ADD_INT(d, DB_ORDERCHKONLY);
5749 ADD_INT(d, DB_PR_PAGE);
5750#if ! (DBVER >= 33)
5751 ADD_INT(d, DB_VRFY_FLAGMASK);
5752 ADD_INT(d, DB_PR_HEADERS);
5753#endif
5754 ADD_INT(d, DB_PR_RECOVERYTEST);
5755 ADD_INT(d, DB_SALVAGE);
5756
5757 ADD_INT(d, DB_LOCK_NORUN);
5758 ADD_INT(d, DB_LOCK_DEFAULT);
5759 ADD_INT(d, DB_LOCK_OLDEST);
5760 ADD_INT(d, DB_LOCK_RANDOM);
5761 ADD_INT(d, DB_LOCK_YOUNGEST);
5762#if (DBVER >= 33)
5763 ADD_INT(d, DB_LOCK_MAXLOCKS);
5764 ADD_INT(d, DB_LOCK_MINLOCKS);
5765 ADD_INT(d, DB_LOCK_MINWRITE);
5766#endif
5767
5768
5769#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005770 /* docs say to use zero instead */
5771 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005772#else
5773 ADD_INT(d, DB_LOCK_CONFLICT);
5774#endif
5775
5776 ADD_INT(d, DB_LOCK_DUMP);
5777 ADD_INT(d, DB_LOCK_GET);
5778 ADD_INT(d, DB_LOCK_INHERIT);
5779 ADD_INT(d, DB_LOCK_PUT);
5780 ADD_INT(d, DB_LOCK_PUT_ALL);
5781 ADD_INT(d, DB_LOCK_PUT_OBJ);
5782
5783 ADD_INT(d, DB_LOCK_NG);
5784 ADD_INT(d, DB_LOCK_READ);
5785 ADD_INT(d, DB_LOCK_WRITE);
5786 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005788 ADD_INT(d, DB_LOCK_IWRITE);
5789 ADD_INT(d, DB_LOCK_IREAD);
5790 ADD_INT(d, DB_LOCK_IWR);
5791#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005792#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005793 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005794#else
5795 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5796#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005797 ADD_INT(d, DB_LOCK_WWRITE);
5798#endif
5799
5800 ADD_INT(d, DB_LOCK_RECORD);
5801 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005803#if (DBVER >= 33)
5804 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5805#endif
5806
5807 ADD_INT(d, DB_LOCK_NOWAIT);
5808 ADD_INT(d, DB_LOCK_RECORD);
5809 ADD_INT(d, DB_LOCK_UPGRADE);
5810
5811#if (DBVER >= 33)
5812 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005813#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005814 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005815#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005816 ADD_INT(d, DB_LSTAT_FREE);
5817 ADD_INT(d, DB_LSTAT_HELD);
5818#if (DBVER == 33)
5819 ADD_INT(d, DB_LSTAT_NOGRANT);
5820#endif
5821 ADD_INT(d, DB_LSTAT_PENDING);
5822 ADD_INT(d, DB_LSTAT_WAITING);
5823#endif
5824
5825 ADD_INT(d, DB_ARCH_ABS);
5826 ADD_INT(d, DB_ARCH_DATA);
5827 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005828#if (DBVER >= 42)
5829 ADD_INT(d, DB_ARCH_REMOVE);
5830#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005831
5832 ADD_INT(d, DB_BTREE);
5833 ADD_INT(d, DB_HASH);
5834 ADD_INT(d, DB_RECNO);
5835 ADD_INT(d, DB_QUEUE);
5836 ADD_INT(d, DB_UNKNOWN);
5837
5838 ADD_INT(d, DB_DUP);
5839 ADD_INT(d, DB_DUPSORT);
5840 ADD_INT(d, DB_RECNUM);
5841 ADD_INT(d, DB_RENUMBER);
5842 ADD_INT(d, DB_REVSPLITOFF);
5843 ADD_INT(d, DB_SNAPSHOT);
5844
5845 ADD_INT(d, DB_JOIN_NOSORT);
5846
5847 ADD_INT(d, DB_AFTER);
5848 ADD_INT(d, DB_APPEND);
5849 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005850#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005851 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005852#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005853#if (DBVER >= 41)
5854 _addIntToDict(d, "DB_CHECKPOINT", 0);
5855#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005856 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005857 ADD_INT(d, DB_CURLSN);
5858#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005859#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005860 ADD_INT(d, DB_COMMIT);
5861#endif
5862 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005863 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005864 ADD_INT(d, DB_CURRENT);
5865#if (DBVER >= 33)
5866 ADD_INT(d, DB_FAST_STAT);
5867#endif
5868 ADD_INT(d, DB_FIRST);
5869 ADD_INT(d, DB_FLUSH);
5870 ADD_INT(d, DB_GET_BOTH);
5871 ADD_INT(d, DB_GET_RECNO);
5872 ADD_INT(d, DB_JOIN_ITEM);
5873 ADD_INT(d, DB_KEYFIRST);
5874 ADD_INT(d, DB_KEYLAST);
5875 ADD_INT(d, DB_LAST);
5876 ADD_INT(d, DB_NEXT);
5877 ADD_INT(d, DB_NEXT_DUP);
5878 ADD_INT(d, DB_NEXT_NODUP);
5879 ADD_INT(d, DB_NODUPDATA);
5880 ADD_INT(d, DB_NOOVERWRITE);
5881 ADD_INT(d, DB_NOSYNC);
5882 ADD_INT(d, DB_POSITION);
5883 ADD_INT(d, DB_PREV);
5884 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005885#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005886 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005887#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005888 ADD_INT(d, DB_SET);
5889 ADD_INT(d, DB_SET_RANGE);
5890 ADD_INT(d, DB_SET_RECNO);
5891 ADD_INT(d, DB_WRITECURSOR);
5892
5893 ADD_INT(d, DB_OPFLAGS_MASK);
5894 ADD_INT(d, DB_RMW);
5895#if (DBVER >= 33)
5896 ADD_INT(d, DB_DIRTY_READ);
5897 ADD_INT(d, DB_MULTIPLE);
5898 ADD_INT(d, DB_MULTIPLE_KEY);
5899#endif
5900
Gregory P. Smith29602d22006-01-24 09:46:48 +00005901#if (DBVER >= 44)
5902 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5903 ADD_INT(d, DB_READ_COMMITTED);
5904#endif
5905
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005906#if (DBVER >= 33)
5907 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005908 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005909#endif
5910
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005911#if (DBVER >= 41)
5912 _addIntToDict(d, "DB_INCOMPLETE", 0);
5913#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005914 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005915#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005916 ADD_INT(d, DB_KEYEMPTY);
5917 ADD_INT(d, DB_KEYEXIST);
5918 ADD_INT(d, DB_LOCK_DEADLOCK);
5919 ADD_INT(d, DB_LOCK_NOTGRANTED);
5920 ADD_INT(d, DB_NOSERVER);
5921 ADD_INT(d, DB_NOSERVER_HOME);
5922 ADD_INT(d, DB_NOSERVER_ID);
5923 ADD_INT(d, DB_NOTFOUND);
5924 ADD_INT(d, DB_OLD_VERSION);
5925 ADD_INT(d, DB_RUNRECOVERY);
5926 ADD_INT(d, DB_VERIFY_BAD);
5927#if (DBVER >= 33)
5928 ADD_INT(d, DB_PAGE_NOTFOUND);
5929 ADD_INT(d, DB_SECONDARY_BAD);
5930#endif
5931#if (DBVER >= 40)
5932 ADD_INT(d, DB_STAT_CLEAR);
5933 ADD_INT(d, DB_REGION_INIT);
5934 ADD_INT(d, DB_NOLOCKING);
5935 ADD_INT(d, DB_YIELDCPU);
5936 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5937 ADD_INT(d, DB_NOPANIC);
5938#endif
5939
Guido van Rossum2cc30da2007-11-02 23:46:40 +00005940#ifdef DB_REGISTER
5941 ADD_INT(d, DB_REGISTER);
5942#endif
5943
Gregory P. Smith41631e82003-09-21 00:08:14 +00005944#if (DBVER >= 42)
5945 ADD_INT(d, DB_TIME_NOTGRANTED);
5946 ADD_INT(d, DB_TXN_NOT_DURABLE);
5947 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5948 ADD_INT(d, DB_LOG_AUTOREMOVE);
5949 ADD_INT(d, DB_DIRECT_LOG);
5950 ADD_INT(d, DB_DIRECT_DB);
5951 ADD_INT(d, DB_INIT_REP);
5952 ADD_INT(d, DB_ENCRYPT);
5953 ADD_INT(d, DB_CHKSUM);
5954#endif
5955
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005956#if (DBVER >= 43)
5957 ADD_INT(d, DB_LOG_INMEMORY);
5958 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005959 ADD_INT(d, DB_SEQ_DEC);
5960 ADD_INT(d, DB_SEQ_INC);
5961 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005962#endif
5963
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005964#if (DBVER >= 41)
5965 ADD_INT(d, DB_ENCRYPT_AES);
5966 ADD_INT(d, DB_AUTO_COMMIT);
5967#else
5968 /* allow berkeleydb 4.1 aware apps to run on older versions */
5969 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5970#endif
5971
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005972 ADD_INT(d, EINVAL);
5973 ADD_INT(d, EACCES);
5974 ADD_INT(d, ENOSPC);
5975 ADD_INT(d, ENOMEM);
5976 ADD_INT(d, EAGAIN);
5977 ADD_INT(d, EBUSY);
5978 ADD_INT(d, EEXIST);
5979 ADD_INT(d, ENOENT);
5980 ADD_INT(d, EPERM);
5981
Barry Warsaw1baa9822003-03-31 19:51:29 +00005982#if (DBVER >= 40)
5983 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5984 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5985#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005986
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005987 /* The exception name must be correct for pickled exception *
5988 * objects to unpickle properly. */
5989#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5990#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5991#else
5992#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5993#endif
5994
5995 /* All the rest of the exceptions derive only from DBError */
5996#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5997 PyDict_SetItemString(d, #name, name)
5998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005999 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006000 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6001 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006002
Gregory P. Smithe9477062005-06-04 06:46:59 +00006003 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6004 * from both DBError and KeyError, since the API only supports
6005 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006006 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006007 {
Georg Brandl1a3284e2007-12-02 09:40:06 +00006008 PyObject *builtin_mod = PyImport_ImportModule("builtins");
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006009 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6010 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006011 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6012 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013 Py_file_input, d, d);
6014 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006015 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016 PyDict_DelItemString(d, "KeyError");
6017
6018
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006019#if !INCOMPLETE_IS_WARNING
6020 MAKE_EX(DBIncompleteError);
6021#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006022 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006023 MAKE_EX(DBKeyEmptyError);
6024 MAKE_EX(DBKeyExistError);
6025 MAKE_EX(DBLockDeadlockError);
6026 MAKE_EX(DBLockNotGrantedError);
6027 MAKE_EX(DBOldVersionError);
6028 MAKE_EX(DBRunRecoveryError);
6029 MAKE_EX(DBVerifyBadError);
6030 MAKE_EX(DBNoServerError);
6031 MAKE_EX(DBNoServerHomeError);
6032 MAKE_EX(DBNoServerIDError);
6033#if (DBVER >= 33)
6034 MAKE_EX(DBPageNotFoundError);
6035 MAKE_EX(DBSecondaryBadError);
6036#endif
6037
6038 MAKE_EX(DBInvalidArgError);
6039 MAKE_EX(DBAccessError);
6040 MAKE_EX(DBNoSpaceError);
6041 MAKE_EX(DBNoMemoryError);
6042 MAKE_EX(DBAgainError);
6043 MAKE_EX(DBBusyError);
6044 MAKE_EX(DBFileExistsError);
6045 MAKE_EX(DBNoSuchFileError);
6046 MAKE_EX(DBPermissionsError);
6047
6048#undef MAKE_EX
6049
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006050 /* Initiliase the C API structure and add it to the module */
6051 bsddb_api.db_type = &DB_Type;
6052 bsddb_api.dbcursor_type = &DBCursor_Type;
6053 bsddb_api.dbenv_type = &DBEnv_Type;
6054 bsddb_api.dbtxn_type = &DBTxn_Type;
6055 bsddb_api.dblock_type = &DBLock_Type;
6056#if (DBVER >= 43)
6057 bsddb_api.dbsequence_type = &DBSequence_Type;
6058#endif
6059 bsddb_api.makeDBError = makeDBError;
6060
6061 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6062 PyDict_SetItemString(d, "api", py_api);
6063 Py_DECREF(py_api);
6064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006065 /* Check for errors */
6066 if (PyErr_Occurred()) {
6067 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006068 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006069 }
6070}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006071
6072/* allow this module to be named _pybsddb so that it can be installed
6073 * and imported on top of python >= 2.3 that includes its own older
6074 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006075PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006076{
6077 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6078 init_bsddb();
6079}