blob: 648fb0da99ff63de8554f8bca7cf72b5182ff10c [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 }
Alexandre Vassalotti25078842008-06-10 16:43:26 +0000315
316 if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE))
317 return NULL;
318
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000319 if (view->ndim > 1) {
320 PyErr_SetString(PyExc_BufferError,
321 "buffers must be single dimension");
322 PyObject_ReleaseBuffer(obj, view);
323 PyMem_Free(view);
324 return NULL;
325 }
326 return view;
327}
328
329
330/* Create a DBT structure (containing key and data values) from Python
331 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000332 may be filled with a newly allocated Py_buffer view on success.
333 The caller MUST call free_buf_view() on any returned Py_buffer. */
334static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000335{
Thomas Heller39763a12007-09-24 14:43:56 +0000336 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000337
338 /* simple way to ensure the caller can detect if we've returned a
339 new buffer view or not: require their pointer to start out NULL. */
340 assert(*returned_view_p == NULL);
341
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000342 CLEAR_DBT(*dbt);
343 if (obj == Py_None) {
344 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000345 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000347 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000348 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000349 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000350 return 0;
351 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000352
353 if ( !(view = _malloc_view(obj)) )
354 return 0;
355
356 dbt->data = view->buf;
357 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
358 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000359 return 1;
360}
361
362
363/* Recno and Queue DBs can have integer keys. This function figures out
364 what's been given, verifies that it's allowed, and then makes the DBT.
365
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000366 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000367 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000368static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000369make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000370 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371{
372 db_recno_t recno;
373 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000374 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000375
376 /* simple way to ensure the caller can detect if we've returned a
377 new buffer view or not: require their pointer to start out NULL. */
378 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000379
380 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000381 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000382 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000383 if (type == -1)
384 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 if (type == DB_RECNO || type == DB_QUEUE) {
386 PyErr_SetString(
387 PyExc_TypeError,
388 "None keys not allowed for Recno and Queue DB's");
389 return 0;
390 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000391 /* no need to do anything, the structure has already been zeroed */
392 }
393
Christian Heimes217cfd12007-12-02 14:31:20 +0000394 else if (PyLong_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000395 /* verify access method type */
396 type = _DB_get_type(self);
397 if (type == -1)
398 return 0;
399 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000400 /* if BTREE then an Integer key is allowed with the
401 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000402 *pflags |= DB_SET_RECNO;
403 }
404 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000405 PyErr_SetString(
406 PyExc_TypeError,
407 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000408 return 0;
409 }
410
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000411 /* Make a key out of the requested recno, use allocated space so DB
412 * will be able to realloc room for the real key if needed. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000413 recno = PyLong_AS_LONG(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000414 key->data = malloc(sizeof(db_recno_t));
415 if (key->data == NULL) {
416 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
417 return 0;
418 }
419 key->ulen = key->size = sizeof(db_recno_t);
420 memcpy(key->data, &recno, sizeof(db_recno_t));
421 key->flags = DB_DBT_REALLOC;
422 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000423
424 else if (PyObject_CheckBuffer(keyobj)) {
425 /* verify access method type */
426 type = _DB_get_type(self);
427 if (type == -1)
428 return 0;
429 if (type == DB_RECNO || type == DB_QUEUE) {
430 PyErr_SetString(
431 PyExc_TypeError,
432 "Non-integer keys not allowed for Recno and Queue DB's");
433 return 0;
434 }
435
436 if ( !(view = _malloc_view(keyobj)) )
437 return 0;
438
Gregory P. Smith568065e2007-11-01 21:55:08 +0000439 /*
440 * NOTE(gps): I don't like doing a data copy here, it seems
441 * wasteful. But without a clean way to tell FREE_DBT if it
442 * should free key->data or not we have to. Other places in
443 * the code check for DB_THREAD and forceably set DBT_MALLOC
444 * when we otherwise would leave flags 0 to indicate that.
445 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000446 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000447 key->data = malloc(key->size);
448 if (key->data == NULL) {
449 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
450 key->size = 0;
451 return 0;
452 }
453 memcpy(key->data, view->buf, key->size);
454 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000455 *returned_view_p = view;
456 }
457
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000458 else {
459 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000460 "buffer or int object expected for key, %s found",
Christian Heimes90aa7642007-12-19 02:45:37 +0000461 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000462 return 0;
463 }
464
465 return 1;
466}
467
468
469/* Add partial record access to an existing DBT data struct.
470 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
471 and the data storage/retrieval will be done using dlen and doff. */
472static int add_partial_dbt(DBT* d, int dlen, int doff) {
473 /* if neither were set we do nothing (-1 is the default value) */
474 if ((dlen == -1) && (doff == -1)) {
475 return 1;
476 }
477
478 if ((dlen < 0) || (doff < 0)) {
479 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
480 return 0;
481 }
482
483 d->flags = d->flags | DB_DBT_PARTIAL;
484 d->dlen = (unsigned int) dlen;
485 d->doff = (unsigned int) doff;
486 return 1;
487}
488
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000489/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
490/* TODO: make this use the native libc strlcpy() when available (BSD) */
491unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
492{
493 unsigned int srclen, copylen;
494
495 srclen = strlen(src);
496 if (n <= 0)
497 return srclen;
498 copylen = (srclen > n-1) ? n-1 : srclen;
499 /* populate dest[0] thru dest[copylen-1] */
500 memcpy(dest, src, copylen);
501 /* guarantee null termination */
502 dest[copylen] = 0;
503
504 return srclen;
505}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000506
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000507/* Callback used to save away more information about errors from the DB
508 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000510#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000511static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000512#else
513static void _db_errorCallback(const DB_ENV *db_env,
514 const char* prefix, const char* msg)
515#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000516{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000517 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518}
519
520
521/* make a nice exception object to raise for errors. */
522static int makeDBError(int err)
523{
524 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000525 PyObject *errObj = NULL;
526 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000527 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000528 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000529
530 switch (err) {
531 case 0: /* successful, no error */ break;
532
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000533#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000534 case DB_INCOMPLETE:
535#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000536 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
537 /* Ensure that bytes_left never goes negative */
538 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
539 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
540 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000541 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000542 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000543 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000544 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000545 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546
547#else /* do an exception instead */
548 errObj = DBIncompleteError;
549#endif
550 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000551#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000552
553 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
554 case DB_KEYEXIST: errObj = DBKeyExistError; break;
555 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
556 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
557 case DB_NOTFOUND: errObj = DBNotFoundError; break;
558 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
559 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
560 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
561 case DB_NOSERVER: errObj = DBNoServerError; break;
562 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
563 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
564#if (DBVER >= 33)
565 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
566 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
567#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000568 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000569
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000570#if (DBVER >= 43)
571 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
572 case ENOMEM: errObj = PyExc_MemoryError; break;
573#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000574 case EINVAL: errObj = DBInvalidArgError; break;
575 case EACCES: errObj = DBAccessError; break;
576 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577 case EAGAIN: errObj = DBAgainError; break;
578 case EBUSY : errObj = DBBusyError; break;
579 case EEXIST: errObj = DBFileExistsError; break;
580 case ENOENT: errObj = DBNoSuchFileError; break;
581 case EPERM : errObj = DBPermissionsError; break;
582
583 default: errObj = DBError; break;
584 }
585
586 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000587 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
588 /* Ensure that bytes_left never goes negative */
589 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
590 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
591 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000592 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000593 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000594 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000595 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000596
597 errTuple = Py_BuildValue("(is)", err, errTxt);
598 PyErr_SetObject(errObj, errTuple);
599 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 }
601
602 return ((errObj != NULL) || exceptionRaised);
603}
604
605
606
607/* set a type exception */
608static void makeTypeError(char* expected, PyObject* found)
609{
610 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000611 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000612}
613
614
615/* verify that an obj is either None or a DBTxn, and set the txn pointer */
616static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
617{
618 if (txnobj == Py_None || txnobj == NULL) {
619 *txn = NULL;
620 return 1;
621 }
622 if (DBTxnObject_Check(txnobj)) {
623 *txn = ((DBTxnObject*)txnobj)->txn;
624 return 1;
625 }
626 else
627 makeTypeError("DBTxn", txnobj);
628 return 0;
629}
630
631
632/* Delete a key from a database
633 Returns 0 on success, -1 on an error. */
634static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
635{
636 int err;
637
638 MYDB_BEGIN_ALLOW_THREADS;
639 err = self->db->del(self->db, txn, key, 0);
640 MYDB_END_ALLOW_THREADS;
641 if (makeDBError(err)) {
642 return -1;
643 }
644 self->haveStat = 0;
645 return 0;
646}
647
648
649/* Store a key into a database
650 Returns 0 on success, -1 on an error. */
651static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
652{
653 int err;
654
655 MYDB_BEGIN_ALLOW_THREADS;
656 err = self->db->put(self->db, txn, key, data, flags);
657 MYDB_END_ALLOW_THREADS;
658 if (makeDBError(err)) {
659 return -1;
660 }
661 self->haveStat = 0;
662 return 0;
663}
664
665/* Get a key/data pair from a cursor */
666static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
667 PyObject *args, PyObject *kwargs, char *format)
668{
669 int err;
670 PyObject* retval = NULL;
671 DBT key, data;
672 int dlen = -1;
673 int doff = -1;
674 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000675 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000676
677 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
678 &flags, &dlen, &doff))
679 return NULL;
680
681 CHECK_CURSOR_NOT_CLOSED(self);
682
683 flags |= extra_flags;
684 CLEAR_DBT(key);
685 CLEAR_DBT(data);
686 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
687 /* Tell BerkeleyDB to malloc the return value (thread safe) */
688 data.flags = DB_DBT_MALLOC;
689 key.flags = DB_DBT_MALLOC;
690 }
691 if (!add_partial_dbt(&data, dlen, doff))
692 return NULL;
693
694 MYDB_BEGIN_ALLOW_THREADS;
695 err = self->dbc->c_get(self->dbc, &key, &data, flags);
696 MYDB_END_ALLOW_THREADS;
697
Gregory P. Smithe9477062005-06-04 06:46:59 +0000698 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
699 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000700 Py_INCREF(Py_None);
701 retval = Py_None;
702 }
703 else if (makeDBError(err)) {
704 retval = NULL;
705 }
706 else { /* otherwise, success! */
707
708 /* if Recno or Queue, return the key as an Int */
709 switch (_DB_get_type(self->mydb)) {
710 case -1:
711 retval = NULL;
712 break;
713
714 case DB_RECNO:
715 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000716 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000717 data.data, data.size);
718 break;
719 case DB_HASH:
720 case DB_BTREE:
721 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000722 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000723 data.data, data.size);
724 break;
725 }
726 }
727 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000728 free_dbt(&key);
729 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000730 }
731 return retval;
732}
733
734
735/* add an integer to a dictionary using the given name as a key */
736static void _addIntToDict(PyObject* dict, char *name, int value)
737{
Christian Heimes217cfd12007-12-02 14:31:20 +0000738 PyObject* v = PyLong_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000739 if (!v || PyDict_SetItemString(dict, name, v))
740 PyErr_Clear();
741
742 Py_XDECREF(v);
743}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000744
745/* The same, when the value is a time_t */
746static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
747{
748 PyObject* v;
749 /* if the value fits in regular int, use that. */
750#ifdef HAVE_LONG_LONG
751 if (sizeof(time_t) > sizeof(long))
752 v = PyLong_FromLongLong((PY_LONG_LONG) value);
753 else
754#endif
Christian Heimes217cfd12007-12-02 14:31:20 +0000755 v = PyLong_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000756 if (!v || PyDict_SetItemString(dict, name, v))
757 PyErr_Clear();
758
759 Py_XDECREF(v);
760}
761
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000762#if (DBVER >= 43)
763/* add an db_seq_t to a dictionary using the given name as a key */
764static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
765{
766 PyObject* v = PyLong_FromLongLong(value);
767 if (!v || PyDict_SetItemString(dict, name, v))
768 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000770 Py_XDECREF(v);
771}
772#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773
774
775
776/* --------------------------------------------------------------------- */
777/* Allocators and deallocators */
778
779static DBObject*
780newDBObject(DBEnvObject* arg, int flags)
781{
782 DBObject* self;
783 DB_ENV* db_env = NULL;
784 int err;
785
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000787 if (self == NULL)
788 return NULL;
789
790 self->haveStat = 0;
791 self->flags = 0;
792 self->setflags = 0;
793 self->myenvobj = NULL;
794#if (DBVER >= 33)
795 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000796 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797 self->primaryDBType = 0;
798#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000799 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000800
801 /* keep a reference to our python DBEnv object */
802 if (arg) {
803 Py_INCREF(arg);
804 self->myenvobj = arg;
805 db_env = arg->db_env;
806 }
807
808 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000809 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000811 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
812 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813
814 MYDB_BEGIN_ALLOW_THREADS;
815 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000816 if (self->db != NULL) {
817 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000819 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000820#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000821 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000822 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000823 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
824 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000825 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000826 if (makeDBError(err)) {
827 if (self->myenvobj) {
828 Py_DECREF(self->myenvobj);
829 self->myenvobj = NULL;
830 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000831 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 self = NULL;
833 }
834 return self;
835}
836
837
838static void
839DB_dealloc(DBObject* self)
840{
841 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000842 /* avoid closing a DB when its DBEnv has been closed out from under
843 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000844 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000845 (self->myenvobj && self->myenvobj->db_env))
846 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 MYDB_BEGIN_ALLOW_THREADS;
848 self->db->close(self->db, 0);
849 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000851 PyErr_WarnEx(PyExc_RuntimeWarning,
852 "DB could not be closed in destructor:"
853 " DBEnv already closed",
854 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000855 }
856 self->db = NULL;
857 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000858 if (self->in_weakreflist != NULL) {
859 PyObject_ClearWeakRefs((PyObject *) self);
860 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861 if (self->myenvobj) {
862 Py_DECREF(self->myenvobj);
863 self->myenvobj = NULL;
864 }
865#if (DBVER >= 33)
866 if (self->associateCallback != NULL) {
867 Py_DECREF(self->associateCallback);
868 self->associateCallback = NULL;
869 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000870 if (self->btCompareCallback != NULL) {
871 Py_DECREF(self->btCompareCallback);
872 self->btCompareCallback = NULL;
873 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000874#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876}
877
878
879static DBCursorObject*
880newDBCursorObject(DBC* dbc, DBObject* db)
881{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000882 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000883 if (self == NULL)
884 return NULL;
885
886 self->dbc = dbc;
887 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000888 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 Py_INCREF(self->mydb);
890 return self;
891}
892
893
894static void
895DBCursor_dealloc(DBCursorObject* self)
896{
897 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000898
Gregory P. Smitha703a212003-11-03 01:04:41 +0000899 if (self->in_weakreflist != NULL) {
900 PyObject_ClearWeakRefs((PyObject *) self);
901 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000902
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000904 /* If the underlying database has been closed, we don't
905 need to do anything. If the environment has been closed
906 we need to leak, as BerkeleyDB will crash trying to access
907 the environment. There was an exception when the
908 user closed the environment even though there still was
909 a database open. */
910 if (self->mydb->db && self->mydb->myenvobj &&
911 !self->mydb->myenvobj->closed)
Christian Heimes292d3512008-02-03 16:51:08 +0000912 /* test for: open db + no environment or non-closed environment */
913 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
914 !self->mydb->myenvobj->closed))) {
915 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000916 err = self->dbc->c_close(self->dbc);
Christian Heimes292d3512008-02-03 16:51:08 +0000917 MYDB_END_ALLOW_THREADS;
918 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000920 }
921 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000923}
924
925
926static DBEnvObject*
927newDBEnvObject(int flags)
928{
929 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000930 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931 if (self == NULL)
932 return NULL;
933
934 self->closed = 1;
935 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000936 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
937 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000938 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939
940 MYDB_BEGIN_ALLOW_THREADS;
941 err = db_env_create(&self->db_env, flags);
942 MYDB_END_ALLOW_THREADS;
943 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000944 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945 self = NULL;
946 }
947 else {
948 self->db_env->set_errcall(self->db_env, _db_errorCallback);
949 }
950 return self;
951}
952
953
954static void
955DBEnv_dealloc(DBEnvObject* self)
956{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000957 if (self->in_weakreflist != NULL) {
958 PyObject_ClearWeakRefs((PyObject *) self);
959 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000960
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000961 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962 MYDB_BEGIN_ALLOW_THREADS;
963 self->db_env->close(self->db_env, 0);
964 MYDB_END_ALLOW_THREADS;
965 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000966 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000967}
968
969
970static DBTxnObject*
971newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
972{
973 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000974 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975 if (self == NULL)
976 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000977 Py_INCREF(myenv);
978 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000979 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980
981 MYDB_BEGIN_ALLOW_THREADS;
982#if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984#else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000989 Py_DECREF(self->env);
990 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000991 self = NULL;
992 }
993 return self;
994}
995
996
997static void
998DBTxn_dealloc(DBTxnObject* self)
999{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000 if (self->in_weakreflist != NULL) {
1001 PyObject_ClearWeakRefs((PyObject *) self);
1002 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001003
Gregory P. Smith31c50652004-06-28 01:20:40 +00001004 if (self->txn) {
1005 /* it hasn't been finalized, abort it! */
1006 MYDB_BEGIN_ALLOW_THREADS;
1007#if (DBVER >= 40)
1008 self->txn->abort(self->txn);
1009#else
1010 txn_abort(self->txn);
1011#endif
1012 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001013 PyErr_WarnEx(PyExc_RuntimeWarning,
1014 "DBTxn aborted in destructor. "
1015 " No prior commit() or abort().",
1016 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001017 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001018
Neal Norwitz62a21122006-01-25 05:21:55 +00001019 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001021}
1022
1023
1024static DBLockObject*
1025newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1026 db_lockmode_t lock_mode, int flags)
1027{
1028 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001029 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001030 if (self == NULL)
1031 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001032 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033
1034 MYDB_BEGIN_ALLOW_THREADS;
1035#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001036 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1037 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001038#else
1039 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1040#endif
1041 MYDB_END_ALLOW_THREADS;
1042 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001043 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 self = NULL;
1045 }
1046
1047 return self;
1048}
1049
1050
1051static void
1052DBLock_dealloc(DBLockObject* self)
1053{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001054 if (self->in_weakreflist != NULL) {
1055 PyObject_ClearWeakRefs((PyObject *) self);
1056 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001057 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001059 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060}
1061
1062
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001063#if (DBVER >= 43)
1064static DBSequenceObject*
1065newDBSequenceObject(DBObject* mydb, int flags)
1066{
1067 int err;
1068 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1069 if (self == NULL)
1070 return NULL;
1071 Py_INCREF(mydb);
1072 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001073 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001074
1075
1076 MYDB_BEGIN_ALLOW_THREADS;
1077 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1078 MYDB_END_ALLOW_THREADS;
1079 if (makeDBError(err)) {
1080 Py_DECREF(self->mydb);
1081 PyObject_Del(self);
1082 self = NULL;
1083 }
1084
1085 return self;
1086}
1087
1088
1089static void
1090DBSequence_dealloc(DBSequenceObject* self)
1091{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001092 if (self->in_weakreflist != NULL) {
1093 PyObject_ClearWeakRefs((PyObject *) self);
1094 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001095
1096 Py_DECREF(self->mydb);
1097 PyObject_Del(self);
1098}
1099#endif
1100
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001101/* --------------------------------------------------------------------- */
1102/* DB methods */
1103
1104static PyObject*
1105DB_append(DBObject* self, PyObject* args)
1106{
1107 PyObject* txnobj = NULL;
1108 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001109 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001110 db_recno_t recno;
1111 DBT key, data;
1112 DB_TXN *txn = NULL;
1113
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001114 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001115 return NULL;
1116
1117 CHECK_DB_NOT_CLOSED(self);
1118
1119 /* make a dummy key out of a recno */
1120 recno = 0;
1121 CLEAR_DBT(key);
1122 key.data = &recno;
1123 key.size = sizeof(recno);
1124 key.ulen = key.size;
1125 key.flags = DB_DBT_USERMEM;
1126
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001128 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001129
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001130 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1131 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001133 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001134
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001135 free_buf_view(dataobj, data_buf_view);
Christian Heimes217cfd12007-12-02 14:31:20 +00001136 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001137}
1138
1139
1140#if (DBVER >= 33)
1141
1142static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001143_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1144 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001145{
1146 int retval = DB_DONOTINDEX;
1147 DBObject* secondaryDB = (DBObject*)db->app_private;
1148 PyObject* callback = secondaryDB->associateCallback;
1149 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001150 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001151 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152
1153
1154 if (callback != NULL) {
1155 MYDB_BEGIN_BLOCK_THREADS;
1156
Thomas Woutersb3153832006-03-08 01:47:19 +00001157 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001158 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001159 priData->data, priData->size);
1160 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001161 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001162 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001163 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001164 result = PyEval_CallObject(callback, args);
1165 }
1166 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001167 PyErr_Print();
1168 }
1169 else if (result == Py_None) {
1170 retval = DB_DONOTINDEX;
1171 }
Christian Heimes217cfd12007-12-02 14:31:20 +00001172 else if (PyLong_Check(result)) {
1173 retval = PyLong_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174 }
Christian Heimes72b710a2008-05-26 13:28:38 +00001175 else if (PyByteArray_Check(result) || PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001177 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001178
1179 CLEAR_DBT(*secKey);
Christian Heimes90aa7642007-12-19 02:45:37 +00001180 size = Py_SIZE(result);
Christian Heimes9c4756e2008-05-26 13:22:05 +00001181 if (PyByteArray_Check(result))
1182 data = PyByteArray_AS_STRING(result);
Guido van Rossum98297ee2007-11-06 21:34:58 +00001183 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001184 data = PyBytes_AS_STRING(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001185 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1186 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001187 if (secKey->data) {
1188 memcpy(secKey->data, data, size);
1189 secKey->size = size;
1190 retval = 0;
1191 }
1192 else {
1193 PyErr_SetString(PyExc_MemoryError,
1194 "malloc failed in _db_associateCallback");
1195 PyErr_Print();
1196 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001197 }
1198 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001199 PyErr_SetString(
1200 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001201 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001202 PyErr_Print();
1203 }
1204
Thomas Woutersb3153832006-03-08 01:47:19 +00001205 Py_XDECREF(args);
1206 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207
1208 MYDB_END_BLOCK_THREADS;
1209 }
1210 return retval;
1211}
1212
1213
1214static PyObject*
1215DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1216{
1217 int err, flags=0;
1218 DBObject* secondaryDB;
1219 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001220#if (DBVER >= 41)
1221 PyObject *txnobj = NULL;
1222 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001223 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001224 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001226 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001227#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001229#if (DBVER >= 41)
1230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1231 &secondaryDB, &callback, &flags,
1232 &txnobj)) {
1233#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235 &secondaryDB, &callback, &flags)) {
1236#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001238 }
1239
1240#if (DBVER >= 41)
1241 if (!checkTxnObj(txnobj, &txn)) return NULL;
1242#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001243
1244 CHECK_DB_NOT_CLOSED(self);
1245 if (!DBObject_Check(secondaryDB)) {
1246 makeTypeError("DB", (PyObject*)secondaryDB);
1247 return NULL;
1248 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001249 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250 if (callback == Py_None) {
1251 callback = NULL;
1252 }
1253 else if (!PyCallable_Check(callback)) {
1254 makeTypeError("Callable", callback);
1255 return NULL;
1256 }
1257
1258 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001259 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001260 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001261 secondaryDB->associateCallback = callback;
1262 secondaryDB->primaryDBType = _DB_get_type(self);
1263
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001264 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1265 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1266 * The global interepreter lock is not initialized until the first
1267 * thread is created using thread.start_new_thread() or fork() is
1268 * called. that would cause the ALLOW_THREADS here to segfault due
1269 * to a null pointer reference if no threads or child processes
1270 * have been created. This works around that and is a no-op if
1271 * threads have already been initialized.
1272 * (see pybsddb-users mailing list post on 2002-08-07)
1273 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001274#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001275 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001276#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001278#if (DBVER >= 41)
1279 err = self->db->associate(self->db,
1280 txn,
1281 secondaryDB->db,
1282 _db_associateCallback,
1283 flags);
1284#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 err = self->db->associate(self->db,
1286 secondaryDB->db,
1287 _db_associateCallback,
1288 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001289#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290 MYDB_END_ALLOW_THREADS;
1291
1292 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001293 Py_XDECREF(secondaryDB->associateCallback);
1294 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001295 secondaryDB->primaryDBType = 0;
1296 }
1297
1298 RETURN_IF_ERR();
1299 RETURN_NONE();
1300}
1301
1302
1303#endif
1304
1305
1306static PyObject*
1307DB_close(DBObject* self, PyObject* args)
1308{
1309 int err, flags=0;
1310 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1311 return NULL;
1312 if (self->db != NULL) {
1313 if (self->myenvobj)
1314 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 self->db = NULL;
1317 RETURN_IF_ERR();
1318 }
1319 RETURN_NONE();
1320}
1321
1322
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323static PyObject*
1324_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1325{
1326 int err, flags=0, type;
1327 PyObject* txnobj = NULL;
1328 PyObject* retval = NULL;
1329 DBT key, data;
1330 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001331 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1336
1337 CHECK_DB_NOT_CLOSED(self);
1338 type = _DB_get_type(self);
1339 if (type == -1)
1340 return NULL;
1341 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342 PyErr_SetString(PyExc_TypeError,
1343 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001344 return NULL;
1345 }
1346 if (!checkTxnObj(txnobj, &txn))
1347 return NULL;
1348
1349 CLEAR_DBT(key);
1350 CLEAR_DBT(data);
1351 if (CHECK_DBFLAG(self, DB_THREAD)) {
1352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1353 data.flags = DB_DBT_MALLOC;
1354 key.flags = DB_DBT_MALLOC;
1355 }
1356
1357 MYDB_BEGIN_ALLOW_THREADS;
1358 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1359 MYDB_END_ALLOW_THREADS;
1360
Gregory P. Smithe9477062005-06-04 06:46:59 +00001361 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1362 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1366 }
1367 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001368 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001370 free_dbt(&key);
1371 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001372 }
1373
1374 RETURN_IF_ERR();
1375 return retval;
1376}
1377
1378static PyObject*
1379DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1380{
1381 return _DB_consume(self, args, kwargs, DB_CONSUME);
1382}
1383
1384static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001385DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1386 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001387{
1388 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1389}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001390
1391
1392static PyObject*
1393DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1394{
1395 int err, flags=0;
1396 DBC* dbc;
1397 PyObject* txnobj = NULL;
1398 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001399 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001400
1401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1402 &txnobj, &flags))
1403 return NULL;
1404 CHECK_DB_NOT_CLOSED(self);
1405 if (!checkTxnObj(txnobj, &txn))
1406 return NULL;
1407
1408 MYDB_BEGIN_ALLOW_THREADS;
1409 err = self->db->cursor(self->db, txn, &dbc, flags);
1410 MYDB_END_ALLOW_THREADS;
1411 RETURN_IF_ERR();
1412 return (PyObject*) newDBCursorObject(dbc, self);
1413}
1414
1415
1416static PyObject*
1417DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1418{
1419 PyObject* txnobj = NULL;
1420 int flags = 0;
1421 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001422 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423 DBT key;
1424 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001425 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001426
1427 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1428 &keyobj, &txnobj, &flags))
1429 return NULL;
1430 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001431 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001432 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001433 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001434 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001436 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001438 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001439 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001440 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001441 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001442
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001443 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001444 RETURN_NONE();
1445}
1446
1447
1448static PyObject*
1449DB_fd(DBObject* self, PyObject* args)
1450{
1451 int err, the_fd;
1452
1453 if (!PyArg_ParseTuple(args,":fd"))
1454 return NULL;
1455 CHECK_DB_NOT_CLOSED(self);
1456
1457 MYDB_BEGIN_ALLOW_THREADS;
1458 err = self->db->fd(self->db, &the_fd);
1459 MYDB_END_ALLOW_THREADS;
1460 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00001461 return PyLong_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001462}
1463
1464
1465static PyObject*
1466DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1467{
1468 int err, flags=0;
1469 PyObject* txnobj = NULL;
1470 PyObject* keyobj;
1471 PyObject* dfltobj = NULL;
1472 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001473 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, data;
1477 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001478 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001479 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001480
1481 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001482 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1483 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 return NULL;
1485
1486 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001487 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001488 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001489 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001490 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001492 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493
1494 CLEAR_DBT(data);
1495 if (CHECK_DBFLAG(self, DB_THREAD)) {
1496 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1497 data.flags = DB_DBT_MALLOC;
1498 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001499 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001500 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001501 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001502 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503
1504 MYDB_BEGIN_ALLOW_THREADS;
1505 err = self->db->get(self->db, txn, &key, &data, flags);
1506 MYDB_END_ALLOW_THREADS;
1507
Gregory P. Smithe9477062005-06-04 06:46:59 +00001508 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001509 err = 0;
1510 Py_INCREF(dfltobj);
1511 retval = dfltobj;
1512 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001513 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1514 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515 err = 0;
1516 Py_INCREF(Py_None);
1517 retval = Py_None;
1518 }
1519 else if (!err) {
1520 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001521 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001522 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001523 else /* return just the data */
Christian Heimes72b710a2008-05-26 13:28:38 +00001524 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001525 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001526 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001527 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528
1529 RETURN_IF_ERR();
1530 return retval;
1531}
1532
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001533#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001534static PyObject*
1535DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1536{
1537 int err, flags=0;
1538 PyObject* txnobj = NULL;
1539 PyObject* keyobj;
1540 PyObject* dfltobj = NULL;
1541 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001542 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001543 int dlen = -1;
1544 int doff = -1;
1545 DBT key, pkey, data;
1546 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001547 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001548 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001549
1550 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1551 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1552 &doff))
1553 return NULL;
1554
1555 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001556 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001557 return NULL;
1558 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001559 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001560 return NULL;
1561 }
1562
1563 CLEAR_DBT(data);
1564 if (CHECK_DBFLAG(self, DB_THREAD)) {
1565 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1566 data.flags = DB_DBT_MALLOC;
1567 }
1568 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001569 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001570 return NULL;
1571 }
1572
1573 CLEAR_DBT(pkey);
1574 pkey.flags = DB_DBT_MALLOC;
1575
1576 MYDB_BEGIN_ALLOW_THREADS;
1577 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1578 MYDB_END_ALLOW_THREADS;
1579
Gregory P. Smithe9477062005-06-04 06:46:59 +00001580 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001581 err = 0;
1582 Py_INCREF(dfltobj);
1583 retval = dfltobj;
1584 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001585 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1586 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001587 err = 0;
1588 Py_INCREF(Py_None);
1589 retval = Py_None;
1590 }
1591 else if (!err) {
1592 PyObject *pkeyObj;
1593 PyObject *dataObj;
Christian Heimes72b710a2008-05-26 13:28:38 +00001594 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595
1596 if (self->primaryDBType == DB_RECNO ||
1597 self->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001598 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001599 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001600 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001601
1602 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1603 {
1604 PyObject *keyObj;
1605 int type = _DB_get_type(self);
1606 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001607 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001608 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001609 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001610#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001611 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001612#else
1613 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1614#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001615 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616 }
1617 else /* return just the pkey and data */
1618 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001619#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001620 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001621#else
1622 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1623#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001625 Py_DECREF(dataObj);
1626 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001627 free_dbt(&pkey);
1628 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001629 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001630 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001631
1632 RETURN_IF_ERR();
1633 return retval;
1634}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001635#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001636
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637
1638/* Return size of entry */
1639static PyObject*
1640DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1641{
1642 int err, flags=0;
1643 PyObject* txnobj = NULL;
1644 PyObject* keyobj;
1645 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001646 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001647 DBT key, data;
1648 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001649 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001650
1651 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1652 &keyobj, &txnobj))
1653 return NULL;
1654 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001655 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001656 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001657 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001658 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001660 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 CLEAR_DBT(data);
1662
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001663 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1664 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001665 data.flags = DB_DBT_USERMEM;
1666 data.ulen = 0;
1667 MYDB_BEGIN_ALLOW_THREADS;
1668 err = self->db->get(self->db, txn, &key, &data, flags);
1669 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001670 if (err == DB_BUFFER_SMALL) {
Christian Heimes217cfd12007-12-02 14:31:20 +00001671 retval = PyLong_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001672 err = 0;
1673 }
1674
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001675 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1676 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001677 RETURN_IF_ERR();
1678 return retval;
1679}
1680
1681
1682static PyObject*
1683DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1684{
1685 int err, flags=0;
1686 PyObject* txnobj = NULL;
1687 PyObject* keyobj;
1688 PyObject* dataobj;
1689 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001690 Py_buffer* data_buf_view = NULL;
1691 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001693 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001694 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001695 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696
1697
1698 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1699 &keyobj, &dataobj, &txnobj, &flags))
1700 return NULL;
1701
1702 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001703 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001705 if ( !checkTxnObj(txnobj, &txn) ||
1706 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001707 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001708 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001709 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001710 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001711
1712 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001713 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714
1715 if (CHECK_DBFLAG(self, DB_THREAD)) {
1716 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001717 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001718 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001719 }
1720
1721 MYDB_BEGIN_ALLOW_THREADS;
1722 err = self->db->get(self->db, txn, &key, &data, flags);
1723 MYDB_END_ALLOW_THREADS;
1724
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001725 free_buf_view(dataobj, data_buf_view);
1726
Gregory P. Smithe9477062005-06-04 06:46:59 +00001727 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1728 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729 err = 0;
1730 Py_INCREF(Py_None);
1731 retval = Py_None;
1732 }
1733 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001734 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001735 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001736 /* XXX(guido) But what if the input is PyString? */
Christian Heimes72b710a2008-05-26 13:28:38 +00001737 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001738
1739 /* Even though the flags require DB_DBT_MALLOC, data is not always
1740 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1741 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001742 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001743 }
1744
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001745 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746 RETURN_IF_ERR();
1747 return retval;
1748}
1749
1750
1751static PyObject*
1752DB_get_byteswapped(DBObject* self, PyObject* args)
1753{
1754#if (DBVER >= 33)
1755 int err = 0;
1756#endif
1757 int retval = -1;
1758
1759 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1760 return NULL;
1761 CHECK_DB_NOT_CLOSED(self);
1762
1763#if (DBVER >= 33)
1764 MYDB_BEGIN_ALLOW_THREADS;
1765 err = self->db->get_byteswapped(self->db, &retval);
1766 MYDB_END_ALLOW_THREADS;
1767 RETURN_IF_ERR();
1768#else
1769 MYDB_BEGIN_ALLOW_THREADS;
1770 retval = self->db->get_byteswapped(self->db);
1771 MYDB_END_ALLOW_THREADS;
1772#endif
Christian Heimes217cfd12007-12-02 14:31:20 +00001773 return PyLong_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001774}
1775
1776
1777static PyObject*
1778DB_get_type(DBObject* self, PyObject* args)
1779{
1780 int type;
1781
1782 if (!PyArg_ParseTuple(args,":get_type"))
1783 return NULL;
1784 CHECK_DB_NOT_CLOSED(self);
1785
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001787 if (type == -1)
1788 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00001789 return PyLong_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001790}
1791
1792
1793static PyObject*
1794DB_join(DBObject* self, PyObject* args)
1795{
1796 int err, flags=0;
1797 int length, x;
1798 PyObject* cursorsObj;
1799 DBC** cursors;
1800 DBC* dbc;
1801
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1803 return NULL;
1804
1805 CHECK_DB_NOT_CLOSED(self);
1806
1807 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001808 PyErr_SetString(PyExc_TypeError,
1809 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001810 return NULL;
1811 }
1812
1813 length = PyObject_Length(cursorsObj);
1814 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001815 if (!cursors) {
1816 PyErr_NoMemory();
1817 return NULL;
1818 }
1819
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001820 cursors[length] = NULL;
1821 for (x=0; x<length; x++) {
1822 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001823 if (item == NULL) {
1824 free(cursors);
1825 return NULL;
1826 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001827 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001828 PyErr_SetString(PyExc_TypeError,
1829 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001830 free(cursors);
1831 return NULL;
1832 }
1833 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001834 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001835 }
1836
1837 MYDB_BEGIN_ALLOW_THREADS;
1838 err = self->db->join(self->db, cursors, &dbc, flags);
1839 MYDB_END_ALLOW_THREADS;
1840 free(cursors);
1841 RETURN_IF_ERR();
1842
Gregory P. Smith7441e652003-11-03 21:35:31 +00001843 /* FIXME: this is a buggy interface. The returned cursor
1844 contains internal references to the passed in cursors
1845 but does not hold python references to them or prevent
1846 them from being closed prematurely. This can cause
1847 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 return (PyObject*) newDBCursorObject(dbc, self);
1849}
1850
1851
1852static PyObject*
1853DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1854{
1855 int err, flags=0;
1856 PyObject* txnobj = NULL;
1857 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001858 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859 DBT key;
1860 DB_TXN *txn = NULL;
1861 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001862 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001863
1864 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1865 &keyobj, &txnobj, &flags))
1866 return NULL;
1867 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001868 if (!checkTxnObj(txnobj, &txn))
1869 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001870 if (!make_dbt(keyobj, &key, &key_buf_view))
1871 /* BTree only, don't need to allow for an int key */
1872 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001873
1874 MYDB_BEGIN_ALLOW_THREADS;
1875 err = self->db->key_range(self->db, txn, &key, &range, flags);
1876 MYDB_END_ALLOW_THREADS;
1877
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001878 free_buf_view(keyobj, key_buf_view);
1879
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001880 RETURN_IF_ERR();
1881 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1882}
1883
1884
1885static PyObject*
1886DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1887{
1888 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1889 char* filename = NULL;
1890 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001891#if (DBVER >= 41)
1892 PyObject *txnobj = NULL;
1893 DB_TXN *txn = NULL;
1894 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001895 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001896 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1897 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001898 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001899 "filename", "dbtype", "flags", "mode", "txn", NULL};
1900#else
1901 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001902 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001903 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1904 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001905 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001906 "filename", "dbtype", "flags", "mode", NULL};
1907#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001908
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001909#if (DBVER >= 41)
1910 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1911 &filename, &dbname, &type, &flags, &mode,
1912 &txnobj))
1913#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001914 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001915 &filename, &dbname, &type, &flags,
1916 &mode))
1917#endif
1918 {
1919 PyErr_Clear();
1920 type = DB_UNKNOWN; flags = 0; mode = 0660;
1921 filename = NULL; dbname = NULL;
1922#if (DBVER >= 41)
1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1924 kwnames_basic,
1925 &filename, &type, &flags, &mode,
1926 &txnobj))
1927 return NULL;
1928#else
1929 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1930 kwnames_basic,
1931 &filename, &type, &flags, &mode))
1932 return NULL;
1933#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001934 }
1935
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001936#if (DBVER >= 41)
1937 if (!checkTxnObj(txnobj, &txn)) return NULL;
1938#endif
1939
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001941 PyObject *t = Py_BuildValue("(is)", 0,
1942 "Cannot call open() twice for DB object");
1943 PyErr_SetObject(DBError, t);
1944 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945 return NULL;
1946 }
1947
1948 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001949#if (DBVER >= 41)
1950 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1951#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001953#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 MYDB_END_ALLOW_THREADS;
1955 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001956 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 self->db = NULL;
1958 return NULL;
1959 }
1960
Guido van Rossum77677112007-11-05 19:43:04 +00001961#if (DBVER >= 42)
1962 self->db->get_flags(self->db, &self->setflags);
1963#endif
1964
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 self->flags = flags;
1966 RETURN_NONE();
1967}
1968
1969
1970static PyObject*
1971DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1972{
1973 int flags=0;
1974 PyObject* txnobj = NULL;
1975 int dlen = -1;
1976 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001977 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001978 Py_buffer *data_buf_view = NULL;
1979 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001980 DBT key, data;
1981 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001982 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001983 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984
1985 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1986 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1987 return NULL;
1988
1989 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001990 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001991 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001992 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001993 !add_partial_dbt(&data, dlen, doff) ||
1994 !checkTxnObj(txnobj, &txn) )
1995 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001996 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1997 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001998 return NULL;
1999 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000
2001 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002002 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2003 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002004 return NULL;
2005 }
2006
2007 if (flags & DB_APPEND)
Christian Heimes217cfd12007-12-02 14:31:20 +00002008 retval = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002009 else {
2010 retval = Py_None;
2011 Py_INCREF(retval);
2012 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002013 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2014 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002015 return retval;
2016}
2017
2018
2019
2020static PyObject*
2021DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2022{
2023 char* filename;
2024 char* database = NULL;
2025 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002026 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002027
2028 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2029 &filename, &database, &flags))
2030 return NULL;
2031 CHECK_DB_NOT_CLOSED(self);
2032
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002033 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002034 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035 RETURN_IF_ERR();
2036 RETURN_NONE();
2037}
2038
2039
2040
2041static PyObject*
2042DB_rename(DBObject* self, PyObject* args)
2043{
2044 char* filename;
2045 char* database;
2046 char* newname;
2047 int err, flags=0;
2048
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002049 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2050 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002051 return NULL;
2052 CHECK_DB_NOT_CLOSED(self);
2053
2054 MYDB_BEGIN_ALLOW_THREADS;
2055 err = self->db->rename(self->db, filename, database, newname, flags);
2056 MYDB_END_ALLOW_THREADS;
2057 RETURN_IF_ERR();
2058 RETURN_NONE();
2059}
2060
2061
2062static PyObject*
2063DB_set_bt_minkey(DBObject* self, PyObject* args)
2064{
2065 int err, minkey;
2066
2067 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2068 return NULL;
2069 CHECK_DB_NOT_CLOSED(self);
2070
2071 MYDB_BEGIN_ALLOW_THREADS;
2072 err = self->db->set_bt_minkey(self->db, minkey);
2073 MYDB_END_ALLOW_THREADS;
2074 RETURN_IF_ERR();
2075 RETURN_NONE();
2076}
2077
Neal Norwitz84562352005-10-20 04:30:15 +00002078#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002079static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002080_default_cmp(const DBT *leftKey,
2081 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002082{
2083 int res;
2084 int lsize = leftKey->size, rsize = rightKey->size;
2085
Georg Brandlef1701f2006-03-07 14:57:48 +00002086 res = memcmp(leftKey->data, rightKey->data,
2087 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002088
2089 if (res == 0) {
2090 if (lsize < rsize) {
2091 res = -1;
2092 }
2093 else if (lsize > rsize) {
2094 res = 1;
2095 }
2096 }
2097 return res;
2098}
2099
2100static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002101_db_compareCallback(DB* db,
2102 const DBT *leftKey,
2103 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104{
2105 int res = 0;
2106 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002107 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109
2110 if (self == NULL || self->btCompareCallback == NULL) {
2111 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002112 PyErr_SetString(PyExc_TypeError,
2113 (self == 0
2114 ? "DB_bt_compare db is NULL."
2115 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002116 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002117 PyErr_Print();
2118 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002119 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002121 MYDB_BEGIN_BLOCK_THREADS;
2122
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002123 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002124 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002125 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002126 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002129 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002130 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 PyErr_Print();
2133 res = _default_cmp(leftKey, rightKey);
Christian Heimes217cfd12007-12-02 14:31:20 +00002134 } else if (PyLong_Check(result)) {
2135 res = PyLong_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002136 } else {
2137 PyErr_SetString(PyExc_TypeError,
2138 "DB_bt_compare callback MUST return an int.");
2139 /* we're in a callback within the DB code, we can't raise */
2140 PyErr_Print();
2141 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142 }
2143
Thomas Woutersb3153832006-03-08 01:47:19 +00002144 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002145 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146
2147 MYDB_END_BLOCK_THREADS;
2148 }
2149 return res;
2150}
2151
2152static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002153DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002154{
2155 int err;
2156 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002157 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002158
Georg Brandlef1701f2006-03-07 14:57:48 +00002159 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002160 return NULL;
2161
Georg Brandlef1701f2006-03-07 14:57:48 +00002162 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002163
Georg Brandlef1701f2006-03-07 14:57:48 +00002164 if (!PyCallable_Check(comparator)) {
2165 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002166 return NULL;
2167 }
2168
2169 /*
2170 * Perform a test call of the comparator function with two empty
2171 * string objects here. verify that it returns an int (0).
2172 * err if not.
2173 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002174 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002175 result = PyEval_CallObject(comparator, tuple);
2176 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002177 if (result == NULL)
2178 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002179 if (!PyLong_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 PyErr_SetString(PyExc_TypeError,
2181 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002183 } else if (PyLong_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002184 PyErr_SetString(PyExc_TypeError,
2185 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002186 return NULL;
2187 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002188 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002189
2190 /* We don't accept multiple set_bt_compare operations, in order to
2191 * simplify the code. This would have no real use, as one cannot
2192 * change the function once the db is opened anyway */
2193 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002194 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002195 return NULL;
2196 }
2197
Georg Brandlef1701f2006-03-07 14:57:48 +00002198 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002199 self->btCompareCallback = comparator;
2200
2201 /* This is to workaround a problem with un-initialized threads (see
2202 comment in DB_associate) */
2203#ifdef WITH_THREAD
2204 PyEval_InitThreads();
2205#endif
2206
Thomas Woutersb3153832006-03-08 01:47:19 +00002207 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002208
2209 if (err) {
2210 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002211 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002212 self->btCompareCallback = NULL;
2213 }
2214
Georg Brandlef1701f2006-03-07 14:57:48 +00002215 RETURN_IF_ERR();
2216 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002217}
Neal Norwitz84562352005-10-20 04:30:15 +00002218#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002220
2221static PyObject*
2222DB_set_cachesize(DBObject* self, PyObject* args)
2223{
2224 int err;
2225 int gbytes = 0, bytes = 0, ncache = 0;
2226
2227 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2228 &gbytes,&bytes,&ncache))
2229 return NULL;
2230 CHECK_DB_NOT_CLOSED(self);
2231
2232 MYDB_BEGIN_ALLOW_THREADS;
2233 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2234 MYDB_END_ALLOW_THREADS;
2235 RETURN_IF_ERR();
2236 RETURN_NONE();
2237}
2238
2239
2240static PyObject*
2241DB_set_flags(DBObject* self, PyObject* args)
2242{
2243 int err, flags;
2244
2245 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2246 return NULL;
2247 CHECK_DB_NOT_CLOSED(self);
2248
2249 MYDB_BEGIN_ALLOW_THREADS;
2250 err = self->db->set_flags(self->db, flags);
2251 MYDB_END_ALLOW_THREADS;
2252 RETURN_IF_ERR();
2253
2254 self->setflags |= flags;
2255 RETURN_NONE();
2256}
2257
2258
2259static PyObject*
2260DB_set_h_ffactor(DBObject* self, PyObject* args)
2261{
2262 int err, ffactor;
2263
2264 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2265 return NULL;
2266 CHECK_DB_NOT_CLOSED(self);
2267
2268 MYDB_BEGIN_ALLOW_THREADS;
2269 err = self->db->set_h_ffactor(self->db, ffactor);
2270 MYDB_END_ALLOW_THREADS;
2271 RETURN_IF_ERR();
2272 RETURN_NONE();
2273}
2274
2275
2276static PyObject*
2277DB_set_h_nelem(DBObject* self, PyObject* args)
2278{
2279 int err, nelem;
2280
2281 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2282 return NULL;
2283 CHECK_DB_NOT_CLOSED(self);
2284
2285 MYDB_BEGIN_ALLOW_THREADS;
2286 err = self->db->set_h_nelem(self->db, nelem);
2287 MYDB_END_ALLOW_THREADS;
2288 RETURN_IF_ERR();
2289 RETURN_NONE();
2290}
2291
2292
2293static PyObject*
2294DB_set_lorder(DBObject* self, PyObject* args)
2295{
2296 int err, lorder;
2297
2298 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2299 return NULL;
2300 CHECK_DB_NOT_CLOSED(self);
2301
2302 MYDB_BEGIN_ALLOW_THREADS;
2303 err = self->db->set_lorder(self->db, lorder);
2304 MYDB_END_ALLOW_THREADS;
2305 RETURN_IF_ERR();
2306 RETURN_NONE();
2307}
2308
2309
2310static PyObject*
2311DB_set_pagesize(DBObject* self, PyObject* args)
2312{
2313 int err, pagesize;
2314
2315 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2316 return NULL;
2317 CHECK_DB_NOT_CLOSED(self);
2318
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->set_pagesize(self->db, pagesize);
2321 MYDB_END_ALLOW_THREADS;
2322 RETURN_IF_ERR();
2323 RETURN_NONE();
2324}
2325
2326
2327static PyObject*
2328DB_set_re_delim(DBObject* self, PyObject* args)
2329{
2330 int err;
2331 char delim;
2332
2333 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2334 PyErr_Clear();
2335 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2336 return NULL;
2337 }
2338
2339 CHECK_DB_NOT_CLOSED(self);
2340
2341 MYDB_BEGIN_ALLOW_THREADS;
2342 err = self->db->set_re_delim(self->db, delim);
2343 MYDB_END_ALLOW_THREADS;
2344 RETURN_IF_ERR();
2345 RETURN_NONE();
2346}
2347
2348static PyObject*
2349DB_set_re_len(DBObject* self, PyObject* args)
2350{
2351 int err, len;
2352
2353 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2354 return NULL;
2355 CHECK_DB_NOT_CLOSED(self);
2356
2357 MYDB_BEGIN_ALLOW_THREADS;
2358 err = self->db->set_re_len(self->db, len);
2359 MYDB_END_ALLOW_THREADS;
2360 RETURN_IF_ERR();
2361 RETURN_NONE();
2362}
2363
2364
2365static PyObject*
2366DB_set_re_pad(DBObject* self, PyObject* args)
2367{
2368 int err;
2369 char pad;
2370
2371 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2372 PyErr_Clear();
2373 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2374 return NULL;
2375 }
2376 CHECK_DB_NOT_CLOSED(self);
2377
2378 MYDB_BEGIN_ALLOW_THREADS;
2379 err = self->db->set_re_pad(self->db, pad);
2380 MYDB_END_ALLOW_THREADS;
2381 RETURN_IF_ERR();
2382 RETURN_NONE();
2383}
2384
2385
2386static PyObject*
2387DB_set_re_source(DBObject* self, PyObject* args)
2388{
2389 int err;
2390 char *re_source;
2391
2392 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2393 return NULL;
2394 CHECK_DB_NOT_CLOSED(self);
2395
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_re_source(self->db, re_source);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2400 RETURN_NONE();
2401}
2402
2403
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002404static PyObject*
2405DB_set_q_extentsize(DBObject* self, PyObject* args)
2406{
2407 int err;
2408 int extentsize;
2409
2410 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2413
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_q_extentsize(self->db, extentsize);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2419}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002420
2421static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002422DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002423{
2424 int err, flags = 0, type;
2425 void* sp;
2426 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002427#if (DBVER >= 43)
2428 PyObject* txnobj = NULL;
2429 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002430 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002431#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002432 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002433#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002434
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002435#if (DBVER >= 43)
2436 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2437 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002438 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002439 if (!checkTxnObj(txnobj, &txn))
2440 return NULL;
2441#else
2442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2443 return NULL;
2444#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002445 CHECK_DB_NOT_CLOSED(self);
2446
2447 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002448#if (DBVER >= 43)
2449 err = self->db->stat(self->db, txn, &sp, flags);
2450#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002451 err = self->db->stat(self->db, &sp, flags);
2452#else
2453 err = self->db->stat(self->db, &sp, NULL, flags);
2454#endif
2455 MYDB_END_ALLOW_THREADS;
2456 RETURN_IF_ERR();
2457
2458 self->haveStat = 1;
2459
2460 /* Turn the stat structure into a dictionary */
2461 type = _DB_get_type(self);
2462 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2463 free(sp);
2464 return NULL;
2465 }
2466
2467#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2468#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2469#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2470
2471 switch (type) {
2472 case DB_HASH:
2473 MAKE_HASH_ENTRY(magic);
2474 MAKE_HASH_ENTRY(version);
2475 MAKE_HASH_ENTRY(nkeys);
2476 MAKE_HASH_ENTRY(ndata);
2477 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002478#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002479 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002480#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002481 MAKE_HASH_ENTRY(ffactor);
2482 MAKE_HASH_ENTRY(buckets);
2483 MAKE_HASH_ENTRY(free);
2484 MAKE_HASH_ENTRY(bfree);
2485 MAKE_HASH_ENTRY(bigpages);
2486 MAKE_HASH_ENTRY(big_bfree);
2487 MAKE_HASH_ENTRY(overflows);
2488 MAKE_HASH_ENTRY(ovfl_free);
2489 MAKE_HASH_ENTRY(dup);
2490 MAKE_HASH_ENTRY(dup_free);
2491 break;
2492
2493 case DB_BTREE:
2494 case DB_RECNO:
2495 MAKE_BT_ENTRY(magic);
2496 MAKE_BT_ENTRY(version);
2497 MAKE_BT_ENTRY(nkeys);
2498 MAKE_BT_ENTRY(ndata);
2499 MAKE_BT_ENTRY(pagesize);
2500 MAKE_BT_ENTRY(minkey);
2501 MAKE_BT_ENTRY(re_len);
2502 MAKE_BT_ENTRY(re_pad);
2503 MAKE_BT_ENTRY(levels);
2504 MAKE_BT_ENTRY(int_pg);
2505 MAKE_BT_ENTRY(leaf_pg);
2506 MAKE_BT_ENTRY(dup_pg);
2507 MAKE_BT_ENTRY(over_pg);
2508 MAKE_BT_ENTRY(free);
2509 MAKE_BT_ENTRY(int_pgfree);
2510 MAKE_BT_ENTRY(leaf_pgfree);
2511 MAKE_BT_ENTRY(dup_pgfree);
2512 MAKE_BT_ENTRY(over_pgfree);
2513 break;
2514
2515 case DB_QUEUE:
2516 MAKE_QUEUE_ENTRY(magic);
2517 MAKE_QUEUE_ENTRY(version);
2518 MAKE_QUEUE_ENTRY(nkeys);
2519 MAKE_QUEUE_ENTRY(ndata);
2520 MAKE_QUEUE_ENTRY(pagesize);
2521 MAKE_QUEUE_ENTRY(pages);
2522 MAKE_QUEUE_ENTRY(re_len);
2523 MAKE_QUEUE_ENTRY(re_pad);
2524 MAKE_QUEUE_ENTRY(pgfree);
2525#if (DBVER == 31)
2526 MAKE_QUEUE_ENTRY(start);
2527#endif
2528 MAKE_QUEUE_ENTRY(first_recno);
2529 MAKE_QUEUE_ENTRY(cur_recno);
2530 break;
2531
2532 default:
2533 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2534 Py_DECREF(d);
2535 d = NULL;
2536 }
2537
2538#undef MAKE_HASH_ENTRY
2539#undef MAKE_BT_ENTRY
2540#undef MAKE_QUEUE_ENTRY
2541
2542 free(sp);
2543 return d;
2544}
2545
2546static PyObject*
2547DB_sync(DBObject* self, PyObject* args)
2548{
2549 int err;
2550 int flags = 0;
2551
2552 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2553 return NULL;
2554 CHECK_DB_NOT_CLOSED(self);
2555
2556 MYDB_BEGIN_ALLOW_THREADS;
2557 err = self->db->sync(self->db, flags);
2558 MYDB_END_ALLOW_THREADS;
2559 RETURN_IF_ERR();
2560 RETURN_NONE();
2561}
2562
2563
2564#if (DBVER >= 33)
2565static PyObject*
2566DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2567{
2568 int err, flags=0;
2569 u_int32_t count=0;
2570 PyObject* txnobj = NULL;
2571 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002572 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573
2574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2575 &txnobj, &flags))
2576 return NULL;
2577 CHECK_DB_NOT_CLOSED(self);
2578 if (!checkTxnObj(txnobj, &txn))
2579 return NULL;
2580
2581 MYDB_BEGIN_ALLOW_THREADS;
2582 err = self->db->truncate(self->db, txn, &count, flags);
2583 MYDB_END_ALLOW_THREADS;
2584 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00002585 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002586}
2587#endif
2588
2589
2590static PyObject*
2591DB_upgrade(DBObject* self, PyObject* args)
2592{
2593 int err, flags=0;
2594 char *filename;
2595
2596 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2597 return NULL;
2598 CHECK_DB_NOT_CLOSED(self);
2599
2600 MYDB_BEGIN_ALLOW_THREADS;
2601 err = self->db->upgrade(self->db, filename, flags);
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2604 RETURN_NONE();
2605}
2606
2607
2608static PyObject*
2609DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2610{
2611 int err, flags=0;
2612 char* fileName;
2613 char* dbName=NULL;
2614 char* outFileName=NULL;
2615 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002616 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002617 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002618
2619 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2620 &fileName, &dbName, &outFileName, &flags))
2621 return NULL;
2622
2623 CHECK_DB_NOT_CLOSED(self);
2624 if (outFileName)
2625 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002626 /* XXX(nnorwitz): it should probably be an exception if outFile
2627 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002628
2629 MYDB_BEGIN_ALLOW_THREADS;
2630 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2631 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002632 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002633 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002634
2635 /* DB.verify acts as a DB handle destructor (like close); this was
2636 * documented in BerkeleyDB 4.2 but had the undocumented effect
2637 * of not being safe in prior versions while still requiring an explicit
2638 * DB.close call afterwards. Lets call close for the user to emulate
2639 * the safe 4.2 behaviour. */
2640#if (DBVER <= 41)
2641 self->db->close(self->db, 0);
2642#endif
2643 self->db = NULL;
2644
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002645 RETURN_IF_ERR();
2646 RETURN_NONE();
2647}
2648
2649
2650static PyObject*
2651DB_set_get_returns_none(DBObject* self, PyObject* args)
2652{
2653 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002654 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002655
2656 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2657 return NULL;
2658 CHECK_DB_NOT_CLOSED(self);
2659
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002660 if (self->moduleFlags.getReturnsNone)
2661 ++oldValue;
2662 if (self->moduleFlags.cursorSetReturnsNone)
2663 ++oldValue;
2664 self->moduleFlags.getReturnsNone = (flags >= 1);
2665 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00002666 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002667}
2668
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002669#if (DBVER >= 41)
2670static PyObject*
2671DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2672{
2673 int err;
2674 u_int32_t flags=0;
2675 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002676 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002677
2678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2679 &passwd, &flags)) {
2680 return NULL;
2681 }
2682
2683 MYDB_BEGIN_ALLOW_THREADS;
2684 err = self->db->set_encrypt(self->db, passwd, flags);
2685 MYDB_END_ALLOW_THREADS;
2686
2687 RETURN_IF_ERR();
2688 RETURN_NONE();
2689}
2690#endif /* DBVER >= 41 */
2691
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692
2693/*-------------------------------------------------------------- */
2694/* Mapping and Dictionary-like access routines */
2695
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002696Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002697{
2698 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002699 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700 int flags = 0;
2701 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002702 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703
2704 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002705 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2706 PyErr_SetObject(DBError, t);
2707 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002708 return -1;
2709 }
2710
2711 if (self->haveStat) { /* Has the stat function been called recently? If
2712 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002713 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002714 }
2715
2716 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002717redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002718#if (DBVER >= 43)
2719 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2720#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721 err = self->db->stat(self->db, &sp, flags);
2722#else
2723 err = self->db->stat(self->db, &sp, NULL, flags);
2724#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002725
2726 /* All the stat structures have matching fields upto the ndata field,
2727 so we can use any of them for the type cast */
2728 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2729
2730 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2731 * redo a full stat to make sure.
2732 * Fixes SF python bug 1493322, pybsddb bug 1184012
2733 */
2734 if (size == 0 && (flags & DB_FAST_STAT)) {
2735 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002736 if (!err)
2737 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002738 goto redo_stat_for_length;
2739 }
2740
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002741 MYDB_END_ALLOW_THREADS;
2742
2743 if (err)
2744 return -1;
2745
2746 self->haveStat = 1;
2747
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002748 free(sp);
2749 return size;
2750}
2751
2752
2753PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2754{
2755 int err;
2756 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002757 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002758 DBT key;
2759 DBT data;
2760
2761 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002762 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002763 return NULL;
2764
2765 CLEAR_DBT(data);
2766 if (CHECK_DBFLAG(self, DB_THREAD)) {
2767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2768 data.flags = DB_DBT_MALLOC;
2769 }
2770 MYDB_BEGIN_ALLOW_THREADS;
2771 err = self->db->get(self->db, NULL, &key, &data, 0);
2772 MYDB_END_ALLOW_THREADS;
2773 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2774 PyErr_SetObject(PyExc_KeyError, keyobj);
2775 retval = NULL;
2776 }
2777 else if (makeDBError(err)) {
2778 retval = NULL;
2779 }
2780 else {
Christian Heimes72b710a2008-05-26 13:28:38 +00002781 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002782 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002783 }
2784
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002785 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 return retval;
2787}
2788
2789
2790static int
2791DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2792{
2793 DBT key, data;
2794 int retval;
2795 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002796 Py_buffer *data_buf_view = NULL;
2797 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002798
2799 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002800 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2801 PyErr_SetObject(DBError, t);
2802 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 return -1;
2804 }
2805
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002806 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002807 return -1;
2808
2809 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002810 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002811 retval = -1;
2812 else {
2813 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002814 /* dictionaries shouldn't have duplicate keys */
2815 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002816 retval = _DB_put(self, NULL, &key, &data, flags);
2817
2818 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002819 /* try deleting any old record that matches and then PUT it
2820 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002821 _DB_delete(self, NULL, &key, 0);
2822 PyErr_Clear();
2823 retval = _DB_put(self, NULL, &key, &data, flags);
2824 }
2825 }
2826 }
2827 else {
2828 /* dataobj == NULL, so delete the key */
2829 retval = _DB_delete(self, NULL, &key, 0);
2830 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002831 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2832 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002833 return retval;
2834}
2835
2836
2837static PyObject*
2838DB_has_key(DBObject* self, PyObject* args)
2839{
2840 int err;
2841 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002842 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 DBT key, data;
2844 PyObject* txnobj = NULL;
2845 DB_TXN *txn = NULL;
2846
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002847 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848 return NULL;
2849 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002850 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002852 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002853 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002855 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002856
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002857 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 it has a record but can't allocate a buffer for the data. This saves
2859 having to deal with data we won't be using.
2860 */
2861 CLEAR_DBT(data);
2862 data.flags = DB_DBT_USERMEM;
2863
2864 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002865 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002867 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002868
2869 if (err == DB_BUFFER_SMALL || err == 0) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002870 return PyLong_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002871 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002872 return PyLong_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002873 }
2874
2875 makeDBError(err);
2876 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002877}
2878
2879
2880#define _KEYS_LIST 1
2881#define _VALUES_LIST 2
2882#define _ITEMS_LIST 3
2883
2884static PyObject*
2885_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2886{
2887 int err, dbtype;
2888 DBT key;
2889 DBT data;
2890 DBC *cursor;
2891 PyObject* list;
2892 PyObject* item = NULL;
2893
2894 CHECK_DB_NOT_CLOSED(self);
2895 CLEAR_DBT(key);
2896 CLEAR_DBT(data);
2897
2898 dbtype = _DB_get_type(self);
2899 if (dbtype == -1)
2900 return NULL;
2901
2902 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002903 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002904 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905
2906 /* get a cursor */
2907 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002908 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002909 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002910 if (makeDBError(err)) {
2911 Py_DECREF(list);
2912 return NULL;
2913 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002914
2915 if (CHECK_DBFLAG(self, DB_THREAD)) {
2916 key.flags = DB_DBT_REALLOC;
2917 data.flags = DB_DBT_REALLOC;
2918 }
2919
2920 while (1) { /* use the cursor to traverse the DB, collecting items */
2921 MYDB_BEGIN_ALLOW_THREADS;
2922 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2923 MYDB_END_ALLOW_THREADS;
2924
2925 if (err) {
2926 /* for any error, break out of the loop */
2927 break;
2928 }
2929
2930 switch (type) {
2931 case _KEYS_LIST:
2932 switch(dbtype) {
2933 case DB_BTREE:
2934 case DB_HASH:
2935 default:
Christian Heimes72b710a2008-05-26 13:28:38 +00002936 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 break;
2938 case DB_RECNO:
2939 case DB_QUEUE:
Christian Heimes217cfd12007-12-02 14:31:20 +00002940 item = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002941 break;
2942 }
2943 break;
2944
2945 case _VALUES_LIST:
Christian Heimes72b710a2008-05-26 13:28:38 +00002946 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002947 break;
2948
2949 case _ITEMS_LIST:
2950 switch(dbtype) {
2951 case DB_BTREE:
2952 case DB_HASH:
2953 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002954 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002955 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002956 break;
2957 case DB_RECNO:
2958 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002959 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002960 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 break;
2962 }
2963 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002964 default:
2965 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2966 item = NULL;
2967 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002968 }
2969 if (item == NULL) {
2970 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971 list = NULL;
2972 goto done;
2973 }
2974 PyList_Append(list, item);
2975 Py_DECREF(item);
2976 }
2977
Gregory P. Smithe9477062005-06-04 06:46:59 +00002978 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2979 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 Py_DECREF(list);
2981 list = NULL;
2982 }
2983
2984 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002985 free_dbt(&key);
2986 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002987 MYDB_BEGIN_ALLOW_THREADS;
2988 cursor->c_close(cursor);
2989 MYDB_END_ALLOW_THREADS;
2990 return list;
2991}
2992
2993
2994static PyObject*
2995DB_keys(DBObject* self, PyObject* args)
2996{
2997 PyObject* txnobj = NULL;
2998 DB_TXN *txn = NULL;
2999
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003000 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003001 return NULL;
3002 if (!checkTxnObj(txnobj, &txn))
3003 return NULL;
3004 return _DB_make_list(self, txn, _KEYS_LIST);
3005}
3006
3007
3008static PyObject*
3009DB_items(DBObject* self, PyObject* args)
3010{
3011 PyObject* txnobj = NULL;
3012 DB_TXN *txn = NULL;
3013
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003014 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 return NULL;
3016 if (!checkTxnObj(txnobj, &txn))
3017 return NULL;
3018 return _DB_make_list(self, txn, _ITEMS_LIST);
3019}
3020
3021
3022static PyObject*
3023DB_values(DBObject* self, PyObject* args)
3024{
3025 PyObject* txnobj = NULL;
3026 DB_TXN *txn = NULL;
3027
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003028 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003029 return NULL;
3030 if (!checkTxnObj(txnobj, &txn))
3031 return NULL;
3032 return _DB_make_list(self, txn, _VALUES_LIST);
3033}
3034
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003035/* --------------------------------------------------------------------- */
3036/* DBCursor methods */
3037
3038
3039static PyObject*
3040DBC_close(DBCursorObject* self, PyObject* args)
3041{
3042 int err = 0;
3043
3044 if (!PyArg_ParseTuple(args, ":close"))
3045 return NULL;
3046
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003047 if (self->dbc != NULL) {
3048 MYDB_BEGIN_ALLOW_THREADS;
3049 err = self->dbc->c_close(self->dbc);
3050 self->dbc = NULL;
3051 MYDB_END_ALLOW_THREADS;
3052 }
3053 RETURN_IF_ERR();
3054 RETURN_NONE();
3055}
3056
3057
3058static PyObject*
3059DBC_count(DBCursorObject* self, PyObject* args)
3060{
3061 int err = 0;
3062 db_recno_t count;
3063 int flags = 0;
3064
3065 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3066 return NULL;
3067
3068 CHECK_CURSOR_NOT_CLOSED(self);
3069
3070 MYDB_BEGIN_ALLOW_THREADS;
3071 err = self->dbc->c_count(self->dbc, &count, flags);
3072 MYDB_END_ALLOW_THREADS;
3073 RETURN_IF_ERR();
3074
Christian Heimes217cfd12007-12-02 14:31:20 +00003075 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003076}
3077
3078
3079static PyObject*
3080DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3081{
3082 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3083}
3084
3085
3086static PyObject*
3087DBC_delete(DBCursorObject* self, PyObject* args)
3088{
3089 int err, flags=0;
3090
3091 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3092 return NULL;
3093
3094 CHECK_CURSOR_NOT_CLOSED(self);
3095
3096 MYDB_BEGIN_ALLOW_THREADS;
3097 err = self->dbc->c_del(self->dbc, flags);
3098 MYDB_END_ALLOW_THREADS;
3099 RETURN_IF_ERR();
3100
3101 self->mydb->haveStat = 0;
3102 RETURN_NONE();
3103}
3104
3105
3106static PyObject*
3107DBC_dup(DBCursorObject* self, PyObject* args)
3108{
3109 int err, flags =0;
3110 DBC* dbc = NULL;
3111
3112 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3113 return NULL;
3114
3115 CHECK_CURSOR_NOT_CLOSED(self);
3116
3117 MYDB_BEGIN_ALLOW_THREADS;
3118 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3119 MYDB_END_ALLOW_THREADS;
3120 RETURN_IF_ERR();
3121
3122 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3123}
3124
3125static PyObject*
3126DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3127{
3128 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3129}
3130
3131
3132static PyObject*
3133DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3134{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003135 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136 PyObject* keyobj = NULL;
3137 PyObject* dataobj = NULL;
3138 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003139 Py_buffer* data_buf_view = NULL;
3140 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141 int dlen = -1;
3142 int doff = -1;
3143 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003144 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003145 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003146
3147 CLEAR_DBT(key);
3148 CLEAR_DBT(data);
3149 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003150 &flags, &dlen, &doff))
3151 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3154 &kwnames[1],
3155 &keyobj, &flags, &dlen, &doff))
3156 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003158 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3159 kwnames, &keyobj, &dataobj,
3160 &flags, &dlen, &doff))
3161 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 return NULL;
3163 }
3164 }
3165 }
3166
3167 CHECK_CURSOR_NOT_CLOSED(self);
3168
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003169 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003171 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003172 (!add_partial_dbt(&data, dlen, doff)) )
3173 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003174 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3175 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003177 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003178
3179 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3180 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003181 if (!(key.flags & DB_DBT_REALLOC)) {
3182 key.flags |= DB_DBT_MALLOC;
3183 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003184 }
3185
3186 MYDB_BEGIN_ALLOW_THREADS;
3187 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3188 MYDB_END_ALLOW_THREADS;
3189
Gregory P. Smithe9477062005-06-04 06:46:59 +00003190 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3191 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003192 Py_INCREF(Py_None);
3193 retval = Py_None;
3194 }
3195 else if (makeDBError(err)) {
3196 retval = NULL;
3197 }
3198 else {
3199 switch (_DB_get_type(self->mydb)) {
3200 case -1:
3201 retval = NULL;
3202 break;
3203 case DB_BTREE:
3204 case DB_HASH:
3205 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003206 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003207 data.data, data.size);
3208 break;
3209 case DB_RECNO:
3210 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003211 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003212 data.data, data.size);
3213 break;
3214 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003215 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003216 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003217 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3218 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003219 return retval;
3220}
3221
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003222#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003223static PyObject*
3224DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3225{
3226 int err, flags=0;
3227 PyObject* keyobj = NULL;
3228 PyObject* dataobj = NULL;
3229 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003230 Py_buffer* data_buf_view = NULL;
3231 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003232 int dlen = -1;
3233 int doff = -1;
3234 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003235 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3236 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003237
3238 CLEAR_DBT(key);
3239 CLEAR_DBT(data);
3240 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3241 &flags, &dlen, &doff))
3242 {
3243 PyErr_Clear();
3244 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003245 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003246 &keyobj, &flags, &dlen, &doff))
3247 {
3248 PyErr_Clear();
3249 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3250 kwnames, &keyobj, &dataobj,
3251 &flags, &dlen, &doff))
3252 {
3253 return NULL;
3254 }
3255 }
3256 }
3257
3258 CHECK_CURSOR_NOT_CLOSED(self);
3259
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003260 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003261 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003262 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003263 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003264 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3265 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003266 return NULL;
3267 }
3268
3269 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3270 data.flags = DB_DBT_MALLOC;
3271 if (!(key.flags & DB_DBT_REALLOC)) {
3272 key.flags |= DB_DBT_MALLOC;
3273 }
3274 }
3275
3276 CLEAR_DBT(pkey);
3277 pkey.flags = DB_DBT_MALLOC;
3278
3279 MYDB_BEGIN_ALLOW_THREADS;
3280 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3281 MYDB_END_ALLOW_THREADS;
3282
Gregory P. Smithe9477062005-06-04 06:46:59 +00003283 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3284 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003285 Py_INCREF(Py_None);
3286 retval = Py_None;
3287 }
3288 else if (makeDBError(err)) {
3289 retval = NULL;
3290 }
3291 else {
3292 PyObject *pkeyObj;
3293 PyObject *dataObj;
Christian Heimes72b710a2008-05-26 13:28:38 +00003294 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003295
3296 if (self->mydb->primaryDBType == DB_RECNO ||
3297 self->mydb->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003298 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 else
Christian Heimes72b710a2008-05-26 13:28:38 +00003300 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003302 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003303 {
3304 PyObject *keyObj;
3305 int type = _DB_get_type(self->mydb);
3306 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003307 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003308 else
Christian Heimes72b710a2008-05-26 13:28:38 +00003309 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003310 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003311 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003312 }
3313 else /* return just the pkey and data */
3314 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003315 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003316 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003317 Py_DECREF(dataObj);
3318 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003319 free_dbt(&pkey);
3320 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003321 }
3322 /* the only time REALLOC should be set is if we used an integer
3323 * key that make_key_dbt malloc'd for us. always free these. */
3324 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003325 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003326 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003327 free_buf_view(keyobj, key_buf_view);
3328 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003329 return retval;
3330}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003331#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003332
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003333
3334static PyObject*
3335DBC_get_recno(DBCursorObject* self, PyObject* args)
3336{
3337 int err;
3338 db_recno_t recno;
3339 DBT key;
3340 DBT data;
3341
3342 if (!PyArg_ParseTuple(args, ":get_recno"))
3343 return NULL;
3344
3345 CHECK_CURSOR_NOT_CLOSED(self);
3346
3347 CLEAR_DBT(key);
3348 CLEAR_DBT(data);
3349 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3350 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3351 data.flags = DB_DBT_MALLOC;
3352 key.flags = DB_DBT_MALLOC;
3353 }
3354
3355 MYDB_BEGIN_ALLOW_THREADS;
3356 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3357 MYDB_END_ALLOW_THREADS;
3358 RETURN_IF_ERR();
3359
3360 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003361 free_dbt(&key);
3362 free_dbt(&data);
Christian Heimes217cfd12007-12-02 14:31:20 +00003363 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003364}
3365
3366
3367static PyObject*
3368DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3369{
3370 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3371}
3372
3373
3374static PyObject*
3375DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3376{
3377 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3378}
3379
3380
3381static PyObject*
3382DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3383{
3384 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3385}
3386
3387
3388static PyObject*
3389DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3390{
3391 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003392 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003393 Py_buffer *data_buf_view = NULL;
3394 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003395 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003396 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003397 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003398 int dlen = -1;
3399 int doff = -1;
3400
3401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3402 &keyobj, &dataobj, &flags, &dlen, &doff))
3403 return NULL;
3404
3405 CHECK_CURSOR_NOT_CLOSED(self);
3406
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003407 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003409 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003410 !add_partial_dbt(&data, dlen, doff) )
3411 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003412 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3413 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003415 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003416
3417 MYDB_BEGIN_ALLOW_THREADS;
3418 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3419 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003420 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3421 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003422 RETURN_IF_ERR();
3423 self->mydb->haveStat = 0;
3424 RETURN_NONE();
3425}
3426
3427
3428static PyObject*
3429DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3430{
3431 int err, flags = 0;
3432 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003433 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003434 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003435 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003436 int dlen = -1;
3437 int doff = -1;
3438
3439 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3440 &keyobj, &flags, &dlen, &doff))
3441 return NULL;
3442
3443 CHECK_CURSOR_NOT_CLOSED(self);
3444
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003445 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446 return NULL;
3447
3448 CLEAR_DBT(data);
3449 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3450 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3451 data.flags = DB_DBT_MALLOC;
3452 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003453 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003454 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003455 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003456 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457
3458 MYDB_BEGIN_ALLOW_THREADS;
3459 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3460 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003461 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3462 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003463 Py_INCREF(Py_None);
3464 retval = Py_None;
3465 }
3466 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003467 retval = NULL;
3468 }
3469 else {
3470 switch (_DB_get_type(self->mydb)) {
3471 case -1:
3472 retval = NULL;
3473 break;
3474 case DB_BTREE:
3475 case DB_HASH:
3476 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003477 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003478 data.data, data.size);
3479 break;
3480 case DB_RECNO:
3481 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003482 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003483 data.data, data.size);
3484 break;
3485 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003486 free_dbt(&data);
3487 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003488 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003489 /* the only time REALLOC should be set is if we used an integer
3490 * key that make_key_dbt malloc'd for us. always free these. */
3491 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003492 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003493 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003494 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003495
3496 return retval;
3497}
3498
3499
3500static PyObject*
3501DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3502{
3503 int err, flags = 0;
3504 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003505 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003506 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003507 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003508 int dlen = -1;
3509 int doff = -1;
3510
3511 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3512 &keyobj, &flags, &dlen, &doff))
3513 return NULL;
3514
3515 CHECK_CURSOR_NOT_CLOSED(self);
3516
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003517 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003518 return NULL;
3519
3520 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003521 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003522 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003523 return NULL;
3524 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003525 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3526 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 data.flags |= DB_DBT_MALLOC;
3528 /* only BTREE databases will return anything in the key */
3529 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3530 key.flags |= DB_DBT_MALLOC;
3531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003532 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533 MYDB_BEGIN_ALLOW_THREADS;
3534 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3535 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003536 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3537 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003538 Py_INCREF(Py_None);
3539 retval = Py_None;
3540 }
3541 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003542 retval = NULL;
3543 }
3544 else {
3545 switch (_DB_get_type(self->mydb)) {
3546 case -1:
3547 retval = NULL;
3548 break;
3549 case DB_BTREE:
3550 case DB_HASH:
3551 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003552 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553 data.data, data.size);
3554 break;
3555 case DB_RECNO:
3556 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003557 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558 data.data, data.size);
3559 break;
3560 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003561 free_dbt(&key);
3562 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003563 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003564 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003565 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003566 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003567 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003568 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003569 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570
3571 return retval;
3572}
3573
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003574static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003575_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3576 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003578 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003580 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003581 Py_buffer *data_buf_view = NULL;
3582 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003583
Gregory P. Smith7441e652003-11-03 21:35:31 +00003584 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003585 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003587 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3588 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003590 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003591
3592 MYDB_BEGIN_ALLOW_THREADS;
3593 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3594 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003595 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003596 Py_INCREF(Py_None);
3597 retval = Py_None;
3598 }
3599 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600 retval = NULL;
3601 }
3602 else {
3603 switch (_DB_get_type(self->mydb)) {
3604 case -1:
3605 retval = NULL;
3606 break;
3607 case DB_BTREE:
3608 case DB_HASH:
3609 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003610 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611 data.data, data.size);
3612 break;
3613 case DB_RECNO:
3614 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003615 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003616 data.data, data.size);
3617 break;
3618 }
3619 }
3620
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003621 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3622 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003623 return retval;
3624}
3625
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003626static PyObject*
3627DBC_get_both(DBCursorObject* self, PyObject* args)
3628{
3629 int flags=0;
3630 PyObject *keyobj, *dataobj;
3631
3632 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3633 return NULL;
3634
Gregory P. Smith7441e652003-11-03 21:35:31 +00003635 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003636 CHECK_CURSOR_NOT_CLOSED(self);
3637
3638 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3639 self->mydb->moduleFlags.getReturnsNone);
3640}
3641
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003642/* Return size of entry */
3643static PyObject*
3644DBC_get_current_size(DBCursorObject* self, PyObject* args)
3645{
3646 int err, flags=DB_CURRENT;
3647 PyObject* retval = NULL;
3648 DBT key, data;
3649
3650 if (!PyArg_ParseTuple(args, ":get_current_size"))
3651 return NULL;
3652 CHECK_CURSOR_NOT_CLOSED(self);
3653 CLEAR_DBT(key);
3654 CLEAR_DBT(data);
3655
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003656 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003657 getting the record size. */
3658 data.flags = DB_DBT_USERMEM;
3659 data.ulen = 0;
3660 MYDB_BEGIN_ALLOW_THREADS;
3661 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3662 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003663 if (err == DB_BUFFER_SMALL || !err) {
3664 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Christian Heimes217cfd12007-12-02 14:31:20 +00003665 retval = PyLong_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003666 err = 0;
3667 }
3668
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003669 free_dbt(&key);
3670 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003671 RETURN_IF_ERR();
3672 return retval;
3673}
3674
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003675static PyObject*
3676DBC_set_both(DBCursorObject* self, PyObject* args)
3677{
3678 int flags=0;
3679 PyObject *keyobj, *dataobj;
3680
3681 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3682 return NULL;
3683
Gregory P. Smith7441e652003-11-03 21:35:31 +00003684 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003685 CHECK_CURSOR_NOT_CLOSED(self);
3686
3687 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3688 self->mydb->moduleFlags.cursorSetReturnsNone);
3689}
3690
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003691
3692static PyObject*
3693DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3694{
3695 int err, irecno, flags=0;
3696 db_recno_t recno;
3697 DBT key, data;
3698 PyObject* retval;
3699 int dlen = -1;
3700 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003701 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702
3703 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3704 &irecno, &flags, &dlen, &doff))
3705 return NULL;
3706
3707 CHECK_CURSOR_NOT_CLOSED(self);
3708
3709 CLEAR_DBT(key);
3710 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003711 /* use allocated space so DB will be able to realloc room for the real
3712 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003713 key.data = malloc(sizeof(db_recno_t));
3714 if (key.data == NULL) {
3715 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3716 return NULL;
3717 }
3718 key.size = sizeof(db_recno_t);
3719 key.ulen = key.size;
3720 memcpy(key.data, &recno, sizeof(db_recno_t));
3721 key.flags = DB_DBT_REALLOC;
3722
3723 CLEAR_DBT(data);
3724 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3725 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3726 data.flags = DB_DBT_MALLOC;
3727 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003728 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003729 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003730 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003731 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732
3733 MYDB_BEGIN_ALLOW_THREADS;
3734 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3735 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003736 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3737 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003738 Py_INCREF(Py_None);
3739 retval = Py_None;
3740 }
3741 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003742 retval = NULL;
3743 }
3744 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003745 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003746 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003747 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003748 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003749 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750
3751 return retval;
3752}
3753
3754
3755static PyObject*
3756DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3757{
3758 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3759}
3760
3761
3762static PyObject*
3763DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3764{
3765 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3766}
3767
3768
3769static PyObject*
3770DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3771{
3772 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3773}
3774
3775
3776static PyObject*
3777DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3778{
3779 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3780}
3781
3782
3783static PyObject*
3784DBC_join_item(DBCursorObject* self, PyObject* args)
3785{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003786 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787 DBT key, data;
3788 PyObject* retval;
3789
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003790 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791 return NULL;
3792
3793 CHECK_CURSOR_NOT_CLOSED(self);
3794
3795 CLEAR_DBT(key);
3796 CLEAR_DBT(data);
3797 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3798 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3799 key.flags = DB_DBT_MALLOC;
3800 }
3801
3802 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003803 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003804 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003805 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3806 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003807 Py_INCREF(Py_None);
3808 retval = Py_None;
3809 }
3810 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003811 retval = NULL;
3812 }
3813 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003814 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003815 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003816 }
3817
3818 return retval;
3819}
3820
3821
3822
3823/* --------------------------------------------------------------------- */
3824/* DBEnv methods */
3825
3826
3827static PyObject*
3828DBEnv_close(DBEnvObject* self, PyObject* args)
3829{
3830 int err, flags = 0;
3831
3832 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3833 return NULL;
3834 if (!self->closed) { /* Don't close more than once */
3835 MYDB_BEGIN_ALLOW_THREADS;
3836 err = self->db_env->close(self->db_env, flags);
3837 MYDB_END_ALLOW_THREADS;
3838 /* after calling DBEnv->close, regardless of error, this DBEnv
3839 * may not be accessed again (BerkeleyDB docs). */
3840 self->closed = 1;
3841 self->db_env = NULL;
3842 RETURN_IF_ERR();
3843 }
3844 RETURN_NONE();
3845}
3846
3847
3848static PyObject*
3849DBEnv_open(DBEnvObject* self, PyObject* args)
3850{
3851 int err, flags=0, mode=0660;
3852 char *db_home;
3853
3854 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3855 return NULL;
3856
3857 CHECK_ENV_NOT_CLOSED(self);
3858
3859 MYDB_BEGIN_ALLOW_THREADS;
3860 err = self->db_env->open(self->db_env, db_home, flags, mode);
3861 MYDB_END_ALLOW_THREADS;
3862 RETURN_IF_ERR();
3863 self->closed = 0;
3864 self->flags = flags;
3865 RETURN_NONE();
3866}
3867
3868
3869static PyObject*
3870DBEnv_remove(DBEnvObject* self, PyObject* args)
3871{
3872 int err, flags=0;
3873 char *db_home;
3874
3875 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3876 return NULL;
3877 CHECK_ENV_NOT_CLOSED(self);
3878 MYDB_BEGIN_ALLOW_THREADS;
3879 err = self->db_env->remove(self->db_env, db_home, flags);
3880 MYDB_END_ALLOW_THREADS;
3881 RETURN_IF_ERR();
3882 RETURN_NONE();
3883}
3884
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003885#if (DBVER >= 41)
3886static PyObject*
3887DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3888{
3889 int err;
3890 u_int32_t flags=0;
3891 char *file = NULL;
3892 char *database = NULL;
3893 PyObject *txnobj = NULL;
3894 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003895 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003896 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003897
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003898 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003899 &file, &database, &txnobj, &flags)) {
3900 return NULL;
3901 }
3902 if (!checkTxnObj(txnobj, &txn)) {
3903 return NULL;
3904 }
3905 CHECK_ENV_NOT_CLOSED(self);
3906 MYDB_BEGIN_ALLOW_THREADS;
3907 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3908 MYDB_END_ALLOW_THREADS;
3909 RETURN_IF_ERR();
3910 RETURN_NONE();
3911}
3912
3913static PyObject*
3914DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3915{
3916 int err;
3917 u_int32_t flags=0;
3918 char *file = NULL;
3919 char *database = NULL;
3920 char *newname = NULL;
3921 PyObject *txnobj = NULL;
3922 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003923 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003924 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003925
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003927 &file, &database, &newname, &txnobj, &flags)) {
3928 return NULL;
3929 }
3930 if (!checkTxnObj(txnobj, &txn)) {
3931 return NULL;
3932 }
3933 CHECK_ENV_NOT_CLOSED(self);
3934 MYDB_BEGIN_ALLOW_THREADS;
3935 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3936 flags);
3937 MYDB_END_ALLOW_THREADS;
3938 RETURN_IF_ERR();
3939 RETURN_NONE();
3940}
3941
3942static PyObject*
3943DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3944{
3945 int err;
3946 u_int32_t flags=0;
3947 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003948 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003949
3950 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3951 &passwd, &flags)) {
3952 return NULL;
3953 }
3954
3955 MYDB_BEGIN_ALLOW_THREADS;
3956 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3957 MYDB_END_ALLOW_THREADS;
3958
3959 RETURN_IF_ERR();
3960 RETURN_NONE();
3961}
3962#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003963
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003964#if (DBVER >= 40)
3965static PyObject*
3966DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3967{
3968 int err;
3969 u_int32_t flags=0;
3970 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003971 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003972
3973 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3974 &timeout, &flags)) {
3975 return NULL;
3976 }
3977
3978 MYDB_BEGIN_ALLOW_THREADS;
3979 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3980 MYDB_END_ALLOW_THREADS;
3981
3982 RETURN_IF_ERR();
3983 RETURN_NONE();
3984}
3985#endif /* DBVER >= 40 */
3986
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003987static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003988DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3989{
3990 int err;
3991 long shm_key = 0;
3992
3993 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3994 return NULL;
3995 CHECK_ENV_NOT_CLOSED(self);
3996
3997 err = self->db_env->set_shm_key(self->db_env, shm_key);
3998 RETURN_IF_ERR();
3999 RETURN_NONE();
4000}
4001
4002static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004003DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4004{
4005 int err, gbytes=0, bytes=0, ncache=0;
4006
4007 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4008 &gbytes, &bytes, &ncache))
4009 return NULL;
4010 CHECK_ENV_NOT_CLOSED(self);
4011
4012 MYDB_BEGIN_ALLOW_THREADS;
4013 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4014 MYDB_END_ALLOW_THREADS;
4015 RETURN_IF_ERR();
4016 RETURN_NONE();
4017}
4018
4019
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004020static PyObject*
4021DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4022{
4023 int err, flags=0, onoff=0;
4024
4025 if (!PyArg_ParseTuple(args, "ii:set_flags",
4026 &flags, &onoff))
4027 return NULL;
4028 CHECK_ENV_NOT_CLOSED(self);
4029
4030 MYDB_BEGIN_ALLOW_THREADS;
4031 err = self->db_env->set_flags(self->db_env, flags, onoff);
4032 MYDB_END_ALLOW_THREADS;
4033 RETURN_IF_ERR();
4034 RETURN_NONE();
4035}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004036
4037
4038static PyObject*
4039DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4040{
4041 int err;
4042 char *dir;
4043
4044 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4045 return NULL;
4046 CHECK_ENV_NOT_CLOSED(self);
4047
4048 MYDB_BEGIN_ALLOW_THREADS;
4049 err = self->db_env->set_data_dir(self->db_env, dir);
4050 MYDB_END_ALLOW_THREADS;
4051 RETURN_IF_ERR();
4052 RETURN_NONE();
4053}
4054
4055
4056static PyObject*
4057DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4058{
4059 int err, lg_bsize;
4060
4061 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4062 return NULL;
4063 CHECK_ENV_NOT_CLOSED(self);
4064
4065 MYDB_BEGIN_ALLOW_THREADS;
4066 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4067 MYDB_END_ALLOW_THREADS;
4068 RETURN_IF_ERR();
4069 RETURN_NONE();
4070}
4071
4072
4073static PyObject*
4074DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4075{
4076 int err;
4077 char *dir;
4078
4079 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4080 return NULL;
4081 CHECK_ENV_NOT_CLOSED(self);
4082
4083 MYDB_BEGIN_ALLOW_THREADS;
4084 err = self->db_env->set_lg_dir(self->db_env, dir);
4085 MYDB_END_ALLOW_THREADS;
4086 RETURN_IF_ERR();
4087 RETURN_NONE();
4088}
4089
4090static PyObject*
4091DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4092{
4093 int err, lg_max;
4094
4095 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4096 return NULL;
4097 CHECK_ENV_NOT_CLOSED(self);
4098
4099 MYDB_BEGIN_ALLOW_THREADS;
4100 err = self->db_env->set_lg_max(self->db_env, lg_max);
4101 MYDB_END_ALLOW_THREADS;
4102 RETURN_IF_ERR();
4103 RETURN_NONE();
4104}
4105
4106
Neal Norwitz84562352005-10-20 04:30:15 +00004107#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004108static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004109DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4110{
4111 int err, lg_max;
4112
4113 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4114 return NULL;
4115 CHECK_ENV_NOT_CLOSED(self);
4116
4117 MYDB_BEGIN_ALLOW_THREADS;
4118 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4119 MYDB_END_ALLOW_THREADS;
4120 RETURN_IF_ERR();
4121 RETURN_NONE();
4122}
Neal Norwitz84562352005-10-20 04:30:15 +00004123#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004124
4125
4126static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004127DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4128{
4129 int err, lk_detect;
4130
4131 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4132 return NULL;
4133 CHECK_ENV_NOT_CLOSED(self);
4134
4135 MYDB_BEGIN_ALLOW_THREADS;
4136 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4137 MYDB_END_ALLOW_THREADS;
4138 RETURN_IF_ERR();
4139 RETURN_NONE();
4140}
4141
4142
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004143#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004144static PyObject*
4145DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4146{
4147 int err, max;
4148
4149 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4150 return NULL;
4151 CHECK_ENV_NOT_CLOSED(self);
4152
4153 MYDB_BEGIN_ALLOW_THREADS;
4154 err = self->db_env->set_lk_max(self->db_env, max);
4155 MYDB_END_ALLOW_THREADS;
4156 RETURN_IF_ERR();
4157 RETURN_NONE();
4158}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004159#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004160
4161
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004162
4163static PyObject*
4164DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4165{
4166 int err, max;
4167
4168 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4169 return NULL;
4170 CHECK_ENV_NOT_CLOSED(self);
4171
4172 MYDB_BEGIN_ALLOW_THREADS;
4173 err = self->db_env->set_lk_max_locks(self->db_env, max);
4174 MYDB_END_ALLOW_THREADS;
4175 RETURN_IF_ERR();
4176 RETURN_NONE();
4177}
4178
4179
4180static PyObject*
4181DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4182{
4183 int err, max;
4184
4185 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4186 return NULL;
4187 CHECK_ENV_NOT_CLOSED(self);
4188
4189 MYDB_BEGIN_ALLOW_THREADS;
4190 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4191 MYDB_END_ALLOW_THREADS;
4192 RETURN_IF_ERR();
4193 RETURN_NONE();
4194}
4195
4196
4197static PyObject*
4198DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4199{
4200 int err, max;
4201
4202 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4203 return NULL;
4204 CHECK_ENV_NOT_CLOSED(self);
4205
4206 MYDB_BEGIN_ALLOW_THREADS;
4207 err = self->db_env->set_lk_max_objects(self->db_env, max);
4208 MYDB_END_ALLOW_THREADS;
4209 RETURN_IF_ERR();
4210 RETURN_NONE();
4211}
4212
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004213
4214static PyObject*
4215DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4216{
4217 int err, mp_mmapsize;
4218
4219 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4220 return NULL;
4221 CHECK_ENV_NOT_CLOSED(self);
4222
4223 MYDB_BEGIN_ALLOW_THREADS;
4224 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4225 MYDB_END_ALLOW_THREADS;
4226 RETURN_IF_ERR();
4227 RETURN_NONE();
4228}
4229
4230
4231static PyObject*
4232DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4233{
4234 int err;
4235 char *dir;
4236
4237 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4238 return NULL;
4239 CHECK_ENV_NOT_CLOSED(self);
4240
4241 MYDB_BEGIN_ALLOW_THREADS;
4242 err = self->db_env->set_tmp_dir(self->db_env, dir);
4243 MYDB_END_ALLOW_THREADS;
4244 RETURN_IF_ERR();
4245 RETURN_NONE();
4246}
4247
4248
4249static PyObject*
4250DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4251{
4252 int flags = 0;
4253 PyObject* txnobj = NULL;
4254 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004255 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004256
4257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4258 &txnobj, &flags))
4259 return NULL;
4260
4261 if (!checkTxnObj(txnobj, &txn))
4262 return NULL;
4263 CHECK_ENV_NOT_CLOSED(self);
4264
4265 return (PyObject*)newDBTxnObject(self, txn, flags);
4266}
4267
4268
4269static PyObject*
4270DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4271{
4272 int err, kbyte=0, min=0, flags=0;
4273
4274 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4275 return NULL;
4276 CHECK_ENV_NOT_CLOSED(self);
4277
4278 MYDB_BEGIN_ALLOW_THREADS;
4279#if (DBVER >= 40)
4280 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4281#else
4282 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4283#endif
4284 MYDB_END_ALLOW_THREADS;
4285 RETURN_IF_ERR();
4286 RETURN_NONE();
4287}
4288
4289
4290static PyObject*
4291DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4292{
4293 int err, max;
4294
4295 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4296 return NULL;
4297 CHECK_ENV_NOT_CLOSED(self);
4298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004299 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004300 RETURN_IF_ERR();
4301 RETURN_NONE();
4302}
4303
4304
4305static PyObject*
4306DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4307{
4308 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004309 long stamp;
4310 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004311
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004312 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004313 return NULL;
4314 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004315 timestamp = (time_t)stamp;
4316 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004317 RETURN_IF_ERR();
4318 RETURN_NONE();
4319}
4320
4321
4322static PyObject*
4323DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4324{
4325 int err, atype, flags=0;
4326 int aborted = 0;
4327
4328 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4329 return NULL;
4330 CHECK_ENV_NOT_CLOSED(self);
4331
4332 MYDB_BEGIN_ALLOW_THREADS;
4333#if (DBVER >= 40)
4334 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4335#else
4336 err = lock_detect(self->db_env, flags, atype, &aborted);
4337#endif
4338 MYDB_END_ALLOW_THREADS;
4339 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00004340 return PyLong_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004341}
4342
4343
4344static PyObject*
4345DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4346{
4347 int flags=0;
4348 int locker, lock_mode;
4349 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004350 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004351 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004352
4353 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4354 return NULL;
4355
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004356 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004357 return NULL;
4358
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004359 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4360 free_buf_view(objobj, obj_buf_view);
4361 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004362}
4363
4364
4365static PyObject*
4366DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4367{
4368 int err;
4369 u_int32_t theID;
4370
4371 if (!PyArg_ParseTuple(args, ":lock_id"))
4372 return NULL;
4373
4374 CHECK_ENV_NOT_CLOSED(self);
4375 MYDB_BEGIN_ALLOW_THREADS;
4376#if (DBVER >= 40)
4377 err = self->db_env->lock_id(self->db_env, &theID);
4378#else
4379 err = lock_id(self->db_env, &theID);
4380#endif
4381 MYDB_END_ALLOW_THREADS;
4382 RETURN_IF_ERR();
4383
Christian Heimes217cfd12007-12-02 14:31:20 +00004384 return PyLong_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004385}
4386
Guido van Rossum77677112007-11-05 19:43:04 +00004387#if (DBVER >= 40)
4388static PyObject*
4389DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4390{
4391 int err;
4392 u_int32_t theID;
4393
4394 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4395 return NULL;
4396
4397 CHECK_ENV_NOT_CLOSED(self);
4398 MYDB_BEGIN_ALLOW_THREADS;
4399 err = self->db_env->lock_id_free(self->db_env, theID);
4400 MYDB_END_ALLOW_THREADS;
4401 RETURN_IF_ERR();
4402 RETURN_NONE();
4403}
4404#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004405
4406static PyObject*
4407DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4408{
4409 int err;
4410 DBLockObject* dblockobj;
4411
4412 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4413 return NULL;
4414
4415 CHECK_ENV_NOT_CLOSED(self);
4416 MYDB_BEGIN_ALLOW_THREADS;
4417#if (DBVER >= 40)
4418 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4419#else
4420 err = lock_put(self->db_env, &dblockobj->lock);
4421#endif
4422 MYDB_END_ALLOW_THREADS;
4423 RETURN_IF_ERR();
4424 RETURN_NONE();
4425}
4426
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004427#if (DBVER >= 44)
4428static PyObject*
4429DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4430{
4431 int err;
4432 char *file;
4433 u_int32_t flags = 0;
4434 static char* kwnames[] = { "file", "flags", NULL};
4435
4436 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4437 &file, &flags))
4438 return NULL;
4439 CHECK_ENV_NOT_CLOSED(self);
4440
4441 MYDB_BEGIN_ALLOW_THREADS;
4442 err = self->db_env->lsn_reset(self->db_env, file, flags);
4443 MYDB_END_ALLOW_THREADS;
4444 RETURN_IF_ERR();
4445 RETURN_NONE();
4446}
4447#endif /* DBVER >= 4.4 */
4448
4449#if (DBVER >= 40)
4450static PyObject*
4451DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4452{
4453 int err;
4454 DB_LOG_STAT* statp = NULL;
4455 PyObject* d = NULL;
4456 u_int32_t flags = 0;
4457
4458 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4459 return NULL;
4460 CHECK_ENV_NOT_CLOSED(self);
4461
4462 MYDB_BEGIN_ALLOW_THREADS;
4463 err = self->db_env->log_stat(self->db_env, &statp, flags);
4464 MYDB_END_ALLOW_THREADS;
4465 RETURN_IF_ERR();
4466
4467 /* Turn the stat structure into a dictionary */
4468 d = PyDict_New();
4469 if (d == NULL) {
4470 if (statp)
4471 free(statp);
4472 return NULL;
4473 }
4474
4475#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4476
4477 MAKE_ENTRY(magic);
4478 MAKE_ENTRY(version);
4479 MAKE_ENTRY(mode);
4480 MAKE_ENTRY(lg_bsize);
4481#if (DBVER >= 44)
4482 MAKE_ENTRY(lg_size);
4483 MAKE_ENTRY(record);
4484#endif
4485#if (DBVER <= 40)
4486 MAKE_ENTRY(lg_max);
4487#endif
4488 MAKE_ENTRY(w_mbytes);
4489 MAKE_ENTRY(w_bytes);
4490 MAKE_ENTRY(wc_mbytes);
4491 MAKE_ENTRY(wc_bytes);
4492 MAKE_ENTRY(wcount);
4493 MAKE_ENTRY(wcount_fill);
4494#if (DBVER >= 44)
4495 MAKE_ENTRY(rcount);
4496#endif
4497 MAKE_ENTRY(scount);
4498 MAKE_ENTRY(cur_file);
4499 MAKE_ENTRY(cur_offset);
4500 MAKE_ENTRY(disk_file);
4501 MAKE_ENTRY(disk_offset);
4502 MAKE_ENTRY(maxcommitperflush);
4503 MAKE_ENTRY(mincommitperflush);
4504 MAKE_ENTRY(regsize);
4505 MAKE_ENTRY(region_wait);
4506 MAKE_ENTRY(region_nowait);
4507
4508#undef MAKE_ENTRY
4509 free(statp);
4510 return d;
4511} /* DBEnv_log_stat */
4512#endif /* DBVER >= 4.0 for log_stat method */
4513
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004514
4515static PyObject*
4516DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4517{
4518 int err;
4519 DB_LOCK_STAT* sp;
4520 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004521 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522
4523 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4524 return NULL;
4525 CHECK_ENV_NOT_CLOSED(self);
4526
4527 MYDB_BEGIN_ALLOW_THREADS;
4528#if (DBVER >= 40)
4529 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4530#else
4531#if (DBVER >= 33)
4532 err = lock_stat(self->db_env, &sp);
4533#else
4534 err = lock_stat(self->db_env, &sp, NULL);
4535#endif
4536#endif
4537 MYDB_END_ALLOW_THREADS;
4538 RETURN_IF_ERR();
4539
4540 /* Turn the stat structure into a dictionary */
4541 d = PyDict_New();
4542 if (d == NULL) {
4543 free(sp);
4544 return NULL;
4545 }
4546
4547#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4548
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004549#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004550 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004551#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004552 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004553 MAKE_ENTRY(maxlocks);
4554 MAKE_ENTRY(maxlockers);
4555 MAKE_ENTRY(maxobjects);
4556 MAKE_ENTRY(nlocks);
4557 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004558 MAKE_ENTRY(nlockers);
4559 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560 MAKE_ENTRY(nobjects);
4561 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 MAKE_ENTRY(nrequests);
4563 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004564#if (DBVER < 44)
4565 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004566 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004567#else
4568 MAKE_ENTRY(lock_nowait);
4569 MAKE_ENTRY(lock_wait);
4570#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004571 MAKE_ENTRY(ndeadlocks);
4572 MAKE_ENTRY(regsize);
4573 MAKE_ENTRY(region_wait);
4574 MAKE_ENTRY(region_nowait);
4575
4576#undef MAKE_ENTRY
4577 free(sp);
4578 return d;
4579}
4580
4581
4582static PyObject*
4583DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4584{
4585 int flags=0;
4586 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004587 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004588 PyObject* list;
4589 PyObject* item = NULL;
4590
4591 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4592 return NULL;
4593
4594 CHECK_ENV_NOT_CLOSED(self);
4595 MYDB_BEGIN_ALLOW_THREADS;
4596#if (DBVER >= 40)
4597 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4598#elif (DBVER == 33)
4599 err = log_archive(self->db_env, &log_list, flags);
4600#else
4601 err = log_archive(self->db_env, &log_list, flags, NULL);
4602#endif
4603 MYDB_END_ALLOW_THREADS;
4604 RETURN_IF_ERR();
4605
4606 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004607 if (list == NULL) {
4608 if (log_list)
4609 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004610 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004611 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612
4613 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004614 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004616 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004617 if (item == NULL) {
4618 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004619 list = NULL;
4620 break;
4621 }
4622 PyList_Append(list, item);
4623 Py_DECREF(item);
4624 }
4625 free(log_list_start);
4626 }
4627 return list;
4628}
4629
4630
4631static PyObject*
4632DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4633{
4634 int err;
4635 DB_TXN_STAT* sp;
4636 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004637 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004638
4639 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4640 return NULL;
4641 CHECK_ENV_NOT_CLOSED(self);
4642
4643 MYDB_BEGIN_ALLOW_THREADS;
4644#if (DBVER >= 40)
4645 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4646#elif (DBVER == 33)
4647 err = txn_stat(self->db_env, &sp);
4648#else
4649 err = txn_stat(self->db_env, &sp, NULL);
4650#endif
4651 MYDB_END_ALLOW_THREADS;
4652 RETURN_IF_ERR();
4653
4654 /* Turn the stat structure into a dictionary */
4655 d = PyDict_New();
4656 if (d == NULL) {
4657 free(sp);
4658 return NULL;
4659 }
4660
4661#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004662#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004663
Guido van Rossumd8faa362007-04-27 19:54:29 +00004664 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004665 MAKE_ENTRY(last_txnid);
4666 MAKE_ENTRY(maxtxns);
4667 MAKE_ENTRY(nactive);
4668 MAKE_ENTRY(maxnactive);
4669 MAKE_ENTRY(nbegins);
4670 MAKE_ENTRY(naborts);
4671 MAKE_ENTRY(ncommits);
4672 MAKE_ENTRY(regsize);
4673 MAKE_ENTRY(region_wait);
4674 MAKE_ENTRY(region_nowait);
4675
4676#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004677#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004678 free(sp);
4679 return d;
4680}
4681
4682
4683static PyObject*
4684DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4685{
4686 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004687 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004688
4689 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4690 return NULL;
4691 CHECK_ENV_NOT_CLOSED(self);
4692
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004693 if (self->moduleFlags.getReturnsNone)
4694 ++oldValue;
4695 if (self->moduleFlags.cursorSetReturnsNone)
4696 ++oldValue;
4697 self->moduleFlags.getReturnsNone = (flags >= 1);
4698 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00004699 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004700}
4701
4702
4703/* --------------------------------------------------------------------- */
4704/* DBTxn methods */
4705
4706
4707static PyObject*
4708DBTxn_commit(DBTxnObject* self, PyObject* args)
4709{
4710 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004711 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004712
4713 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4714 return NULL;
4715
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004716 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004717 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4718 "after txn_commit or txn_abort");
4719 PyErr_SetObject(DBError, t);
4720 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004721 return NULL;
4722 }
4723 txn = self->txn;
4724 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004725 MYDB_BEGIN_ALLOW_THREADS;
4726#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004727 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004728#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004729 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730#endif
4731 MYDB_END_ALLOW_THREADS;
4732 RETURN_IF_ERR();
4733 RETURN_NONE();
4734}
4735
4736static PyObject*
4737DBTxn_prepare(DBTxnObject* self, PyObject* args)
4738{
4739#if (DBVER >= 33)
4740 int err;
4741 char* gid=NULL;
4742 int gid_size=0;
4743
Gregory P. Smith361ed152007-08-23 07:32:27 +00004744 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004745 return NULL;
4746
4747 if (gid_size != DB_XIDDATASIZE) {
4748 PyErr_SetString(PyExc_TypeError,
4749 "gid must be DB_XIDDATASIZE bytes long");
4750 return NULL;
4751 }
4752
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004753 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004754 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4755 "after txn_commit or txn_abort");
4756 PyErr_SetObject(DBError, t);
4757 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004758 return NULL;
4759 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004760 MYDB_BEGIN_ALLOW_THREADS;
4761#if (DBVER >= 40)
4762 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4763#else
4764 err = txn_prepare(self->txn, (u_int8_t*)gid);
4765#endif
4766 MYDB_END_ALLOW_THREADS;
4767 RETURN_IF_ERR();
4768 RETURN_NONE();
4769#else
4770 int err;
4771
4772 if (!PyArg_ParseTuple(args, ":prepare"))
4773 return NULL;
4774
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004775 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004776 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4777 "after txn_commit or txn_abort");
4778 PyErr_SetObject(DBError, t);
4779 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004780 return NULL;
4781 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004782 MYDB_BEGIN_ALLOW_THREADS;
4783 err = txn_prepare(self->txn);
4784 MYDB_END_ALLOW_THREADS;
4785 RETURN_IF_ERR();
4786 RETURN_NONE();
4787#endif
4788}
4789
4790
4791static PyObject*
4792DBTxn_abort(DBTxnObject* self, PyObject* args)
4793{
4794 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004795 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004796
4797 if (!PyArg_ParseTuple(args, ":abort"))
4798 return NULL;
4799
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004800 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004801 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4802 "after txn_commit or txn_abort");
4803 PyErr_SetObject(DBError, t);
4804 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004805 return NULL;
4806 }
4807 txn = self->txn;
4808 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809 MYDB_BEGIN_ALLOW_THREADS;
4810#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004811 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004812#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004813 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004814#endif
4815 MYDB_END_ALLOW_THREADS;
4816 RETURN_IF_ERR();
4817 RETURN_NONE();
4818}
4819
4820
4821static PyObject*
4822DBTxn_id(DBTxnObject* self, PyObject* args)
4823{
4824 int id;
4825
4826 if (!PyArg_ParseTuple(args, ":id"))
4827 return NULL;
4828
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004829 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004830 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4831 "after txn_commit or txn_abort");
4832 PyErr_SetObject(DBError, t);
4833 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004834 return NULL;
4835 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004836 MYDB_BEGIN_ALLOW_THREADS;
4837#if (DBVER >= 40)
4838 id = self->txn->id(self->txn);
4839#else
4840 id = txn_id(self->txn);
4841#endif
4842 MYDB_END_ALLOW_THREADS;
Christian Heimes217cfd12007-12-02 14:31:20 +00004843 return PyLong_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004844}
4845
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004846#if (DBVER >= 43)
4847/* --------------------------------------------------------------------- */
4848/* DBSequence methods */
4849
4850
4851static PyObject*
4852DBSequence_close(DBSequenceObject* self, PyObject* args)
4853{
4854 int err, flags=0;
4855 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4856 return NULL;
4857 CHECK_SEQUENCE_NOT_CLOSED(self)
4858
4859 MYDB_BEGIN_ALLOW_THREADS
4860 err = self->sequence->close(self->sequence, flags);
4861 self->sequence = NULL;
4862 MYDB_END_ALLOW_THREADS
4863
4864 RETURN_IF_ERR();
4865
4866 RETURN_NONE();
4867}
4868
4869static PyObject*
4870DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4871{
4872 int err, flags = 0;
4873 int delta = 1;
4874 db_seq_t value;
4875 PyObject *txnobj = NULL;
4876 DB_TXN *txn = NULL;
4877 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4878 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4879 return NULL;
4880 CHECK_SEQUENCE_NOT_CLOSED(self)
4881
4882 if (!checkTxnObj(txnobj, &txn))
4883 return NULL;
4884
4885 MYDB_BEGIN_ALLOW_THREADS
4886 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4887 MYDB_END_ALLOW_THREADS
4888
4889 RETURN_IF_ERR();
4890 return PyLong_FromLongLong(value);
4891
4892}
4893
4894static PyObject*
4895DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4896{
4897 if (!PyArg_ParseTuple(args,":get_dbp"))
4898 return NULL;
4899 CHECK_SEQUENCE_NOT_CLOSED(self)
4900 Py_INCREF(self->mydb);
4901 return (PyObject* )self->mydb;
4902}
4903
4904static PyObject*
4905DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4906{
4907 int err;
4908 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004909 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004910 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004911 CHECK_SEQUENCE_NOT_CLOSED(self)
4912 MYDB_BEGIN_ALLOW_THREADS
4913 err = self->sequence->get_key(self->sequence, &key);
4914 MYDB_END_ALLOW_THREADS
4915
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004916 if (!err)
Christian Heimes72b710a2008-05-26 13:28:38 +00004917 retval = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004918
4919 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004920 RETURN_IF_ERR();
4921
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004922 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004923}
4924
4925static PyObject*
4926DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4927{
4928 int err;
4929 db_seq_t value;
4930 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4931 return NULL;
4932 CHECK_SEQUENCE_NOT_CLOSED(self)
4933
4934 MYDB_BEGIN_ALLOW_THREADS
4935 err = self->sequence->initial_value(self->sequence, value);
4936 MYDB_END_ALLOW_THREADS
4937
4938 RETURN_IF_ERR();
4939
4940 RETURN_NONE();
4941}
4942
4943static PyObject*
4944DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4945{
4946 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004947 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004948 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004949 PyObject *txnobj = NULL;
4950 DB_TXN *txn = NULL;
4951 DBT key;
4952
4953 static char* kwnames[] = {"key", "txn", "flags", NULL };
4954 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4955 return NULL;
4956
4957 if (!checkTxnObj(txnobj, &txn))
4958 return NULL;
4959
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004960 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004961 return NULL;
4962
4963 MYDB_BEGIN_ALLOW_THREADS
4964 err = self->sequence->open(self->sequence, txn, &key, flags);
4965 MYDB_END_ALLOW_THREADS
4966
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004967 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004968 RETURN_IF_ERR();
4969
4970 RETURN_NONE();
4971}
4972
4973static PyObject*
4974DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4975{
4976 int err, flags = 0;
4977 PyObject *txnobj = NULL;
4978 DB_TXN *txn = NULL;
4979
4980 static char* kwnames[] = {"txn", "flags", NULL };
4981 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4982 return NULL;
4983
4984 if (!checkTxnObj(txnobj, &txn))
4985 return NULL;
4986
4987 CHECK_SEQUENCE_NOT_CLOSED(self)
4988
4989 MYDB_BEGIN_ALLOW_THREADS
4990 err = self->sequence->remove(self->sequence, txn, flags);
4991 MYDB_END_ALLOW_THREADS
4992
4993 RETURN_IF_ERR();
4994 RETURN_NONE();
4995}
4996
4997static PyObject*
4998DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4999{
5000 int err, size;
5001 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5002 return NULL;
5003 CHECK_SEQUENCE_NOT_CLOSED(self)
5004
5005 MYDB_BEGIN_ALLOW_THREADS
5006 err = self->sequence->set_cachesize(self->sequence, size);
5007 MYDB_END_ALLOW_THREADS
5008
5009 RETURN_IF_ERR();
5010 RETURN_NONE();
5011}
5012
5013static PyObject*
5014DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5015{
5016 int err, size;
5017 if (!PyArg_ParseTuple(args,":get_cachesize"))
5018 return NULL;
5019 CHECK_SEQUENCE_NOT_CLOSED(self)
5020
5021 MYDB_BEGIN_ALLOW_THREADS
5022 err = self->sequence->get_cachesize(self->sequence, &size);
5023 MYDB_END_ALLOW_THREADS
5024
5025 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005026 return PyLong_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005027}
5028
5029static PyObject*
5030DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5031{
5032 int err, flags = 0;
5033 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5036
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->set_flags(self->sequence, flags);
5039 MYDB_END_ALLOW_THREADS
5040
5041 RETURN_IF_ERR();
5042 RETURN_NONE();
5043
5044}
5045
5046static PyObject*
5047DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5048{
5049 unsigned int flags;
5050 int err;
5051 if (!PyArg_ParseTuple(args,":get_flags"))
5052 return NULL;
5053 CHECK_SEQUENCE_NOT_CLOSED(self)
5054
5055 MYDB_BEGIN_ALLOW_THREADS
5056 err = self->sequence->get_flags(self->sequence, &flags);
5057 MYDB_END_ALLOW_THREADS
5058
5059 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005060 return PyLong_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005061}
5062
5063static PyObject*
5064DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5065{
5066 int err;
5067 db_seq_t min, max;
5068 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5069 return NULL;
5070 CHECK_SEQUENCE_NOT_CLOSED(self)
5071
5072 MYDB_BEGIN_ALLOW_THREADS
5073 err = self->sequence->set_range(self->sequence, min, max);
5074 MYDB_END_ALLOW_THREADS
5075
5076 RETURN_IF_ERR();
5077 RETURN_NONE();
5078}
5079
5080static PyObject*
5081DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5082{
5083 int err;
5084 db_seq_t min, max;
5085 if (!PyArg_ParseTuple(args,":get_range"))
5086 return NULL;
5087 CHECK_SEQUENCE_NOT_CLOSED(self)
5088
5089 MYDB_BEGIN_ALLOW_THREADS
5090 err = self->sequence->get_range(self->sequence, &min, &max);
5091 MYDB_END_ALLOW_THREADS
5092
5093 RETURN_IF_ERR();
5094 return Py_BuildValue("(LL)", min, max);
5095}
5096
5097static PyObject*
5098DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5099{
5100 int err, flags = 0;
5101 DB_SEQUENCE_STAT* sp = NULL;
5102 PyObject* dict_stat;
5103 static char* kwnames[] = {"flags", NULL };
5104 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5105 return NULL;
5106 CHECK_SEQUENCE_NOT_CLOSED(self);
5107
5108 MYDB_BEGIN_ALLOW_THREADS;
5109 err = self->sequence->stat(self->sequence, &sp, flags);
5110 MYDB_END_ALLOW_THREADS;
5111 RETURN_IF_ERR();
5112
5113 if ((dict_stat = PyDict_New()) == NULL) {
5114 free(sp);
5115 return NULL;
5116 }
5117
5118
5119#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5120#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5121
5122 MAKE_INT_ENTRY(wait);
5123 MAKE_INT_ENTRY(nowait);
5124 MAKE_LONG_LONG_ENTRY(current);
5125 MAKE_LONG_LONG_ENTRY(value);
5126 MAKE_LONG_LONG_ENTRY(last_value);
5127 MAKE_LONG_LONG_ENTRY(min);
5128 MAKE_LONG_LONG_ENTRY(max);
5129 MAKE_INT_ENTRY(cache_size);
5130 MAKE_INT_ENTRY(flags);
5131
5132#undef MAKE_INT_ENTRY
5133#undef MAKE_LONG_LONG_ENTRY
5134
5135 free(sp);
5136 return dict_stat;
5137}
5138#endif
5139
5140
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005141/* --------------------------------------------------------------------- */
5142/* Method definition tables and type objects */
5143
5144static PyMethodDef DB_methods[] = {
5145 {"append", (PyCFunction)DB_append, METH_VARARGS},
5146#if (DBVER >= 33)
5147 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5148#endif
5149 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5151 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005152 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5153 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5154 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5155 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005156#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005157 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005158#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005159 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5160 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5161 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5162 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5163 {"join", (PyCFunction)DB_join, METH_VARARGS},
5164 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5165 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5166 {"items", (PyCFunction)DB_items, METH_VARARGS},
5167 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5168 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5169 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5170 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5171 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5172 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005173#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005174 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005175#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005177#if (DBVER >= 41)
5178 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5179#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005180 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5181 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5182 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5183 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5184 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5185 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5186 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5187 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5188 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005189 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005190 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005191 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5192#if (DBVER >= 33)
5193 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5194#endif
5195 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5196 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5197 {"values", (PyCFunction)DB_values, METH_VARARGS},
5198 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5199 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5200 {NULL, NULL} /* sentinel */
5201};
5202
5203
5204static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005205 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005206 (binaryfunc)DB_subscript, /*mp_subscript*/
5207 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5208};
5209
5210
5211static PyMethodDef DBCursor_methods[] = {
5212 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5213 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5214 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5215 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5216 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5217 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5218 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005219#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005220 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005221#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005222 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5223 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5224 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5225 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5226 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5227 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5228 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5229 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005230 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005231 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005232 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5233 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5234 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5235 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5236 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5237 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5238 {NULL, NULL} /* sentinel */
5239};
5240
5241
5242static PyMethodDef DBEnv_methods[] = {
5243 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5244 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5245 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005246#if (DBVER >= 41)
5247 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5248 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5249 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5250#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005251#if (DBVER >= 40)
5252 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5253#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005254 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005255 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5256 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005257 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005258 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5259 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5260 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005261#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005262 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005265#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005266 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005268 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5269 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5270 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005271 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5272 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5273 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5274 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5275 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5276 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005277 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005278 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5279 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5280 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005281#if (DBVER >= 40)
5282 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5283#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005284 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5285 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5286 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005287#if (DBVER >= 40)
5288 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5289#endif
5290#if (DBVER >= 44)
5291 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5292#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005293 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5294 {NULL, NULL} /* sentinel */
5295};
5296
5297
5298static PyMethodDef DBTxn_methods[] = {
5299 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5300 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5301 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5302 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5303 {NULL, NULL} /* sentinel */
5304};
5305
5306
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005307#if (DBVER >= 43)
5308static PyMethodDef DBSequence_methods[] = {
5309 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5310 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5311 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5312 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5313 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5314 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5315 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5316 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5317 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5318 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5319 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5320 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5321 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5322 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5323 {NULL, NULL} /* sentinel */
5324};
5325#endif
5326
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005327static PyObject*
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005328DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005329{
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005330 CHECK_ENV_NOT_CLOSED(self);
5331 if (self->db_env->db_home == NULL) {
5332 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005333 }
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005334 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005335}
5336
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005337static PyGetSetDef DBEnv_getsets[] = {
5338 {"db_home", (getter)DBEnv_db_home_get, NULL,},
5339 {NULL}
5340};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005341
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005342
Neal Norwitz227b5332006-03-22 09:28:35 +00005343static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005344 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005345 "DB", /*tp_name*/
5346 sizeof(DBObject), /*tp_basicsize*/
5347 0, /*tp_itemsize*/
5348 /* methods */
5349 (destructor)DB_dealloc, /*tp_dealloc*/
5350 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005351 0, /*tp_getattr*/
5352 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005353 0, /*tp_compare*/
5354 0, /*tp_repr*/
5355 0, /*tp_as_number*/
5356 0, /*tp_as_sequence*/
5357 &DB_mapping,/*tp_as_mapping*/
5358 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005359 0, /* tp_call */
5360 0, /* tp_str */
5361 0, /* tp_getattro */
5362 0, /* tp_setattro */
5363 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005364 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005365 0, /* tp_doc */
5366 0, /* tp_traverse */
5367 0, /* tp_clear */
5368 0, /* tp_richcompare */
5369 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005370 0, /* tp_iter */
5371 0, /* tp_iternext */
5372 DB_methods, /* tp_methods */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005373};
5374
5375
Neal Norwitz227b5332006-03-22 09:28:35 +00005376static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005377 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005378 "DBCursor", /*tp_name*/
5379 sizeof(DBCursorObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5383 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005384 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5391 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005392 0, /* tp_call */
5393 0, /* tp_str */
5394 0, /* tp_getattro */
5395 0, /* tp_setattro */
5396 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005397 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005398 0, /* tp_doc */
5399 0, /* tp_traverse */
5400 0, /* tp_clear */
5401 0, /* tp_richcompare */
5402 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005403 0, /* tp_iter */
5404 0, /* tp_iternext */
5405 DBCursor_methods, /* tp_methods */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005406};
5407
5408
Neal Norwitz227b5332006-03-22 09:28:35 +00005409static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005410 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005411 "DBEnv", /*tp_name*/
5412 sizeof(DBEnvObject), /*tp_basicsize*/
5413 0, /*tp_itemsize*/
5414 /* methods */
5415 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5416 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005417 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005418 0, /*tp_setattr*/
5419 0, /*tp_compare*/
5420 0, /*tp_repr*/
5421 0, /*tp_as_number*/
5422 0, /*tp_as_sequence*/
5423 0, /*tp_as_mapping*/
5424 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005425 0, /* tp_call */
5426 0, /* tp_str */
5427 0, /* tp_getattro */
5428 0, /* tp_setattro */
5429 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005430 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005431 0, /* tp_doc */
5432 0, /* tp_traverse */
5433 0, /* tp_clear */
5434 0, /* tp_richcompare */
5435 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005436 0, /* tp_iter */
5437 0, /* tp_iternext */
5438 DBEnv_methods, /* tp_methods */
5439 0, /* tp_members */
5440 DBEnv_getsets, /* tp_getsets */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005441};
5442
Neal Norwitz227b5332006-03-22 09:28:35 +00005443static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005444 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005445 "DBTxn", /*tp_name*/
5446 sizeof(DBTxnObject), /*tp_basicsize*/
5447 0, /*tp_itemsize*/
5448 /* methods */
5449 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5450 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005451 0, /*tp_getattr*/
5452 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005453 0, /*tp_compare*/
5454 0, /*tp_repr*/
5455 0, /*tp_as_number*/
5456 0, /*tp_as_sequence*/
5457 0, /*tp_as_mapping*/
5458 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005459 0, /* tp_call */
5460 0, /* tp_str */
5461 0, /* tp_getattro */
5462 0, /* tp_setattro */
5463 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005464 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005465 0, /* tp_doc */
5466 0, /* tp_traverse */
5467 0, /* tp_clear */
5468 0, /* tp_richcompare */
5469 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005470 0, /* tp_iter */
5471 0, /* tp_iternext */
5472 DBTxn_methods, /* tp_methods */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005473};
5474
5475
Neal Norwitz227b5332006-03-22 09:28:35 +00005476static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005477 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005478 "DBLock", /*tp_name*/
5479 sizeof(DBLockObject), /*tp_basicsize*/
5480 0, /*tp_itemsize*/
5481 /* methods */
5482 (destructor)DBLock_dealloc, /*tp_dealloc*/
5483 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005484 0, /*tp_getattr*/
5485 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005486 0, /*tp_compare*/
5487 0, /*tp_repr*/
5488 0, /*tp_as_number*/
5489 0, /*tp_as_sequence*/
5490 0, /*tp_as_mapping*/
5491 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005492 0, /* tp_call */
5493 0, /* tp_str */
5494 0, /* tp_getattro */
5495 0, /* tp_setattro */
5496 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005497 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005498 0, /* tp_doc */
5499 0, /* tp_traverse */
5500 0, /* tp_clear */
5501 0, /* tp_richcompare */
5502 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005503};
5504
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005505#if (DBVER >= 43)
5506static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005507 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005508 "DBSequence", /*tp_name*/
5509 sizeof(DBSequenceObject), /*tp_basicsize*/
5510 0, /*tp_itemsize*/
5511 /* methods */
5512 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5513 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005514 0, /*tp_getattr*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005515 0, /*tp_setattr*/
5516 0, /*tp_compare*/
5517 0, /*tp_repr*/
5518 0, /*tp_as_number*/
5519 0, /*tp_as_sequence*/
5520 0, /*tp_as_mapping*/
5521 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005522 0, /* tp_call */
5523 0, /* tp_str */
5524 0, /* tp_getattro */
5525 0, /* tp_setattro */
5526 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005527 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005528 0, /* tp_doc */
5529 0, /* tp_traverse */
5530 0, /* tp_clear */
5531 0, /* tp_richcompare */
5532 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005533 0, /* tp_iter */
5534 0, /* tp_iternext */
5535 DBSequence_methods, /* tp_methods */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005536};
5537#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005538
5539/* --------------------------------------------------------------------- */
5540/* Module-level functions */
5541
5542static PyObject*
5543DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5544{
5545 PyObject* dbenvobj = NULL;
5546 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005547 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005548
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5550 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005551 return NULL;
5552 if (dbenvobj == Py_None)
5553 dbenvobj = NULL;
5554 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5555 makeTypeError("DBEnv", dbenvobj);
5556 return NULL;
5557 }
5558
5559 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5560}
5561
5562
5563static PyObject*
5564DBEnv_construct(PyObject* self, PyObject* args)
5565{
5566 int flags = 0;
5567 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5568 return (PyObject* )newDBEnvObject(flags);
5569}
5570
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005571#if (DBVER >= 43)
5572static PyObject*
5573DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5574{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005575 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005576 int flags = 0;
5577 static char* kwnames[] = { "db", "flags", NULL};
5578
5579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5580 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005581 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005582 makeTypeError("DB", dbobj);
5583 return NULL;
5584 }
5585 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5586}
5587#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005588
5589static char bsddb_version_doc[] =
5590"Returns a tuple of major, minor, and patch release numbers of the\n\
5591underlying DB library.";
5592
5593static PyObject*
5594bsddb_version(PyObject* self, PyObject* args)
5595{
5596 int major, minor, patch;
5597
5598 if (!PyArg_ParseTuple(args, ":version"))
5599 return NULL;
5600 db_version(&major, &minor, &patch);
5601 return Py_BuildValue("(iii)", major, minor, patch);
5602}
5603
5604
5605/* List of functions defined in the module */
5606
5607static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005608 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5609 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5610#if (DBVER >= 43)
5611 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5612#endif
5613 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005614 {NULL, NULL} /* sentinel */
5615};
5616
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005617/* API structure */
5618static BSDDB_api bsddb_api;
5619
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005620
5621/* --------------------------------------------------------------------- */
5622/* Module initialization */
5623
5624
5625/* Convenience routine to export an integer value.
5626 * Errors are silently ignored, for better or for worse...
5627 */
5628#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5629
Gregory P. Smith41631e82003-09-21 00:08:14 +00005630#define MODULE_NAME_MAX_LEN 11
5631static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005632
Martin v. Löwis1a214512008-06-11 05:26:20 +00005633
5634static struct PyModuleDef _bsddbmodule = {
5635 PyModuleDef_HEAD_INIT,
5636 _bsddbModuleName,
5637 NULL,
5638 -1,
5639 bsddb_methods,
5640 NULL,
5641 NULL,
5642 NULL,
5643 NULL
5644};
5645
5646PyMODINIT_FUNC PyInit__bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647{
5648 PyObject* m;
5649 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005650 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5651 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5652 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005653 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005654
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00005655 /* Initialize object types */
5656 if (PyType_Ready(&DB_Type) < 0)
5657 return NULL;
5658 if (PyType_Ready(&DBCursor_Type) < 0)
5659 return NULL;
5660 if (PyType_Ready(&DBEnv_Type) < 0)
5661 return NULL;
5662 if (PyType_Ready(&DBTxn_Type) < 0)
5663 return NULL;
5664 if (PyType_Ready(&DBLock_Type) < 0)
5665 return NULL;
5666#if (DBVER >= 43)
5667 if (PyType_Ready(&DBSequence_Type) < 0)
5668 return NULL;
5669#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 */
Martin v. Löwis1a214512008-06-11 05:26:20 +00005678 m = PyModule_Create(&_bsddbmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005679 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +00005680 return NULL;
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öwis1a214512008-06-11 05:26:20 +00006069 Py_DECREF(m);
6070 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006071 }
Martin v. Löwis1a214512008-06-11 05:26:20 +00006072 return m;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006073}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006074
6075/* allow this module to be named _pybsddb so that it can be installed
6076 * and imported on top of python >= 2.3 that includes its own older
6077 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006078PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006079{
6080 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Martin v. Löwis1a214512008-06-11 05:26:20 +00006081 return PyInit__bsddb();
Gregory P. Smith41631e82003-09-21 00:08:14 +00006082}