blob: 3a67a1e600a8c5f2db0e34434afd87a21230567c [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithc4119182007-09-09 20:17:22 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Gregory P. Smithc4119182007-09-09 20:17:22 +000051 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000052 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
Guido van Rossum8ce8a782007-11-01 19:42:39 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000101typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102#endif
103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000194#if PYTHON_API_VERSION < 1010
195#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000196#endif
197
Gregory P. Smith31c50652004-06-28 01:20:40 +0000198
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000199/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000200#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000201#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000202
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203
Neal Norwitz227b5332006-03-22 09:28:35 +0000204static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000205
Christian Heimes90aa7642007-12-19 02:45:37 +0000206#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000211#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +0000212#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000254
255static int makeDBError(int err);
256
257
258/* Return the access method type of the DBObject */
259static int _DB_get_type(DBObject* self)
260{
261#if (DBVER >= 33)
262 DBTYPE type;
263 int err;
264 err = self->db->get_type(self->db, &type);
265 if (makeDBError(err)) {
266 return -1;
267 }
268 return type;
269#else
270 return self->db->get_type(self->db);
271#endif
272}
273
274
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000275/* Handy function to free a DBT and any self-allocated data within.
276 To be used on self created DBTs. The make_dbt and make_key_dbt
277 functions have their own free routines that do more that this. */
278static void free_dbt(DBT *dbt)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279{
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000280 if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
281 free(dbt->data);
282 dbt->data = NULL;
283 }
284}
285
286
287/* Cleanup a Python buffer API view created by make_dbt() */
Thomas Heller39763a12007-09-24 14:43:56 +0000288static void free_buf_view(PyObject *obj, Py_buffer *view)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000289{
290 if (view) {
291 PyObject_ReleaseBuffer(obj, view);
292 PyMem_Free(view);
293 }
294}
295
296
297/* Cleanup a DBT and an associated Python buffer API view
298 created by make_key_dbt() */
299#define FREE_DBT_VIEW(dbt, obj, view) \
300 do { \
301 free_dbt(&(dbt)); \
302 free_buf_view((obj), (view)); \
303 } while(0);
304
305
Thomas Heller39763a12007-09-24 14:43:56 +0000306static Py_buffer * _malloc_view(PyObject *obj)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000307{
Thomas Heller39763a12007-09-24 14:43:56 +0000308 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000309
Thomas Heller39763a12007-09-24 14:43:56 +0000310 if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000311 PyErr_SetString(PyExc_MemoryError,
Thomas Heller39763a12007-09-24 14:43:56 +0000312 "Py_buffer malloc failed");
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000313 return NULL;
314 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000315 if (view->ndim > 1) {
316 PyErr_SetString(PyExc_BufferError,
317 "buffers must be single dimension");
318 PyObject_ReleaseBuffer(obj, view);
319 PyMem_Free(view);
320 return NULL;
321 }
322 return view;
323}
324
325
326/* Create a DBT structure (containing key and data values) from Python
327 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000328 may be filled with a newly allocated Py_buffer view on success.
329 The caller MUST call free_buf_view() on any returned Py_buffer. */
330static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000331{
Thomas Heller39763a12007-09-24 14:43:56 +0000332 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000333
334 /* simple way to ensure the caller can detect if we've returned a
335 new buffer view or not: require their pointer to start out NULL. */
336 assert(*returned_view_p == NULL);
337
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000338 CLEAR_DBT(*dbt);
339 if (obj == Py_None) {
340 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000341 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000342 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000343 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000344 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000345 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346 return 0;
347 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000348
349 if ( !(view = _malloc_view(obj)) )
350 return 0;
351
352 dbt->data = view->buf;
353 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
354 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000355 return 1;
356}
357
358
359/* Recno and Queue DBs can have integer keys. This function figures out
360 what's been given, verifies that it's allowed, and then makes the DBT.
361
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000362 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000363 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000364static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000365make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000366 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000367{
368 db_recno_t recno;
369 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000370 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000371
372 /* simple way to ensure the caller can detect if we've returned a
373 new buffer view or not: require their pointer to start out NULL. */
374 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000375
376 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000377 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000378 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000379 if (type == -1)
380 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000381 if (type == DB_RECNO || type == DB_QUEUE) {
382 PyErr_SetString(
383 PyExc_TypeError,
384 "None keys not allowed for Recno and Queue DB's");
385 return 0;
386 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000387 /* no need to do anything, the structure has already been zeroed */
388 }
389
Christian Heimes217cfd12007-12-02 14:31:20 +0000390 else if (PyLong_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000391 /* verify access method type */
392 type = _DB_get_type(self);
393 if (type == -1)
394 return 0;
395 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396 /* if BTREE then an Integer key is allowed with the
397 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 *pflags |= DB_SET_RECNO;
399 }
400 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000401 PyErr_SetString(
402 PyExc_TypeError,
403 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000404 return 0;
405 }
406
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 /* Make a key out of the requested recno, use allocated space so DB
408 * will be able to realloc room for the real key if needed. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000409 recno = PyLong_AS_LONG(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000410 key->data = malloc(sizeof(db_recno_t));
411 if (key->data == NULL) {
412 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
413 return 0;
414 }
415 key->ulen = key->size = sizeof(db_recno_t);
416 memcpy(key->data, &recno, sizeof(db_recno_t));
417 key->flags = DB_DBT_REALLOC;
418 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000419
420 else if (PyObject_CheckBuffer(keyobj)) {
421 /* verify access method type */
422 type = _DB_get_type(self);
423 if (type == -1)
424 return 0;
425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "Non-integer keys not allowed for Recno and Queue DB's");
429 return 0;
430 }
431
432 if ( !(view = _malloc_view(keyobj)) )
433 return 0;
434
Gregory P. Smith568065e2007-11-01 21:55:08 +0000435 /*
436 * NOTE(gps): I don't like doing a data copy here, it seems
437 * wasteful. But without a clean way to tell FREE_DBT if it
438 * should free key->data or not we have to. Other places in
439 * the code check for DB_THREAD and forceably set DBT_MALLOC
440 * when we otherwise would leave flags 0 to indicate that.
441 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000442 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000443 key->data = malloc(key->size);
444 if (key->data == NULL) {
445 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
446 key->size = 0;
447 return 0;
448 }
449 memcpy(key->data, view->buf, key->size);
450 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000451 *returned_view_p = view;
452 }
453
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000454 else {
455 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000456 "buffer or int object expected for key, %s found",
Christian Heimes90aa7642007-12-19 02:45:37 +0000457 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000458 return 0;
459 }
460
461 return 1;
462}
463
464
465/* Add partial record access to an existing DBT data struct.
466 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
467 and the data storage/retrieval will be done using dlen and doff. */
468static int add_partial_dbt(DBT* d, int dlen, int doff) {
469 /* if neither were set we do nothing (-1 is the default value) */
470 if ((dlen == -1) && (doff == -1)) {
471 return 1;
472 }
473
474 if ((dlen < 0) || (doff < 0)) {
475 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
476 return 0;
477 }
478
479 d->flags = d->flags | DB_DBT_PARTIAL;
480 d->dlen = (unsigned int) dlen;
481 d->doff = (unsigned int) doff;
482 return 1;
483}
484
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000485/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
486/* TODO: make this use the native libc strlcpy() when available (BSD) */
487unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
488{
489 unsigned int srclen, copylen;
490
491 srclen = strlen(src);
492 if (n <= 0)
493 return srclen;
494 copylen = (srclen > n-1) ? n-1 : srclen;
495 /* populate dest[0] thru dest[copylen-1] */
496 memcpy(dest, src, copylen);
497 /* guarantee null termination */
498 dest[copylen] = 0;
499
500 return srclen;
501}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000502
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000503/* Callback used to save away more information about errors from the DB
504 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000505static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000506#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000507static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000508#else
509static void _db_errorCallback(const DB_ENV *db_env,
510 const char* prefix, const char* msg)
511#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514}
515
516
517/* make a nice exception object to raise for errors. */
518static int makeDBError(int err)
519{
520 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000521 PyObject *errObj = NULL;
522 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000523 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000524 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000525
526 switch (err) {
527 case 0: /* successful, no error */ break;
528
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000529#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 case DB_INCOMPLETE:
531#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000532 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
533 /* Ensure that bytes_left never goes negative */
534 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
535 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
536 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000538 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000539 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000540 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000541 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000542
543#else /* do an exception instead */
544 errObj = DBIncompleteError;
545#endif
546 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000547#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000548
549 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
550 case DB_KEYEXIST: errObj = DBKeyExistError; break;
551 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
552 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
553 case DB_NOTFOUND: errObj = DBNotFoundError; break;
554 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
555 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
556 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
557 case DB_NOSERVER: errObj = DBNoServerError; break;
558 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
559 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
560#if (DBVER >= 33)
561 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
562 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
563#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000564 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000565
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000566#if (DBVER >= 43)
567 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
568 case ENOMEM: errObj = PyExc_MemoryError; break;
569#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000570 case EINVAL: errObj = DBInvalidArgError; break;
571 case EACCES: errObj = DBAccessError; break;
572 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000573 case EAGAIN: errObj = DBAgainError; break;
574 case EBUSY : errObj = DBBusyError; break;
575 case EEXIST: errObj = DBFileExistsError; break;
576 case ENOENT: errObj = DBNoSuchFileError; break;
577 case EPERM : errObj = DBPermissionsError; break;
578
579 default: errObj = DBError; break;
580 }
581
582 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000583 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
584 /* Ensure that bytes_left never goes negative */
585 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
586 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
587 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000588 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000589 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000590 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000591 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000592
593 errTuple = Py_BuildValue("(is)", err, errTxt);
594 PyErr_SetObject(errObj, errTuple);
595 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 }
597
598 return ((errObj != NULL) || exceptionRaised);
599}
600
601
602
603/* set a type exception */
604static void makeTypeError(char* expected, PyObject* found)
605{
606 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000607 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608}
609
610
611/* verify that an obj is either None or a DBTxn, and set the txn pointer */
612static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
613{
614 if (txnobj == Py_None || txnobj == NULL) {
615 *txn = NULL;
616 return 1;
617 }
618 if (DBTxnObject_Check(txnobj)) {
619 *txn = ((DBTxnObject*)txnobj)->txn;
620 return 1;
621 }
622 else
623 makeTypeError("DBTxn", txnobj);
624 return 0;
625}
626
627
628/* Delete a key from a database
629 Returns 0 on success, -1 on an error. */
630static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
631{
632 int err;
633
634 MYDB_BEGIN_ALLOW_THREADS;
635 err = self->db->del(self->db, txn, key, 0);
636 MYDB_END_ALLOW_THREADS;
637 if (makeDBError(err)) {
638 return -1;
639 }
640 self->haveStat = 0;
641 return 0;
642}
643
644
645/* Store a key into a database
646 Returns 0 on success, -1 on an error. */
647static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
648{
649 int err;
650
651 MYDB_BEGIN_ALLOW_THREADS;
652 err = self->db->put(self->db, txn, key, data, flags);
653 MYDB_END_ALLOW_THREADS;
654 if (makeDBError(err)) {
655 return -1;
656 }
657 self->haveStat = 0;
658 return 0;
659}
660
661/* Get a key/data pair from a cursor */
662static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
663 PyObject *args, PyObject *kwargs, char *format)
664{
665 int err;
666 PyObject* retval = NULL;
667 DBT key, data;
668 int dlen = -1;
669 int doff = -1;
670 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000671 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000672
673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
674 &flags, &dlen, &doff))
675 return NULL;
676
677 CHECK_CURSOR_NOT_CLOSED(self);
678
679 flags |= extra_flags;
680 CLEAR_DBT(key);
681 CLEAR_DBT(data);
682 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
683 /* Tell BerkeleyDB to malloc the return value (thread safe) */
684 data.flags = DB_DBT_MALLOC;
685 key.flags = DB_DBT_MALLOC;
686 }
687 if (!add_partial_dbt(&data, dlen, doff))
688 return NULL;
689
690 MYDB_BEGIN_ALLOW_THREADS;
691 err = self->dbc->c_get(self->dbc, &key, &data, flags);
692 MYDB_END_ALLOW_THREADS;
693
Gregory P. Smithe9477062005-06-04 06:46:59 +0000694 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
695 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000696 Py_INCREF(Py_None);
697 retval = Py_None;
698 }
699 else if (makeDBError(err)) {
700 retval = NULL;
701 }
702 else { /* otherwise, success! */
703
704 /* if Recno or Queue, return the key as an Int */
705 switch (_DB_get_type(self->mydb)) {
706 case -1:
707 retval = NULL;
708 break;
709
710 case DB_RECNO:
711 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000712 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000713 data.data, data.size);
714 break;
715 case DB_HASH:
716 case DB_BTREE:
717 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000718 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000719 data.data, data.size);
720 break;
721 }
722 }
723 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000724 free_dbt(&key);
725 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 }
727 return retval;
728}
729
730
731/* add an integer to a dictionary using the given name as a key */
732static void _addIntToDict(PyObject* dict, char *name, int value)
733{
Christian Heimes217cfd12007-12-02 14:31:20 +0000734 PyObject* v = PyLong_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 if (!v || PyDict_SetItemString(dict, name, v))
736 PyErr_Clear();
737
738 Py_XDECREF(v);
739}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000740
741/* The same, when the value is a time_t */
742static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
743{
744 PyObject* v;
745 /* if the value fits in regular int, use that. */
746#ifdef HAVE_LONG_LONG
747 if (sizeof(time_t) > sizeof(long))
748 v = PyLong_FromLongLong((PY_LONG_LONG) value);
749 else
750#endif
Christian Heimes217cfd12007-12-02 14:31:20 +0000751 v = PyLong_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000752 if (!v || PyDict_SetItemString(dict, name, v))
753 PyErr_Clear();
754
755 Py_XDECREF(v);
756}
757
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000758#if (DBVER >= 43)
759/* add an db_seq_t to a dictionary using the given name as a key */
760static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
761{
762 PyObject* v = PyLong_FromLongLong(value);
763 if (!v || PyDict_SetItemString(dict, name, v))
764 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000766 Py_XDECREF(v);
767}
768#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769
770
771
772/* --------------------------------------------------------------------- */
773/* Allocators and deallocators */
774
775static DBObject*
776newDBObject(DBEnvObject* arg, int flags)
777{
778 DBObject* self;
779 DB_ENV* db_env = NULL;
780 int err;
781
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000782 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 if (self == NULL)
784 return NULL;
785
786 self->haveStat = 0;
787 self->flags = 0;
788 self->setflags = 0;
789 self->myenvobj = NULL;
790#if (DBVER >= 33)
791 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000792 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 self->primaryDBType = 0;
794#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000795 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000796
797 /* keep a reference to our python DBEnv object */
798 if (arg) {
799 Py_INCREF(arg);
800 self->myenvobj = arg;
801 db_env = arg->db_env;
802 }
803
804 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000805 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000807 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
808 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809
810 MYDB_BEGIN_ALLOW_THREADS;
811 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000812 if (self->db != NULL) {
813 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000815 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000817 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000818 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000819 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
820 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000821 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000822 if (makeDBError(err)) {
823 if (self->myenvobj) {
824 Py_DECREF(self->myenvobj);
825 self->myenvobj = NULL;
826 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000827 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 self = NULL;
829 }
830 return self;
831}
832
833
834static void
835DB_dealloc(DBObject* self)
836{
837 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000838 /* avoid closing a DB when its DBEnv has been closed out from under
839 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000840 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000841 (self->myenvobj && self->myenvobj->db_env))
842 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 MYDB_BEGIN_ALLOW_THREADS;
844 self->db->close(self->db, 0);
845 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000847 PyErr_WarnEx(PyExc_RuntimeWarning,
848 "DB could not be closed in destructor:"
849 " DBEnv already closed",
850 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 }
852 self->db = NULL;
853 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000854 if (self->in_weakreflist != NULL) {
855 PyObject_ClearWeakRefs((PyObject *) self);
856 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857 if (self->myenvobj) {
858 Py_DECREF(self->myenvobj);
859 self->myenvobj = NULL;
860 }
861#if (DBVER >= 33)
862 if (self->associateCallback != NULL) {
863 Py_DECREF(self->associateCallback);
864 self->associateCallback = NULL;
865 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000866 if (self->btCompareCallback != NULL) {
867 Py_DECREF(self->btCompareCallback);
868 self->btCompareCallback = NULL;
869 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000871 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000872}
873
874
875static DBCursorObject*
876newDBCursorObject(DBC* dbc, DBObject* db)
877{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000878 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879 if (self == NULL)
880 return NULL;
881
882 self->dbc = dbc;
883 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000884 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 Py_INCREF(self->mydb);
886 return self;
887}
888
889
890static void
891DBCursor_dealloc(DBCursorObject* self)
892{
893 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000894
Gregory P. Smitha703a212003-11-03 01:04:41 +0000895 if (self->in_weakreflist != NULL) {
896 PyObject_ClearWeakRefs((PyObject *) self);
897 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899 if (self->dbc != NULL) {
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000900 /* If the underlying database has been closed, we don't
901 need to do anything. If the environment has been closed
902 we need to leak, as BerkeleyDB will crash trying to access
903 the environment. There was an exception when the
904 user closed the environment even though there still was
905 a database open. */
906 if (self->mydb->db && self->mydb->myenvobj &&
907 !self->mydb->myenvobj->closed)
Christian Heimes292d3512008-02-03 16:51:08 +0000908 /* test for: open db + no environment or non-closed environment */
909 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed))) {
911 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000912 err = self->dbc->c_close(self->dbc);
Christian Heimes292d3512008-02-03 16:51:08 +0000913 MYDB_END_ALLOW_THREADS;
914 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 }
917 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919}
920
921
922static DBEnvObject*
923newDBEnvObject(int flags)
924{
925 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000926 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927 if (self == NULL)
928 return NULL;
929
930 self->closed = 1;
931 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000932 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
933 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000934 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000940 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 self = NULL;
942 }
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
945 }
946 return self;
947}
948
949
950static void
951DBEnv_dealloc(DBEnvObject* self)
952{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953 if (self->in_weakreflist != NULL) {
954 PyObject_ClearWeakRefs((PyObject *) self);
955 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000956
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000957 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 MYDB_BEGIN_ALLOW_THREADS;
959 self->db_env->close(self->db_env, 0);
960 MYDB_END_ALLOW_THREADS;
961 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000963}
964
965
966static DBTxnObject*
967newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
968{
969 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000970 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971 if (self == NULL)
972 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000973 Py_INCREF(myenv);
974 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000975 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976
977 MYDB_BEGIN_ALLOW_THREADS;
978#if (DBVER >= 40)
979 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
980#else
981 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
982#endif
983 MYDB_END_ALLOW_THREADS;
984 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000985 Py_DECREF(self->env);
986 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000987 self = NULL;
988 }
989 return self;
990}
991
992
993static void
994DBTxn_dealloc(DBTxnObject* self)
995{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000996 if (self->in_weakreflist != NULL) {
997 PyObject_ClearWeakRefs((PyObject *) self);
998 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999
Gregory P. Smith31c50652004-06-28 01:20:40 +00001000 if (self->txn) {
1001 /* it hasn't been finalized, abort it! */
1002 MYDB_BEGIN_ALLOW_THREADS;
1003#if (DBVER >= 40)
1004 self->txn->abort(self->txn);
1005#else
1006 txn_abort(self->txn);
1007#endif
1008 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001009 PyErr_WarnEx(PyExc_RuntimeWarning,
1010 "DBTxn aborted in destructor. "
1011 " No prior commit() or abort().",
1012 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001013 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014
Neal Norwitz62a21122006-01-25 05:21:55 +00001015 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001016 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017}
1018
1019
1020static DBLockObject*
1021newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1022 db_lockmode_t lock_mode, int flags)
1023{
1024 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001025 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 if (self == NULL)
1027 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001028 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029
1030 MYDB_BEGIN_ALLOW_THREADS;
1031#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001032 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1033 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001034#else
1035 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1036#endif
1037 MYDB_END_ALLOW_THREADS;
1038 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001039 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040 self = NULL;
1041 }
1042
1043 return self;
1044}
1045
1046
1047static void
1048DBLock_dealloc(DBLockObject* self)
1049{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001050 if (self->in_weakreflist != NULL) {
1051 PyObject_ClearWeakRefs((PyObject *) self);
1052 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001053 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001054
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056}
1057
1058
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001059#if (DBVER >= 43)
1060static DBSequenceObject*
1061newDBSequenceObject(DBObject* mydb, int flags)
1062{
1063 int err;
1064 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1065 if (self == NULL)
1066 return NULL;
1067 Py_INCREF(mydb);
1068 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001069 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001070
1071
1072 MYDB_BEGIN_ALLOW_THREADS;
1073 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1074 MYDB_END_ALLOW_THREADS;
1075 if (makeDBError(err)) {
1076 Py_DECREF(self->mydb);
1077 PyObject_Del(self);
1078 self = NULL;
1079 }
1080
1081 return self;
1082}
1083
1084
1085static void
1086DBSequence_dealloc(DBSequenceObject* self)
1087{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001088 if (self->in_weakreflist != NULL) {
1089 PyObject_ClearWeakRefs((PyObject *) self);
1090 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001091
1092 Py_DECREF(self->mydb);
1093 PyObject_Del(self);
1094}
1095#endif
1096
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001097/* --------------------------------------------------------------------- */
1098/* DB methods */
1099
1100static PyObject*
1101DB_append(DBObject* self, PyObject* args)
1102{
1103 PyObject* txnobj = NULL;
1104 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001105 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106 db_recno_t recno;
1107 DBT key, data;
1108 DB_TXN *txn = NULL;
1109
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001110 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111 return NULL;
1112
1113 CHECK_DB_NOT_CLOSED(self);
1114
1115 /* make a dummy key out of a recno */
1116 recno = 0;
1117 CLEAR_DBT(key);
1118 key.data = &recno;
1119 key.size = sizeof(recno);
1120 key.ulen = key.size;
1121 key.flags = DB_DBT_USERMEM;
1122
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001123 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001124 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001126 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1127 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001129 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001131 free_buf_view(dataobj, data_buf_view);
Christian Heimes217cfd12007-12-02 14:31:20 +00001132 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133}
1134
1135
1136#if (DBVER >= 33)
1137
1138static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001139_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1140 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001141{
1142 int retval = DB_DONOTINDEX;
1143 DBObject* secondaryDB = (DBObject*)db->app_private;
1144 PyObject* callback = secondaryDB->associateCallback;
1145 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001147 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001148
1149
1150 if (callback != NULL) {
1151 MYDB_BEGIN_BLOCK_THREADS;
1152
Thomas Woutersb3153832006-03-08 01:47:19 +00001153 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001154 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001155 priData->data, priData->size);
1156 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001157 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001158 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001159 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001160 result = PyEval_CallObject(callback, args);
1161 }
1162 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001163 PyErr_Print();
1164 }
1165 else if (result == Py_None) {
1166 retval = DB_DONOTINDEX;
1167 }
Christian Heimes217cfd12007-12-02 14:31:20 +00001168 else if (PyLong_Check(result)) {
1169 retval = PyLong_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 }
Christian Heimes72b710a2008-05-26 13:28:38 +00001171 else if (PyByteArray_Check(result) || PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001173 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174
1175 CLEAR_DBT(*secKey);
Christian Heimes90aa7642007-12-19 02:45:37 +00001176 size = Py_SIZE(result);
Christian Heimes9c4756e2008-05-26 13:22:05 +00001177 if (PyByteArray_Check(result))
1178 data = PyByteArray_AS_STRING(result);
Guido van Rossum98297ee2007-11-06 21:34:58 +00001179 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001180 data = PyBytes_AS_STRING(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1182 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001183 if (secKey->data) {
1184 memcpy(secKey->data, data, size);
1185 secKey->size = size;
1186 retval = 0;
1187 }
1188 else {
1189 PyErr_SetString(PyExc_MemoryError,
1190 "malloc failed in _db_associateCallback");
1191 PyErr_Print();
1192 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001193 }
1194 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001195 PyErr_SetString(
1196 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001197 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198 PyErr_Print();
1199 }
1200
Thomas Woutersb3153832006-03-08 01:47:19 +00001201 Py_XDECREF(args);
1202 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203
1204 MYDB_END_BLOCK_THREADS;
1205 }
1206 return retval;
1207}
1208
1209
1210static PyObject*
1211DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1212{
1213 int err, flags=0;
1214 DBObject* secondaryDB;
1215 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001216#if (DBVER >= 41)
1217 PyObject *txnobj = NULL;
1218 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001219 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001220 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001221#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001222 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001223#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001224
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225#if (DBVER >= 41)
1226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1227 &secondaryDB, &callback, &flags,
1228 &txnobj)) {
1229#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001231 &secondaryDB, &callback, &flags)) {
1232#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001234 }
1235
1236#if (DBVER >= 41)
1237 if (!checkTxnObj(txnobj, &txn)) return NULL;
1238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001239
1240 CHECK_DB_NOT_CLOSED(self);
1241 if (!DBObject_Check(secondaryDB)) {
1242 makeTypeError("DB", (PyObject*)secondaryDB);
1243 return NULL;
1244 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001245 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001246 if (callback == Py_None) {
1247 callback = NULL;
1248 }
1249 else if (!PyCallable_Check(callback)) {
1250 makeTypeError("Callable", callback);
1251 return NULL;
1252 }
1253
1254 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001255 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001256 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001257 secondaryDB->associateCallback = callback;
1258 secondaryDB->primaryDBType = _DB_get_type(self);
1259
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001260 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1261 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1262 * The global interepreter lock is not initialized until the first
1263 * thread is created using thread.start_new_thread() or fork() is
1264 * called. that would cause the ALLOW_THREADS here to segfault due
1265 * to a null pointer reference if no threads or child processes
1266 * have been created. This works around that and is a no-op if
1267 * threads have already been initialized.
1268 * (see pybsddb-users mailing list post on 2002-08-07)
1269 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001270#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001271 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001272#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001273 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001274#if (DBVER >= 41)
1275 err = self->db->associate(self->db,
1276 txn,
1277 secondaryDB->db,
1278 _db_associateCallback,
1279 flags);
1280#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001281 err = self->db->associate(self->db,
1282 secondaryDB->db,
1283 _db_associateCallback,
1284 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001285#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001286 MYDB_END_ALLOW_THREADS;
1287
1288 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001289 Py_XDECREF(secondaryDB->associateCallback);
1290 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291 secondaryDB->primaryDBType = 0;
1292 }
1293
1294 RETURN_IF_ERR();
1295 RETURN_NONE();
1296}
1297
1298
1299#endif
1300
1301
1302static PyObject*
1303DB_close(DBObject* self, PyObject* args)
1304{
1305 int err, flags=0;
1306 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1307 return NULL;
1308 if (self->db != NULL) {
1309 if (self->myenvobj)
1310 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 self->db = NULL;
1313 RETURN_IF_ERR();
1314 }
1315 RETURN_NONE();
1316}
1317
1318
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319static PyObject*
1320_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1321{
1322 int err, flags=0, type;
1323 PyObject* txnobj = NULL;
1324 PyObject* retval = NULL;
1325 DBT key, data;
1326 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001327 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001328
1329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1330 &txnobj, &flags))
1331 return NULL;
1332
1333 CHECK_DB_NOT_CLOSED(self);
1334 type = _DB_get_type(self);
1335 if (type == -1)
1336 return NULL;
1337 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001338 PyErr_SetString(PyExc_TypeError,
1339 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 return NULL;
1341 }
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1344
1345 CLEAR_DBT(key);
1346 CLEAR_DBT(data);
1347 if (CHECK_DBFLAG(self, DB_THREAD)) {
1348 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1349 data.flags = DB_DBT_MALLOC;
1350 key.flags = DB_DBT_MALLOC;
1351 }
1352
1353 MYDB_BEGIN_ALLOW_THREADS;
1354 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1355 MYDB_END_ALLOW_THREADS;
1356
Gregory P. Smithe9477062005-06-04 06:46:59 +00001357 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1358 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001359 err = 0;
1360 Py_INCREF(Py_None);
1361 retval = Py_None;
1362 }
1363 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001364 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001365 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001366 free_dbt(&key);
1367 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368 }
1369
1370 RETURN_IF_ERR();
1371 return retval;
1372}
1373
1374static PyObject*
1375DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1376{
1377 return _DB_consume(self, args, kwargs, DB_CONSUME);
1378}
1379
1380static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001381DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1382 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001383{
1384 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1385}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386
1387
1388static PyObject*
1389DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1390{
1391 int err, flags=0;
1392 DBC* dbc;
1393 PyObject* txnobj = NULL;
1394 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001395 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001396
1397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1398 &txnobj, &flags))
1399 return NULL;
1400 CHECK_DB_NOT_CLOSED(self);
1401 if (!checkTxnObj(txnobj, &txn))
1402 return NULL;
1403
1404 MYDB_BEGIN_ALLOW_THREADS;
1405 err = self->db->cursor(self->db, txn, &dbc, flags);
1406 MYDB_END_ALLOW_THREADS;
1407 RETURN_IF_ERR();
1408 return (PyObject*) newDBCursorObject(dbc, self);
1409}
1410
1411
1412static PyObject*
1413DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1414{
1415 PyObject* txnobj = NULL;
1416 int flags = 0;
1417 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001418 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 DBT key;
1420 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001421 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422
1423 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1424 &keyobj, &txnobj, &flags))
1425 return NULL;
1426 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001427 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001429 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001430 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001432 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001433
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001434 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001435 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001437 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438
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_NONE();
1441}
1442
1443
1444static PyObject*
1445DB_fd(DBObject* self, PyObject* args)
1446{
1447 int err, the_fd;
1448
1449 if (!PyArg_ParseTuple(args,":fd"))
1450 return NULL;
1451 CHECK_DB_NOT_CLOSED(self);
1452
1453 MYDB_BEGIN_ALLOW_THREADS;
1454 err = self->db->fd(self->db, &the_fd);
1455 MYDB_END_ALLOW_THREADS;
1456 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00001457 return PyLong_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001458}
1459
1460
1461static PyObject*
1462DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1463{
1464 int err, flags=0;
1465 PyObject* txnobj = NULL;
1466 PyObject* keyobj;
1467 PyObject* dfltobj = NULL;
1468 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001469 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001470 int dlen = -1;
1471 int doff = -1;
1472 DBT key, data;
1473 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001474 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001475 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476
1477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001478 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1479 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001480 return NULL;
1481
1482 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001483 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001485 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001486 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001488 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489
1490 CLEAR_DBT(data);
1491 if (CHECK_DBFLAG(self, DB_THREAD)) {
1492 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1493 data.flags = DB_DBT_MALLOC;
1494 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001495 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001496 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001497 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001499
1500 MYDB_BEGIN_ALLOW_THREADS;
1501 err = self->db->get(self->db, txn, &key, &data, flags);
1502 MYDB_END_ALLOW_THREADS;
1503
Gregory P. Smithe9477062005-06-04 06:46:59 +00001504 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505 err = 0;
1506 Py_INCREF(dfltobj);
1507 retval = dfltobj;
1508 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001509 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1510 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 err = 0;
1512 Py_INCREF(Py_None);
1513 retval = Py_None;
1514 }
1515 else if (!err) {
1516 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001517 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001518 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001519 else /* return just the data */
Christian Heimes72b710a2008-05-26 13:28:38 +00001520 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001521 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001523 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524
1525 RETURN_IF_ERR();
1526 return retval;
1527}
1528
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001529#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001530static PyObject*
1531DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1532{
1533 int err, flags=0;
1534 PyObject* txnobj = NULL;
1535 PyObject* keyobj;
1536 PyObject* dfltobj = NULL;
1537 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001538 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001539 int dlen = -1;
1540 int doff = -1;
1541 DBT key, pkey, data;
1542 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001543 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001544 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001545
1546 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1547 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1548 &doff))
1549 return NULL;
1550
1551 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001552 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001553 return NULL;
1554 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001555 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001556 return NULL;
1557 }
1558
1559 CLEAR_DBT(data);
1560 if (CHECK_DBFLAG(self, DB_THREAD)) {
1561 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1562 data.flags = DB_DBT_MALLOC;
1563 }
1564 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001565 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001566 return NULL;
1567 }
1568
1569 CLEAR_DBT(pkey);
1570 pkey.flags = DB_DBT_MALLOC;
1571
1572 MYDB_BEGIN_ALLOW_THREADS;
1573 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1574 MYDB_END_ALLOW_THREADS;
1575
Gregory P. Smithe9477062005-06-04 06:46:59 +00001576 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001577 err = 0;
1578 Py_INCREF(dfltobj);
1579 retval = dfltobj;
1580 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001581 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1582 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001583 err = 0;
1584 Py_INCREF(Py_None);
1585 retval = Py_None;
1586 }
1587 else if (!err) {
1588 PyObject *pkeyObj;
1589 PyObject *dataObj;
Christian Heimes72b710a2008-05-26 13:28:38 +00001590 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001591
1592 if (self->primaryDBType == DB_RECNO ||
1593 self->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001594 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001595 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001596 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001597
1598 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1599 {
1600 PyObject *keyObj;
1601 int type = _DB_get_type(self);
1602 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001603 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001604 else
Christian Heimes72b710a2008-05-26 13:28:38 +00001605 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001606#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001607 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001608#else
1609 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1610#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001611 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001612 }
1613 else /* return just the pkey and data */
1614 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001615#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001616 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001617#else
1618 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1619#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001620 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001621 Py_DECREF(dataObj);
1622 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001623 free_dbt(&pkey);
1624 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001625 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001626 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001627
1628 RETURN_IF_ERR();
1629 return retval;
1630}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001631#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001632
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001633
1634/* Return size of entry */
1635static PyObject*
1636DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1637{
1638 int err, flags=0;
1639 PyObject* txnobj = NULL;
1640 PyObject* keyobj;
1641 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001642 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643 DBT key, data;
1644 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001645 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001646
1647 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1648 &keyobj, &txnobj))
1649 return NULL;
1650 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001651 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001653 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001654 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001656 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 CLEAR_DBT(data);
1658
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001659 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1660 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 data.flags = DB_DBT_USERMEM;
1662 data.ulen = 0;
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->get(self->db, txn, &key, &data, flags);
1665 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001666 if (err == DB_BUFFER_SMALL) {
Christian Heimes217cfd12007-12-02 14:31:20 +00001667 retval = PyLong_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668 err = 0;
1669 }
1670
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001671 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1672 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001673 RETURN_IF_ERR();
1674 return retval;
1675}
1676
1677
1678static PyObject*
1679DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1680{
1681 int err, flags=0;
1682 PyObject* txnobj = NULL;
1683 PyObject* keyobj;
1684 PyObject* dataobj;
1685 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001686 Py_buffer* data_buf_view = NULL;
1687 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001688 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001689 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001690 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001691 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692
1693
1694 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1695 &keyobj, &dataobj, &txnobj, &flags))
1696 return NULL;
1697
1698 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001699 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001701 if ( !checkTxnObj(txnobj, &txn) ||
1702 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001703 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001704 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001705 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001706 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001707
1708 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001709 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001710
1711 if (CHECK_DBFLAG(self, DB_THREAD)) {
1712 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001713 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715 }
1716
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1720
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001721 free_buf_view(dataobj, data_buf_view);
1722
Gregory P. Smithe9477062005-06-04 06:46:59 +00001723 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1724 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001725 err = 0;
1726 Py_INCREF(Py_None);
1727 retval = Py_None;
1728 }
1729 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001730 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001731 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001732 /* XXX(guido) But what if the input is PyString? */
Christian Heimes72b710a2008-05-26 13:28:38 +00001733 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001734
1735 /* Even though the flags require DB_DBT_MALLOC, data is not always
1736 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1737 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001738 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001739 }
1740
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001741 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 RETURN_IF_ERR();
1743 return retval;
1744}
1745
1746
1747static PyObject*
1748DB_get_byteswapped(DBObject* self, PyObject* args)
1749{
1750#if (DBVER >= 33)
1751 int err = 0;
1752#endif
1753 int retval = -1;
1754
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1758
1759#if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764#else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768#endif
Christian Heimes217cfd12007-12-02 14:31:20 +00001769 return PyLong_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001770}
1771
1772
1773static PyObject*
1774DB_get_type(DBObject* self, PyObject* args)
1775{
1776 int type;
1777
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001782 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001783 if (type == -1)
1784 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00001785 return PyLong_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786}
1787
1788
1789static PyObject*
1790DB_join(DBObject* self, PyObject* args)
1791{
1792 int err, flags=0;
1793 int length, x;
1794 PyObject* cursorsObj;
1795 DBC** cursors;
1796 DBC* dbc;
1797
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001798 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1799 return NULL;
1800
1801 CHECK_DB_NOT_CLOSED(self);
1802
1803 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001804 PyErr_SetString(PyExc_TypeError,
1805 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001806 return NULL;
1807 }
1808
1809 length = PyObject_Length(cursorsObj);
1810 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001811 if (!cursors) {
1812 PyErr_NoMemory();
1813 return NULL;
1814 }
1815
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 cursors[length] = NULL;
1817 for (x=0; x<length; x++) {
1818 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001819 if (item == NULL) {
1820 free(cursors);
1821 return NULL;
1822 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001823 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001824 PyErr_SetString(PyExc_TypeError,
1825 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001826 free(cursors);
1827 return NULL;
1828 }
1829 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001830 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831 }
1832
1833 MYDB_BEGIN_ALLOW_THREADS;
1834 err = self->db->join(self->db, cursors, &dbc, flags);
1835 MYDB_END_ALLOW_THREADS;
1836 free(cursors);
1837 RETURN_IF_ERR();
1838
Gregory P. Smith7441e652003-11-03 21:35:31 +00001839 /* FIXME: this is a buggy interface. The returned cursor
1840 contains internal references to the passed in cursors
1841 but does not hold python references to them or prevent
1842 them from being closed prematurely. This can cause
1843 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 return (PyObject*) newDBCursorObject(dbc, self);
1845}
1846
1847
1848static PyObject*
1849DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1850{
1851 int err, flags=0;
1852 PyObject* txnobj = NULL;
1853 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001854 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 DBT key;
1856 DB_TXN *txn = NULL;
1857 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001858 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859
1860 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1861 &keyobj, &txnobj, &flags))
1862 return NULL;
1863 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001864 if (!checkTxnObj(txnobj, &txn))
1865 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001866 if (!make_dbt(keyobj, &key, &key_buf_view))
1867 /* BTree only, don't need to allow for an int key */
1868 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001869
1870 MYDB_BEGIN_ALLOW_THREADS;
1871 err = self->db->key_range(self->db, txn, &key, &range, flags);
1872 MYDB_END_ALLOW_THREADS;
1873
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001874 free_buf_view(keyobj, key_buf_view);
1875
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001876 RETURN_IF_ERR();
1877 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1878}
1879
1880
1881static PyObject*
1882DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1883{
1884 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1885 char* filename = NULL;
1886 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001887#if (DBVER >= 41)
1888 PyObject *txnobj = NULL;
1889 DB_TXN *txn = NULL;
1890 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001891 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001892 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1893 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001894 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001895 "filename", "dbtype", "flags", "mode", "txn", NULL};
1896#else
1897 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001898 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001899 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1900 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001901 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001902 "filename", "dbtype", "flags", "mode", NULL};
1903#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001904
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001905#if (DBVER >= 41)
1906 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1907 &filename, &dbname, &type, &flags, &mode,
1908 &txnobj))
1909#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001910 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001911 &filename, &dbname, &type, &flags,
1912 &mode))
1913#endif
1914 {
1915 PyErr_Clear();
1916 type = DB_UNKNOWN; flags = 0; mode = 0660;
1917 filename = NULL; dbname = NULL;
1918#if (DBVER >= 41)
1919 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1920 kwnames_basic,
1921 &filename, &type, &flags, &mode,
1922 &txnobj))
1923 return NULL;
1924#else
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1926 kwnames_basic,
1927 &filename, &type, &flags, &mode))
1928 return NULL;
1929#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 }
1931
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001932#if (DBVER >= 41)
1933 if (!checkTxnObj(txnobj, &txn)) return NULL;
1934#endif
1935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001937 PyObject *t = Py_BuildValue("(is)", 0,
1938 "Cannot call open() twice for DB object");
1939 PyErr_SetObject(DBError, t);
1940 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001941 return NULL;
1942 }
1943
1944 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001945#if (DBVER >= 41)
1946 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1947#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001949#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 MYDB_END_ALLOW_THREADS;
1951 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001952 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001953 self->db = NULL;
1954 return NULL;
1955 }
1956
Guido van Rossum77677112007-11-05 19:43:04 +00001957#if (DBVER >= 42)
1958 self->db->get_flags(self->db, &self->setflags);
1959#endif
1960
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 self->flags = flags;
1962 RETURN_NONE();
1963}
1964
1965
1966static PyObject*
1967DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1968{
1969 int flags=0;
1970 PyObject* txnobj = NULL;
1971 int dlen = -1;
1972 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001973 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001974 Py_buffer *data_buf_view = NULL;
1975 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001976 DBT key, data;
1977 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001978 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001979 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001980
1981 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1982 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1983 return NULL;
1984
1985 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001986 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001987 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001988 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001989 !add_partial_dbt(&data, dlen, doff) ||
1990 !checkTxnObj(txnobj, &txn) )
1991 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001992 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1993 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001994 return NULL;
1995 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001996
1997 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001998 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1999 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000 return NULL;
2001 }
2002
2003 if (flags & DB_APPEND)
Christian Heimes217cfd12007-12-02 14:31:20 +00002004 retval = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002005 else {
2006 retval = Py_None;
2007 Py_INCREF(retval);
2008 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002009 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2010 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 return retval;
2012}
2013
2014
2015
2016static PyObject*
2017DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2018{
2019 char* filename;
2020 char* database = NULL;
2021 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002022 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002023
2024 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2025 &filename, &database, &flags))
2026 return NULL;
2027 CHECK_DB_NOT_CLOSED(self);
2028
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002029 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002030 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002031 RETURN_IF_ERR();
2032 RETURN_NONE();
2033}
2034
2035
2036
2037static PyObject*
2038DB_rename(DBObject* self, PyObject* args)
2039{
2040 char* filename;
2041 char* database;
2042 char* newname;
2043 int err, flags=0;
2044
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002045 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2046 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002047 return NULL;
2048 CHECK_DB_NOT_CLOSED(self);
2049
2050 MYDB_BEGIN_ALLOW_THREADS;
2051 err = self->db->rename(self->db, filename, database, newname, flags);
2052 MYDB_END_ALLOW_THREADS;
2053 RETURN_IF_ERR();
2054 RETURN_NONE();
2055}
2056
2057
2058static PyObject*
2059DB_set_bt_minkey(DBObject* self, PyObject* args)
2060{
2061 int err, minkey;
2062
2063 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2064 return NULL;
2065 CHECK_DB_NOT_CLOSED(self);
2066
2067 MYDB_BEGIN_ALLOW_THREADS;
2068 err = self->db->set_bt_minkey(self->db, minkey);
2069 MYDB_END_ALLOW_THREADS;
2070 RETURN_IF_ERR();
2071 RETURN_NONE();
2072}
2073
Neal Norwitz84562352005-10-20 04:30:15 +00002074#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002075static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002076_default_cmp(const DBT *leftKey,
2077 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002078{
2079 int res;
2080 int lsize = leftKey->size, rsize = rightKey->size;
2081
Georg Brandlef1701f2006-03-07 14:57:48 +00002082 res = memcmp(leftKey->data, rightKey->data,
2083 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002084
2085 if (res == 0) {
2086 if (lsize < rsize) {
2087 res = -1;
2088 }
2089 else if (lsize > rsize) {
2090 res = 1;
2091 }
2092 }
2093 return res;
2094}
2095
2096static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002097_db_compareCallback(DB* db,
2098 const DBT *leftKey,
2099 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002100{
2101 int res = 0;
2102 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002103 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002104 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002105
2106 if (self == NULL || self->btCompareCallback == NULL) {
2107 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 PyErr_SetString(PyExc_TypeError,
2109 (self == 0
2110 ? "DB_bt_compare db is NULL."
2111 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002112 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002113 PyErr_Print();
2114 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002115 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002117 MYDB_BEGIN_BLOCK_THREADS;
2118
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002119 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002120 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002121 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002122 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002123 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002125 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002127 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002128 PyErr_Print();
2129 res = _default_cmp(leftKey, rightKey);
Christian Heimes217cfd12007-12-02 14:31:20 +00002130 } else if (PyLong_Check(result)) {
2131 res = PyLong_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002132 } else {
2133 PyErr_SetString(PyExc_TypeError,
2134 "DB_bt_compare callback MUST return an int.");
2135 /* we're in a callback within the DB code, we can't raise */
2136 PyErr_Print();
2137 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002138 }
2139
Thomas Woutersb3153832006-03-08 01:47:19 +00002140 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002141 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142
2143 MYDB_END_BLOCK_THREADS;
2144 }
2145 return res;
2146}
2147
2148static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002149DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002150{
2151 int err;
2152 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002153 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002154
Georg Brandlef1701f2006-03-07 14:57:48 +00002155 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002156 return NULL;
2157
Georg Brandlef1701f2006-03-07 14:57:48 +00002158 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002159
Georg Brandlef1701f2006-03-07 14:57:48 +00002160 if (!PyCallable_Check(comparator)) {
2161 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162 return NULL;
2163 }
2164
2165 /*
2166 * Perform a test call of the comparator function with two empty
2167 * string objects here. verify that it returns an int (0).
2168 * err if not.
2169 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002170 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002171 result = PyEval_CallObject(comparator, tuple);
2172 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002173 if (result == NULL)
2174 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002175 if (!PyLong_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002176 PyErr_SetString(PyExc_TypeError,
2177 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002179 } else if (PyLong_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002180 PyErr_SetString(PyExc_TypeError,
2181 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002182 return NULL;
2183 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002184 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002185
2186 /* We don't accept multiple set_bt_compare operations, in order to
2187 * simplify the code. This would have no real use, as one cannot
2188 * change the function once the db is opened anyway */
2189 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002190 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002191 return NULL;
2192 }
2193
Georg Brandlef1701f2006-03-07 14:57:48 +00002194 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002195 self->btCompareCallback = comparator;
2196
2197 /* This is to workaround a problem with un-initialized threads (see
2198 comment in DB_associate) */
2199#ifdef WITH_THREAD
2200 PyEval_InitThreads();
2201#endif
2202
Thomas Woutersb3153832006-03-08 01:47:19 +00002203 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204
2205 if (err) {
2206 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002207 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002208 self->btCompareCallback = NULL;
2209 }
2210
Georg Brandlef1701f2006-03-07 14:57:48 +00002211 RETURN_IF_ERR();
2212 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213}
Neal Norwitz84562352005-10-20 04:30:15 +00002214#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002216
2217static PyObject*
2218DB_set_cachesize(DBObject* self, PyObject* args)
2219{
2220 int err;
2221 int gbytes = 0, bytes = 0, ncache = 0;
2222
2223 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2224 &gbytes,&bytes,&ncache))
2225 return NULL;
2226 CHECK_DB_NOT_CLOSED(self);
2227
2228 MYDB_BEGIN_ALLOW_THREADS;
2229 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2230 MYDB_END_ALLOW_THREADS;
2231 RETURN_IF_ERR();
2232 RETURN_NONE();
2233}
2234
2235
2236static PyObject*
2237DB_set_flags(DBObject* self, PyObject* args)
2238{
2239 int err, flags;
2240
2241 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2242 return NULL;
2243 CHECK_DB_NOT_CLOSED(self);
2244
2245 MYDB_BEGIN_ALLOW_THREADS;
2246 err = self->db->set_flags(self->db, flags);
2247 MYDB_END_ALLOW_THREADS;
2248 RETURN_IF_ERR();
2249
2250 self->setflags |= flags;
2251 RETURN_NONE();
2252}
2253
2254
2255static PyObject*
2256DB_set_h_ffactor(DBObject* self, PyObject* args)
2257{
2258 int err, ffactor;
2259
2260 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2261 return NULL;
2262 CHECK_DB_NOT_CLOSED(self);
2263
2264 MYDB_BEGIN_ALLOW_THREADS;
2265 err = self->db->set_h_ffactor(self->db, ffactor);
2266 MYDB_END_ALLOW_THREADS;
2267 RETURN_IF_ERR();
2268 RETURN_NONE();
2269}
2270
2271
2272static PyObject*
2273DB_set_h_nelem(DBObject* self, PyObject* args)
2274{
2275 int err, nelem;
2276
2277 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2278 return NULL;
2279 CHECK_DB_NOT_CLOSED(self);
2280
2281 MYDB_BEGIN_ALLOW_THREADS;
2282 err = self->db->set_h_nelem(self->db, nelem);
2283 MYDB_END_ALLOW_THREADS;
2284 RETURN_IF_ERR();
2285 RETURN_NONE();
2286}
2287
2288
2289static PyObject*
2290DB_set_lorder(DBObject* self, PyObject* args)
2291{
2292 int err, lorder;
2293
2294 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2295 return NULL;
2296 CHECK_DB_NOT_CLOSED(self);
2297
2298 MYDB_BEGIN_ALLOW_THREADS;
2299 err = self->db->set_lorder(self->db, lorder);
2300 MYDB_END_ALLOW_THREADS;
2301 RETURN_IF_ERR();
2302 RETURN_NONE();
2303}
2304
2305
2306static PyObject*
2307DB_set_pagesize(DBObject* self, PyObject* args)
2308{
2309 int err, pagesize;
2310
2311 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2312 return NULL;
2313 CHECK_DB_NOT_CLOSED(self);
2314
2315 MYDB_BEGIN_ALLOW_THREADS;
2316 err = self->db->set_pagesize(self->db, pagesize);
2317 MYDB_END_ALLOW_THREADS;
2318 RETURN_IF_ERR();
2319 RETURN_NONE();
2320}
2321
2322
2323static PyObject*
2324DB_set_re_delim(DBObject* self, PyObject* args)
2325{
2326 int err;
2327 char delim;
2328
2329 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2330 PyErr_Clear();
2331 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2332 return NULL;
2333 }
2334
2335 CHECK_DB_NOT_CLOSED(self);
2336
2337 MYDB_BEGIN_ALLOW_THREADS;
2338 err = self->db->set_re_delim(self->db, delim);
2339 MYDB_END_ALLOW_THREADS;
2340 RETURN_IF_ERR();
2341 RETURN_NONE();
2342}
2343
2344static PyObject*
2345DB_set_re_len(DBObject* self, PyObject* args)
2346{
2347 int err, len;
2348
2349 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2350 return NULL;
2351 CHECK_DB_NOT_CLOSED(self);
2352
2353 MYDB_BEGIN_ALLOW_THREADS;
2354 err = self->db->set_re_len(self->db, len);
2355 MYDB_END_ALLOW_THREADS;
2356 RETURN_IF_ERR();
2357 RETURN_NONE();
2358}
2359
2360
2361static PyObject*
2362DB_set_re_pad(DBObject* self, PyObject* args)
2363{
2364 int err;
2365 char pad;
2366
2367 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2368 PyErr_Clear();
2369 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2370 return NULL;
2371 }
2372 CHECK_DB_NOT_CLOSED(self);
2373
2374 MYDB_BEGIN_ALLOW_THREADS;
2375 err = self->db->set_re_pad(self->db, pad);
2376 MYDB_END_ALLOW_THREADS;
2377 RETURN_IF_ERR();
2378 RETURN_NONE();
2379}
2380
2381
2382static PyObject*
2383DB_set_re_source(DBObject* self, PyObject* args)
2384{
2385 int err;
2386 char *re_source;
2387
2388 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2389 return NULL;
2390 CHECK_DB_NOT_CLOSED(self);
2391
2392 MYDB_BEGIN_ALLOW_THREADS;
2393 err = self->db->set_re_source(self->db, re_source);
2394 MYDB_END_ALLOW_THREADS;
2395 RETURN_IF_ERR();
2396 RETURN_NONE();
2397}
2398
2399
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002400static PyObject*
2401DB_set_q_extentsize(DBObject* self, PyObject* args)
2402{
2403 int err;
2404 int extentsize;
2405
2406 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2407 return NULL;
2408 CHECK_DB_NOT_CLOSED(self);
2409
2410 MYDB_BEGIN_ALLOW_THREADS;
2411 err = self->db->set_q_extentsize(self->db, extentsize);
2412 MYDB_END_ALLOW_THREADS;
2413 RETURN_IF_ERR();
2414 RETURN_NONE();
2415}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002416
2417static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002418DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002419{
2420 int err, flags = 0, type;
2421 void* sp;
2422 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002423#if (DBVER >= 43)
2424 PyObject* txnobj = NULL;
2425 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002426 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002427#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002428 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002429#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002430
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002431#if (DBVER >= 43)
2432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2433 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002434 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002435 if (!checkTxnObj(txnobj, &txn))
2436 return NULL;
2437#else
2438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2439 return NULL;
2440#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441 CHECK_DB_NOT_CLOSED(self);
2442
2443 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002444#if (DBVER >= 43)
2445 err = self->db->stat(self->db, txn, &sp, flags);
2446#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002447 err = self->db->stat(self->db, &sp, flags);
2448#else
2449 err = self->db->stat(self->db, &sp, NULL, flags);
2450#endif
2451 MYDB_END_ALLOW_THREADS;
2452 RETURN_IF_ERR();
2453
2454 self->haveStat = 1;
2455
2456 /* Turn the stat structure into a dictionary */
2457 type = _DB_get_type(self);
2458 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2459 free(sp);
2460 return NULL;
2461 }
2462
2463#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2464#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2465#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2466
2467 switch (type) {
2468 case DB_HASH:
2469 MAKE_HASH_ENTRY(magic);
2470 MAKE_HASH_ENTRY(version);
2471 MAKE_HASH_ENTRY(nkeys);
2472 MAKE_HASH_ENTRY(ndata);
2473 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002474#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002475 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002476#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002477 MAKE_HASH_ENTRY(ffactor);
2478 MAKE_HASH_ENTRY(buckets);
2479 MAKE_HASH_ENTRY(free);
2480 MAKE_HASH_ENTRY(bfree);
2481 MAKE_HASH_ENTRY(bigpages);
2482 MAKE_HASH_ENTRY(big_bfree);
2483 MAKE_HASH_ENTRY(overflows);
2484 MAKE_HASH_ENTRY(ovfl_free);
2485 MAKE_HASH_ENTRY(dup);
2486 MAKE_HASH_ENTRY(dup_free);
2487 break;
2488
2489 case DB_BTREE:
2490 case DB_RECNO:
2491 MAKE_BT_ENTRY(magic);
2492 MAKE_BT_ENTRY(version);
2493 MAKE_BT_ENTRY(nkeys);
2494 MAKE_BT_ENTRY(ndata);
2495 MAKE_BT_ENTRY(pagesize);
2496 MAKE_BT_ENTRY(minkey);
2497 MAKE_BT_ENTRY(re_len);
2498 MAKE_BT_ENTRY(re_pad);
2499 MAKE_BT_ENTRY(levels);
2500 MAKE_BT_ENTRY(int_pg);
2501 MAKE_BT_ENTRY(leaf_pg);
2502 MAKE_BT_ENTRY(dup_pg);
2503 MAKE_BT_ENTRY(over_pg);
2504 MAKE_BT_ENTRY(free);
2505 MAKE_BT_ENTRY(int_pgfree);
2506 MAKE_BT_ENTRY(leaf_pgfree);
2507 MAKE_BT_ENTRY(dup_pgfree);
2508 MAKE_BT_ENTRY(over_pgfree);
2509 break;
2510
2511 case DB_QUEUE:
2512 MAKE_QUEUE_ENTRY(magic);
2513 MAKE_QUEUE_ENTRY(version);
2514 MAKE_QUEUE_ENTRY(nkeys);
2515 MAKE_QUEUE_ENTRY(ndata);
2516 MAKE_QUEUE_ENTRY(pagesize);
2517 MAKE_QUEUE_ENTRY(pages);
2518 MAKE_QUEUE_ENTRY(re_len);
2519 MAKE_QUEUE_ENTRY(re_pad);
2520 MAKE_QUEUE_ENTRY(pgfree);
2521#if (DBVER == 31)
2522 MAKE_QUEUE_ENTRY(start);
2523#endif
2524 MAKE_QUEUE_ENTRY(first_recno);
2525 MAKE_QUEUE_ENTRY(cur_recno);
2526 break;
2527
2528 default:
2529 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2530 Py_DECREF(d);
2531 d = NULL;
2532 }
2533
2534#undef MAKE_HASH_ENTRY
2535#undef MAKE_BT_ENTRY
2536#undef MAKE_QUEUE_ENTRY
2537
2538 free(sp);
2539 return d;
2540}
2541
2542static PyObject*
2543DB_sync(DBObject* self, PyObject* args)
2544{
2545 int err;
2546 int flags = 0;
2547
2548 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2549 return NULL;
2550 CHECK_DB_NOT_CLOSED(self);
2551
2552 MYDB_BEGIN_ALLOW_THREADS;
2553 err = self->db->sync(self->db, flags);
2554 MYDB_END_ALLOW_THREADS;
2555 RETURN_IF_ERR();
2556 RETURN_NONE();
2557}
2558
2559
2560#if (DBVER >= 33)
2561static PyObject*
2562DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2563{
2564 int err, flags=0;
2565 u_int32_t count=0;
2566 PyObject* txnobj = NULL;
2567 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002568 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002569
2570 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2571 &txnobj, &flags))
2572 return NULL;
2573 CHECK_DB_NOT_CLOSED(self);
2574 if (!checkTxnObj(txnobj, &txn))
2575 return NULL;
2576
2577 MYDB_BEGIN_ALLOW_THREADS;
2578 err = self->db->truncate(self->db, txn, &count, flags);
2579 MYDB_END_ALLOW_THREADS;
2580 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00002581 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002582}
2583#endif
2584
2585
2586static PyObject*
2587DB_upgrade(DBObject* self, PyObject* args)
2588{
2589 int err, flags=0;
2590 char *filename;
2591
2592 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2593 return NULL;
2594 CHECK_DB_NOT_CLOSED(self);
2595
2596 MYDB_BEGIN_ALLOW_THREADS;
2597 err = self->db->upgrade(self->db, filename, flags);
2598 MYDB_END_ALLOW_THREADS;
2599 RETURN_IF_ERR();
2600 RETURN_NONE();
2601}
2602
2603
2604static PyObject*
2605DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2606{
2607 int err, flags=0;
2608 char* fileName;
2609 char* dbName=NULL;
2610 char* outFileName=NULL;
2611 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002612 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002613 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002614
2615 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2616 &fileName, &dbName, &outFileName, &flags))
2617 return NULL;
2618
2619 CHECK_DB_NOT_CLOSED(self);
2620 if (outFileName)
2621 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002622 /* XXX(nnorwitz): it should probably be an exception if outFile
2623 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002624
2625 MYDB_BEGIN_ALLOW_THREADS;
2626 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2627 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002628 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002630
2631 /* DB.verify acts as a DB handle destructor (like close); this was
2632 * documented in BerkeleyDB 4.2 but had the undocumented effect
2633 * of not being safe in prior versions while still requiring an explicit
2634 * DB.close call afterwards. Lets call close for the user to emulate
2635 * the safe 4.2 behaviour. */
2636#if (DBVER <= 41)
2637 self->db->close(self->db, 0);
2638#endif
2639 self->db = NULL;
2640
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002641 RETURN_IF_ERR();
2642 RETURN_NONE();
2643}
2644
2645
2646static PyObject*
2647DB_set_get_returns_none(DBObject* self, PyObject* args)
2648{
2649 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002650 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651
2652 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2653 return NULL;
2654 CHECK_DB_NOT_CLOSED(self);
2655
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002656 if (self->moduleFlags.getReturnsNone)
2657 ++oldValue;
2658 if (self->moduleFlags.cursorSetReturnsNone)
2659 ++oldValue;
2660 self->moduleFlags.getReturnsNone = (flags >= 1);
2661 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00002662 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002663}
2664
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002665#if (DBVER >= 41)
2666static PyObject*
2667DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2668{
2669 int err;
2670 u_int32_t flags=0;
2671 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002672 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002673
2674 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2675 &passwd, &flags)) {
2676 return NULL;
2677 }
2678
2679 MYDB_BEGIN_ALLOW_THREADS;
2680 err = self->db->set_encrypt(self->db, passwd, flags);
2681 MYDB_END_ALLOW_THREADS;
2682
2683 RETURN_IF_ERR();
2684 RETURN_NONE();
2685}
2686#endif /* DBVER >= 41 */
2687
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688
2689/*-------------------------------------------------------------- */
2690/* Mapping and Dictionary-like access routines */
2691
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002692Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002693{
2694 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002695 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 int flags = 0;
2697 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002698 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699
2700 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002701 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2702 PyErr_SetObject(DBError, t);
2703 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704 return -1;
2705 }
2706
2707 if (self->haveStat) { /* Has the stat function been called recently? If
2708 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002709 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710 }
2711
2712 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002713redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002714#if (DBVER >= 43)
2715 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2716#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002717 err = self->db->stat(self->db, &sp, flags);
2718#else
2719 err = self->db->stat(self->db, &sp, NULL, flags);
2720#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002721
2722 /* All the stat structures have matching fields upto the ndata field,
2723 so we can use any of them for the type cast */
2724 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2725
2726 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2727 * redo a full stat to make sure.
2728 * Fixes SF python bug 1493322, pybsddb bug 1184012
2729 */
2730 if (size == 0 && (flags & DB_FAST_STAT)) {
2731 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002732 if (!err)
2733 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002734 goto redo_stat_for_length;
2735 }
2736
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 MYDB_END_ALLOW_THREADS;
2738
2739 if (err)
2740 return -1;
2741
2742 self->haveStat = 1;
2743
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002744 free(sp);
2745 return size;
2746}
2747
2748
2749PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2750{
2751 int err;
2752 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002753 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754 DBT key;
2755 DBT data;
2756
2757 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002758 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002759 return NULL;
2760
2761 CLEAR_DBT(data);
2762 if (CHECK_DBFLAG(self, DB_THREAD)) {
2763 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2764 data.flags = DB_DBT_MALLOC;
2765 }
2766 MYDB_BEGIN_ALLOW_THREADS;
2767 err = self->db->get(self->db, NULL, &key, &data, 0);
2768 MYDB_END_ALLOW_THREADS;
2769 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2770 PyErr_SetObject(PyExc_KeyError, keyobj);
2771 retval = NULL;
2772 }
2773 else if (makeDBError(err)) {
2774 retval = NULL;
2775 }
2776 else {
Christian Heimes72b710a2008-05-26 13:28:38 +00002777 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002778 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002779 }
2780
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002781 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002782 return retval;
2783}
2784
2785
2786static int
2787DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2788{
2789 DBT key, data;
2790 int retval;
2791 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002792 Py_buffer *data_buf_view = NULL;
2793 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002794
2795 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002796 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2797 PyErr_SetObject(DBError, t);
2798 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 return -1;
2800 }
2801
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002802 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 return -1;
2804
2805 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002806 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002807 retval = -1;
2808 else {
2809 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002810 /* dictionaries shouldn't have duplicate keys */
2811 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002812 retval = _DB_put(self, NULL, &key, &data, flags);
2813
2814 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002815 /* try deleting any old record that matches and then PUT it
2816 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002817 _DB_delete(self, NULL, &key, 0);
2818 PyErr_Clear();
2819 retval = _DB_put(self, NULL, &key, &data, flags);
2820 }
2821 }
2822 }
2823 else {
2824 /* dataobj == NULL, so delete the key */
2825 retval = _DB_delete(self, NULL, &key, 0);
2826 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002827 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2828 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002829 return retval;
2830}
2831
2832
2833static PyObject*
2834DB_has_key(DBObject* self, PyObject* args)
2835{
2836 int err;
2837 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002838 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 DBT key, data;
2840 PyObject* txnobj = NULL;
2841 DB_TXN *txn = NULL;
2842
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002843 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002844 return NULL;
2845 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002846 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002848 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002849 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002851 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002852
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002853 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 it has a record but can't allocate a buffer for the data. This saves
2855 having to deal with data we won't be using.
2856 */
2857 CLEAR_DBT(data);
2858 data.flags = DB_DBT_USERMEM;
2859
2860 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002861 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002862 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002863 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002864
2865 if (err == DB_BUFFER_SMALL || err == 0) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002866 return PyLong_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002867 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002868 return PyLong_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002869 }
2870
2871 makeDBError(err);
2872 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873}
2874
2875
2876#define _KEYS_LIST 1
2877#define _VALUES_LIST 2
2878#define _ITEMS_LIST 3
2879
2880static PyObject*
2881_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2882{
2883 int err, dbtype;
2884 DBT key;
2885 DBT data;
2886 DBC *cursor;
2887 PyObject* list;
2888 PyObject* item = NULL;
2889
2890 CHECK_DB_NOT_CLOSED(self);
2891 CLEAR_DBT(key);
2892 CLEAR_DBT(data);
2893
2894 dbtype = _DB_get_type(self);
2895 if (dbtype == -1)
2896 return NULL;
2897
2898 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002899 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002900 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002901
2902 /* get a cursor */
2903 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002904 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002906 if (makeDBError(err)) {
2907 Py_DECREF(list);
2908 return NULL;
2909 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910
2911 if (CHECK_DBFLAG(self, DB_THREAD)) {
2912 key.flags = DB_DBT_REALLOC;
2913 data.flags = DB_DBT_REALLOC;
2914 }
2915
2916 while (1) { /* use the cursor to traverse the DB, collecting items */
2917 MYDB_BEGIN_ALLOW_THREADS;
2918 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2919 MYDB_END_ALLOW_THREADS;
2920
2921 if (err) {
2922 /* for any error, break out of the loop */
2923 break;
2924 }
2925
2926 switch (type) {
2927 case _KEYS_LIST:
2928 switch(dbtype) {
2929 case DB_BTREE:
2930 case DB_HASH:
2931 default:
Christian Heimes72b710a2008-05-26 13:28:38 +00002932 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002933 break;
2934 case DB_RECNO:
2935 case DB_QUEUE:
Christian Heimes217cfd12007-12-02 14:31:20 +00002936 item = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 break;
2938 }
2939 break;
2940
2941 case _VALUES_LIST:
Christian Heimes72b710a2008-05-26 13:28:38 +00002942 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002943 break;
2944
2945 case _ITEMS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002950 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002951 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002955 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002956 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002957 break;
2958 }
2959 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002960 default:
2961 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2962 item = NULL;
2963 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002964 }
2965 if (item == NULL) {
2966 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967 list = NULL;
2968 goto done;
2969 }
2970 PyList_Append(list, item);
2971 Py_DECREF(item);
2972 }
2973
Gregory P. Smithe9477062005-06-04 06:46:59 +00002974 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2975 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 Py_DECREF(list);
2977 list = NULL;
2978 }
2979
2980 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002981 free_dbt(&key);
2982 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983 MYDB_BEGIN_ALLOW_THREADS;
2984 cursor->c_close(cursor);
2985 MYDB_END_ALLOW_THREADS;
2986 return list;
2987}
2988
2989
2990static PyObject*
2991DB_keys(DBObject* self, PyObject* args)
2992{
2993 PyObject* txnobj = NULL;
2994 DB_TXN *txn = NULL;
2995
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002996 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002997 return NULL;
2998 if (!checkTxnObj(txnobj, &txn))
2999 return NULL;
3000 return _DB_make_list(self, txn, _KEYS_LIST);
3001}
3002
3003
3004static PyObject*
3005DB_items(DBObject* self, PyObject* args)
3006{
3007 PyObject* txnobj = NULL;
3008 DB_TXN *txn = NULL;
3009
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003010 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003011 return NULL;
3012 if (!checkTxnObj(txnobj, &txn))
3013 return NULL;
3014 return _DB_make_list(self, txn, _ITEMS_LIST);
3015}
3016
3017
3018static PyObject*
3019DB_values(DBObject* self, PyObject* args)
3020{
3021 PyObject* txnobj = NULL;
3022 DB_TXN *txn = NULL;
3023
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003024 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003025 return NULL;
3026 if (!checkTxnObj(txnobj, &txn))
3027 return NULL;
3028 return _DB_make_list(self, txn, _VALUES_LIST);
3029}
3030
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031/* --------------------------------------------------------------------- */
3032/* DBCursor methods */
3033
3034
3035static PyObject*
3036DBC_close(DBCursorObject* self, PyObject* args)
3037{
3038 int err = 0;
3039
3040 if (!PyArg_ParseTuple(args, ":close"))
3041 return NULL;
3042
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003043 if (self->dbc != NULL) {
3044 MYDB_BEGIN_ALLOW_THREADS;
3045 err = self->dbc->c_close(self->dbc);
3046 self->dbc = NULL;
3047 MYDB_END_ALLOW_THREADS;
3048 }
3049 RETURN_IF_ERR();
3050 RETURN_NONE();
3051}
3052
3053
3054static PyObject*
3055DBC_count(DBCursorObject* self, PyObject* args)
3056{
3057 int err = 0;
3058 db_recno_t count;
3059 int flags = 0;
3060
3061 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3062 return NULL;
3063
3064 CHECK_CURSOR_NOT_CLOSED(self);
3065
3066 MYDB_BEGIN_ALLOW_THREADS;
3067 err = self->dbc->c_count(self->dbc, &count, flags);
3068 MYDB_END_ALLOW_THREADS;
3069 RETURN_IF_ERR();
3070
Christian Heimes217cfd12007-12-02 14:31:20 +00003071 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003072}
3073
3074
3075static PyObject*
3076DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3077{
3078 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3079}
3080
3081
3082static PyObject*
3083DBC_delete(DBCursorObject* self, PyObject* args)
3084{
3085 int err, flags=0;
3086
3087 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3088 return NULL;
3089
3090 CHECK_CURSOR_NOT_CLOSED(self);
3091
3092 MYDB_BEGIN_ALLOW_THREADS;
3093 err = self->dbc->c_del(self->dbc, flags);
3094 MYDB_END_ALLOW_THREADS;
3095 RETURN_IF_ERR();
3096
3097 self->mydb->haveStat = 0;
3098 RETURN_NONE();
3099}
3100
3101
3102static PyObject*
3103DBC_dup(DBCursorObject* self, PyObject* args)
3104{
3105 int err, flags =0;
3106 DBC* dbc = NULL;
3107
3108 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3109 return NULL;
3110
3111 CHECK_CURSOR_NOT_CLOSED(self);
3112
3113 MYDB_BEGIN_ALLOW_THREADS;
3114 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3115 MYDB_END_ALLOW_THREADS;
3116 RETURN_IF_ERR();
3117
3118 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3119}
3120
3121static PyObject*
3122DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3123{
3124 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3125}
3126
3127
3128static PyObject*
3129DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3130{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003131 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003132 PyObject* keyobj = NULL;
3133 PyObject* dataobj = NULL;
3134 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003135 Py_buffer* data_buf_view = NULL;
3136 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003137 int dlen = -1;
3138 int doff = -1;
3139 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003140 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003141 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142
3143 CLEAR_DBT(key);
3144 CLEAR_DBT(data);
3145 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003146 &flags, &dlen, &doff))
3147 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003148 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003149 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3150 &kwnames[1],
3151 &keyobj, &flags, &dlen, &doff))
3152 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003153 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3155 kwnames, &keyobj, &dataobj,
3156 &flags, &dlen, &doff))
3157 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158 return NULL;
3159 }
3160 }
3161 }
3162
3163 CHECK_CURSOR_NOT_CLOSED(self);
3164
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003165 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003166 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003167 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003168 (!add_partial_dbt(&data, dlen, doff)) )
3169 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003170 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3171 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003173 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174
3175 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3176 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003177 if (!(key.flags & DB_DBT_REALLOC)) {
3178 key.flags |= DB_DBT_MALLOC;
3179 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003180 }
3181
3182 MYDB_BEGIN_ALLOW_THREADS;
3183 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3184 MYDB_END_ALLOW_THREADS;
3185
Gregory P. Smithe9477062005-06-04 06:46:59 +00003186 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3187 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 Py_INCREF(Py_None);
3189 retval = Py_None;
3190 }
3191 else if (makeDBError(err)) {
3192 retval = NULL;
3193 }
3194 else {
3195 switch (_DB_get_type(self->mydb)) {
3196 case -1:
3197 retval = NULL;
3198 break;
3199 case DB_BTREE:
3200 case DB_HASH:
3201 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003202 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003203 data.data, data.size);
3204 break;
3205 case DB_RECNO:
3206 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003207 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 data.data, data.size);
3209 break;
3210 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003211 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003212 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003213 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3214 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003215 return retval;
3216}
3217
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003218#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003219static PyObject*
3220DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3221{
3222 int err, flags=0;
3223 PyObject* keyobj = NULL;
3224 PyObject* dataobj = NULL;
3225 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003226 Py_buffer* data_buf_view = NULL;
3227 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003228 int dlen = -1;
3229 int doff = -1;
3230 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003231 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3232 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003233
3234 CLEAR_DBT(key);
3235 CLEAR_DBT(data);
3236 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3237 &flags, &dlen, &doff))
3238 {
3239 PyErr_Clear();
3240 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003241 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003242 &keyobj, &flags, &dlen, &doff))
3243 {
3244 PyErr_Clear();
3245 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3246 kwnames, &keyobj, &dataobj,
3247 &flags, &dlen, &doff))
3248 {
3249 return NULL;
3250 }
3251 }
3252 }
3253
3254 CHECK_CURSOR_NOT_CLOSED(self);
3255
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003256 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003257 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003258 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003259 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003260 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3261 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003262 return NULL;
3263 }
3264
3265 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3266 data.flags = DB_DBT_MALLOC;
3267 if (!(key.flags & DB_DBT_REALLOC)) {
3268 key.flags |= DB_DBT_MALLOC;
3269 }
3270 }
3271
3272 CLEAR_DBT(pkey);
3273 pkey.flags = DB_DBT_MALLOC;
3274
3275 MYDB_BEGIN_ALLOW_THREADS;
3276 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3277 MYDB_END_ALLOW_THREADS;
3278
Gregory P. Smithe9477062005-06-04 06:46:59 +00003279 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3280 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003281 Py_INCREF(Py_None);
3282 retval = Py_None;
3283 }
3284 else if (makeDBError(err)) {
3285 retval = NULL;
3286 }
3287 else {
3288 PyObject *pkeyObj;
3289 PyObject *dataObj;
Christian Heimes72b710a2008-05-26 13:28:38 +00003290 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003291
3292 if (self->mydb->primaryDBType == DB_RECNO ||
3293 self->mydb->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003294 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003295 else
Christian Heimes72b710a2008-05-26 13:28:38 +00003296 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003297
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003298 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 {
3300 PyObject *keyObj;
3301 int type = _DB_get_type(self->mydb);
3302 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003303 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003304 else
Christian Heimes72b710a2008-05-26 13:28:38 +00003305 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003306 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003307 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003308 }
3309 else /* return just the pkey and data */
3310 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003311 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003312 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003313 Py_DECREF(dataObj);
3314 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003315 free_dbt(&pkey);
3316 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003317 }
3318 /* the only time REALLOC should be set is if we used an integer
3319 * key that make_key_dbt malloc'd for us. always free these. */
3320 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003321 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003322 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003323 free_buf_view(keyobj, key_buf_view);
3324 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003325 return retval;
3326}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003327#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003328
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003329
3330static PyObject*
3331DBC_get_recno(DBCursorObject* self, PyObject* args)
3332{
3333 int err;
3334 db_recno_t recno;
3335 DBT key;
3336 DBT data;
3337
3338 if (!PyArg_ParseTuple(args, ":get_recno"))
3339 return NULL;
3340
3341 CHECK_CURSOR_NOT_CLOSED(self);
3342
3343 CLEAR_DBT(key);
3344 CLEAR_DBT(data);
3345 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3346 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3347 data.flags = DB_DBT_MALLOC;
3348 key.flags = DB_DBT_MALLOC;
3349 }
3350
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3353 MYDB_END_ALLOW_THREADS;
3354 RETURN_IF_ERR();
3355
3356 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003357 free_dbt(&key);
3358 free_dbt(&data);
Christian Heimes217cfd12007-12-02 14:31:20 +00003359 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360}
3361
3362
3363static PyObject*
3364DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3365{
3366 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3367}
3368
3369
3370static PyObject*
3371DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3372{
3373 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3374}
3375
3376
3377static PyObject*
3378DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3379{
3380 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3381}
3382
3383
3384static PyObject*
3385DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3386{
3387 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003388 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003389 Py_buffer *data_buf_view = NULL;
3390 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003392 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003393 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 int dlen = -1;
3395 int doff = -1;
3396
3397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3398 &keyobj, &dataobj, &flags, &dlen, &doff))
3399 return NULL;
3400
3401 CHECK_CURSOR_NOT_CLOSED(self);
3402
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003403 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003404 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003405 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003406 !add_partial_dbt(&data, dlen, doff) )
3407 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003408 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3409 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003411 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412
3413 MYDB_BEGIN_ALLOW_THREADS;
3414 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3415 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003416 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3417 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 RETURN_IF_ERR();
3419 self->mydb->haveStat = 0;
3420 RETURN_NONE();
3421}
3422
3423
3424static PyObject*
3425DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3426{
3427 int err, flags = 0;
3428 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003429 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003430 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003431 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432 int dlen = -1;
3433 int doff = -1;
3434
3435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3436 &keyobj, &flags, &dlen, &doff))
3437 return NULL;
3438
3439 CHECK_CURSOR_NOT_CLOSED(self);
3440
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003441 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 return NULL;
3443
3444 CLEAR_DBT(data);
3445 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3446 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3447 data.flags = DB_DBT_MALLOC;
3448 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003449 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003450 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003452 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003453
3454 MYDB_BEGIN_ALLOW_THREADS;
3455 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3456 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003457 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3458 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003459 Py_INCREF(Py_None);
3460 retval = Py_None;
3461 }
3462 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 retval = NULL;
3464 }
3465 else {
3466 switch (_DB_get_type(self->mydb)) {
3467 case -1:
3468 retval = NULL;
3469 break;
3470 case DB_BTREE:
3471 case DB_HASH:
3472 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003473 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003474 data.data, data.size);
3475 break;
3476 case DB_RECNO:
3477 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003478 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 data.data, data.size);
3480 break;
3481 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003482 free_dbt(&data);
3483 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003485 /* the only time REALLOC should be set is if we used an integer
3486 * key that make_key_dbt malloc'd for us. always free these. */
3487 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003488 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003489 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003490 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003491
3492 return retval;
3493}
3494
3495
3496static PyObject*
3497DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3498{
3499 int err, flags = 0;
3500 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003501 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003502 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003503 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003504 int dlen = -1;
3505 int doff = -1;
3506
3507 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3508 &keyobj, &flags, &dlen, &doff))
3509 return NULL;
3510
3511 CHECK_CURSOR_NOT_CLOSED(self);
3512
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003513 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003514 return NULL;
3515
3516 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003517 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003518 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003519 return NULL;
3520 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003521 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3522 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003523 data.flags |= DB_DBT_MALLOC;
3524 /* only BTREE databases will return anything in the key */
3525 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3526 key.flags |= DB_DBT_MALLOC;
3527 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003528 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003529 MYDB_BEGIN_ALLOW_THREADS;
3530 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3531 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003532 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3533 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003534 Py_INCREF(Py_None);
3535 retval = Py_None;
3536 }
3537 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 retval = NULL;
3539 }
3540 else {
3541 switch (_DB_get_type(self->mydb)) {
3542 case -1:
3543 retval = NULL;
3544 break;
3545 case DB_BTREE:
3546 case DB_HASH:
3547 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003548 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549 data.data, data.size);
3550 break;
3551 case DB_RECNO:
3552 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003553 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554 data.data, data.size);
3555 break;
3556 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003557 free_dbt(&key);
3558 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003559 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003560 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003561 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003562 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003563 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003564 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003565 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566
3567 return retval;
3568}
3569
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003571_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3572 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003574 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003576 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003577 Py_buffer *data_buf_view = NULL;
3578 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579
Gregory P. Smith7441e652003-11-03 21:35:31 +00003580 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003581 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003583 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3584 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003586 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587
3588 MYDB_BEGIN_ALLOW_THREADS;
3589 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3590 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003591 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003592 Py_INCREF(Py_None);
3593 retval = Py_None;
3594 }
3595 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 retval = NULL;
3597 }
3598 else {
3599 switch (_DB_get_type(self->mydb)) {
3600 case -1:
3601 retval = NULL;
3602 break;
3603 case DB_BTREE:
3604 case DB_HASH:
3605 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003606 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003607 data.data, data.size);
3608 break;
3609 case DB_RECNO:
3610 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003611 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003612 data.data, data.size);
3613 break;
3614 }
3615 }
3616
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003617 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3618 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619 return retval;
3620}
3621
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003622static PyObject*
3623DBC_get_both(DBCursorObject* self, PyObject* args)
3624{
3625 int flags=0;
3626 PyObject *keyobj, *dataobj;
3627
3628 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3629 return NULL;
3630
Gregory P. Smith7441e652003-11-03 21:35:31 +00003631 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003632 CHECK_CURSOR_NOT_CLOSED(self);
3633
3634 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3635 self->mydb->moduleFlags.getReturnsNone);
3636}
3637
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003638/* Return size of entry */
3639static PyObject*
3640DBC_get_current_size(DBCursorObject* self, PyObject* args)
3641{
3642 int err, flags=DB_CURRENT;
3643 PyObject* retval = NULL;
3644 DBT key, data;
3645
3646 if (!PyArg_ParseTuple(args, ":get_current_size"))
3647 return NULL;
3648 CHECK_CURSOR_NOT_CLOSED(self);
3649 CLEAR_DBT(key);
3650 CLEAR_DBT(data);
3651
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003652 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003653 getting the record size. */
3654 data.flags = DB_DBT_USERMEM;
3655 data.ulen = 0;
3656 MYDB_BEGIN_ALLOW_THREADS;
3657 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3658 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003659 if (err == DB_BUFFER_SMALL || !err) {
3660 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Christian Heimes217cfd12007-12-02 14:31:20 +00003661 retval = PyLong_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003662 err = 0;
3663 }
3664
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003665 free_dbt(&key);
3666 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003667 RETURN_IF_ERR();
3668 return retval;
3669}
3670
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671static PyObject*
3672DBC_set_both(DBCursorObject* self, PyObject* args)
3673{
3674 int flags=0;
3675 PyObject *keyobj, *dataobj;
3676
3677 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3678 return NULL;
3679
Gregory P. Smith7441e652003-11-03 21:35:31 +00003680 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003681 CHECK_CURSOR_NOT_CLOSED(self);
3682
3683 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3684 self->mydb->moduleFlags.cursorSetReturnsNone);
3685}
3686
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003687
3688static PyObject*
3689DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3690{
3691 int err, irecno, flags=0;
3692 db_recno_t recno;
3693 DBT key, data;
3694 PyObject* retval;
3695 int dlen = -1;
3696 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003697 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003698
3699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3700 &irecno, &flags, &dlen, &doff))
3701 return NULL;
3702
3703 CHECK_CURSOR_NOT_CLOSED(self);
3704
3705 CLEAR_DBT(key);
3706 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003707 /* use allocated space so DB will be able to realloc room for the real
3708 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003709 key.data = malloc(sizeof(db_recno_t));
3710 if (key.data == NULL) {
3711 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3712 return NULL;
3713 }
3714 key.size = sizeof(db_recno_t);
3715 key.ulen = key.size;
3716 memcpy(key.data, &recno, sizeof(db_recno_t));
3717 key.flags = DB_DBT_REALLOC;
3718
3719 CLEAR_DBT(data);
3720 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3721 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3722 data.flags = DB_DBT_MALLOC;
3723 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003724 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003725 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003726 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003727 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003728
3729 MYDB_BEGIN_ALLOW_THREADS;
3730 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3731 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003732 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3733 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003734 Py_INCREF(Py_None);
3735 retval = Py_None;
3736 }
3737 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738 retval = NULL;
3739 }
3740 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003741 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003742 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003743 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003744 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003745 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003746
3747 return retval;
3748}
3749
3750
3751static PyObject*
3752DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3753{
3754 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3755}
3756
3757
3758static PyObject*
3759DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3760{
3761 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3762}
3763
3764
3765static PyObject*
3766DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3767{
3768 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3769}
3770
3771
3772static PyObject*
3773DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3774{
3775 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3776}
3777
3778
3779static PyObject*
3780DBC_join_item(DBCursorObject* self, PyObject* args)
3781{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003782 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003783 DBT key, data;
3784 PyObject* retval;
3785
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003786 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787 return NULL;
3788
3789 CHECK_CURSOR_NOT_CLOSED(self);
3790
3791 CLEAR_DBT(key);
3792 CLEAR_DBT(data);
3793 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3794 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3795 key.flags = DB_DBT_MALLOC;
3796 }
3797
3798 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003799 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003801 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3802 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003803 Py_INCREF(Py_None);
3804 retval = Py_None;
3805 }
3806 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003807 retval = NULL;
3808 }
3809 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003810 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003811 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003812 }
3813
3814 return retval;
3815}
3816
3817
3818
3819/* --------------------------------------------------------------------- */
3820/* DBEnv methods */
3821
3822
3823static PyObject*
3824DBEnv_close(DBEnvObject* self, PyObject* args)
3825{
3826 int err, flags = 0;
3827
3828 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3829 return NULL;
3830 if (!self->closed) { /* Don't close more than once */
3831 MYDB_BEGIN_ALLOW_THREADS;
3832 err = self->db_env->close(self->db_env, flags);
3833 MYDB_END_ALLOW_THREADS;
3834 /* after calling DBEnv->close, regardless of error, this DBEnv
3835 * may not be accessed again (BerkeleyDB docs). */
3836 self->closed = 1;
3837 self->db_env = NULL;
3838 RETURN_IF_ERR();
3839 }
3840 RETURN_NONE();
3841}
3842
3843
3844static PyObject*
3845DBEnv_open(DBEnvObject* self, PyObject* args)
3846{
3847 int err, flags=0, mode=0660;
3848 char *db_home;
3849
3850 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3851 return NULL;
3852
3853 CHECK_ENV_NOT_CLOSED(self);
3854
3855 MYDB_BEGIN_ALLOW_THREADS;
3856 err = self->db_env->open(self->db_env, db_home, flags, mode);
3857 MYDB_END_ALLOW_THREADS;
3858 RETURN_IF_ERR();
3859 self->closed = 0;
3860 self->flags = flags;
3861 RETURN_NONE();
3862}
3863
3864
3865static PyObject*
3866DBEnv_remove(DBEnvObject* self, PyObject* args)
3867{
3868 int err, flags=0;
3869 char *db_home;
3870
3871 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3872 return NULL;
3873 CHECK_ENV_NOT_CLOSED(self);
3874 MYDB_BEGIN_ALLOW_THREADS;
3875 err = self->db_env->remove(self->db_env, db_home, flags);
3876 MYDB_END_ALLOW_THREADS;
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3879}
3880
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003881#if (DBVER >= 41)
3882static PyObject*
3883DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3884{
3885 int err;
3886 u_int32_t flags=0;
3887 char *file = NULL;
3888 char *database = NULL;
3889 PyObject *txnobj = NULL;
3890 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003891 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003892 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003893
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003894 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003895 &file, &database, &txnobj, &flags)) {
3896 return NULL;
3897 }
3898 if (!checkTxnObj(txnobj, &txn)) {
3899 return NULL;
3900 }
3901 CHECK_ENV_NOT_CLOSED(self);
3902 MYDB_BEGIN_ALLOW_THREADS;
3903 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3904 MYDB_END_ALLOW_THREADS;
3905 RETURN_IF_ERR();
3906 RETURN_NONE();
3907}
3908
3909static PyObject*
3910DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3911{
3912 int err;
3913 u_int32_t flags=0;
3914 char *file = NULL;
3915 char *database = NULL;
3916 char *newname = NULL;
3917 PyObject *txnobj = NULL;
3918 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003919 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003920 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003921
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003923 &file, &database, &newname, &txnobj, &flags)) {
3924 return NULL;
3925 }
3926 if (!checkTxnObj(txnobj, &txn)) {
3927 return NULL;
3928 }
3929 CHECK_ENV_NOT_CLOSED(self);
3930 MYDB_BEGIN_ALLOW_THREADS;
3931 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3932 flags);
3933 MYDB_END_ALLOW_THREADS;
3934 RETURN_IF_ERR();
3935 RETURN_NONE();
3936}
3937
3938static PyObject*
3939DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3940{
3941 int err;
3942 u_int32_t flags=0;
3943 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003944 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003945
3946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3947 &passwd, &flags)) {
3948 return NULL;
3949 }
3950
3951 MYDB_BEGIN_ALLOW_THREADS;
3952 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3953 MYDB_END_ALLOW_THREADS;
3954
3955 RETURN_IF_ERR();
3956 RETURN_NONE();
3957}
3958#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003959
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003960#if (DBVER >= 40)
3961static PyObject*
3962DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3963{
3964 int err;
3965 u_int32_t flags=0;
3966 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003967 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003968
3969 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3970 &timeout, &flags)) {
3971 return NULL;
3972 }
3973
3974 MYDB_BEGIN_ALLOW_THREADS;
3975 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3976 MYDB_END_ALLOW_THREADS;
3977
3978 RETURN_IF_ERR();
3979 RETURN_NONE();
3980}
3981#endif /* DBVER >= 40 */
3982
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003983static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003984DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3985{
3986 int err;
3987 long shm_key = 0;
3988
3989 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3990 return NULL;
3991 CHECK_ENV_NOT_CLOSED(self);
3992
3993 err = self->db_env->set_shm_key(self->db_env, shm_key);
3994 RETURN_IF_ERR();
3995 RETURN_NONE();
3996}
3997
3998static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003999DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4000{
4001 int err, gbytes=0, bytes=0, ncache=0;
4002
4003 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4004 &gbytes, &bytes, &ncache))
4005 return NULL;
4006 CHECK_ENV_NOT_CLOSED(self);
4007
4008 MYDB_BEGIN_ALLOW_THREADS;
4009 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4010 MYDB_END_ALLOW_THREADS;
4011 RETURN_IF_ERR();
4012 RETURN_NONE();
4013}
4014
4015
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004016static PyObject*
4017DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4018{
4019 int err, flags=0, onoff=0;
4020
4021 if (!PyArg_ParseTuple(args, "ii:set_flags",
4022 &flags, &onoff))
4023 return NULL;
4024 CHECK_ENV_NOT_CLOSED(self);
4025
4026 MYDB_BEGIN_ALLOW_THREADS;
4027 err = self->db_env->set_flags(self->db_env, flags, onoff);
4028 MYDB_END_ALLOW_THREADS;
4029 RETURN_IF_ERR();
4030 RETURN_NONE();
4031}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004032
4033
4034static PyObject*
4035DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4036{
4037 int err;
4038 char *dir;
4039
4040 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4041 return NULL;
4042 CHECK_ENV_NOT_CLOSED(self);
4043
4044 MYDB_BEGIN_ALLOW_THREADS;
4045 err = self->db_env->set_data_dir(self->db_env, dir);
4046 MYDB_END_ALLOW_THREADS;
4047 RETURN_IF_ERR();
4048 RETURN_NONE();
4049}
4050
4051
4052static PyObject*
4053DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4054{
4055 int err, lg_bsize;
4056
4057 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4058 return NULL;
4059 CHECK_ENV_NOT_CLOSED(self);
4060
4061 MYDB_BEGIN_ALLOW_THREADS;
4062 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4063 MYDB_END_ALLOW_THREADS;
4064 RETURN_IF_ERR();
4065 RETURN_NONE();
4066}
4067
4068
4069static PyObject*
4070DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4071{
4072 int err;
4073 char *dir;
4074
4075 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4076 return NULL;
4077 CHECK_ENV_NOT_CLOSED(self);
4078
4079 MYDB_BEGIN_ALLOW_THREADS;
4080 err = self->db_env->set_lg_dir(self->db_env, dir);
4081 MYDB_END_ALLOW_THREADS;
4082 RETURN_IF_ERR();
4083 RETURN_NONE();
4084}
4085
4086static PyObject*
4087DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4088{
4089 int err, lg_max;
4090
4091 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4092 return NULL;
4093 CHECK_ENV_NOT_CLOSED(self);
4094
4095 MYDB_BEGIN_ALLOW_THREADS;
4096 err = self->db_env->set_lg_max(self->db_env, lg_max);
4097 MYDB_END_ALLOW_THREADS;
4098 RETURN_IF_ERR();
4099 RETURN_NONE();
4100}
4101
4102
Neal Norwitz84562352005-10-20 04:30:15 +00004103#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004104static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004105DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4106{
4107 int err, lg_max;
4108
4109 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4110 return NULL;
4111 CHECK_ENV_NOT_CLOSED(self);
4112
4113 MYDB_BEGIN_ALLOW_THREADS;
4114 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4115 MYDB_END_ALLOW_THREADS;
4116 RETURN_IF_ERR();
4117 RETURN_NONE();
4118}
Neal Norwitz84562352005-10-20 04:30:15 +00004119#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004120
4121
4122static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004123DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4124{
4125 int err, lk_detect;
4126
4127 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4128 return NULL;
4129 CHECK_ENV_NOT_CLOSED(self);
4130
4131 MYDB_BEGIN_ALLOW_THREADS;
4132 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4133 MYDB_END_ALLOW_THREADS;
4134 RETURN_IF_ERR();
4135 RETURN_NONE();
4136}
4137
4138
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004139#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004140static PyObject*
4141DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4142{
4143 int err, max;
4144
4145 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4146 return NULL;
4147 CHECK_ENV_NOT_CLOSED(self);
4148
4149 MYDB_BEGIN_ALLOW_THREADS;
4150 err = self->db_env->set_lk_max(self->db_env, max);
4151 MYDB_END_ALLOW_THREADS;
4152 RETURN_IF_ERR();
4153 RETURN_NONE();
4154}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004155#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004156
4157
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004158
4159static PyObject*
4160DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4161{
4162 int err, max;
4163
4164 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4165 return NULL;
4166 CHECK_ENV_NOT_CLOSED(self);
4167
4168 MYDB_BEGIN_ALLOW_THREADS;
4169 err = self->db_env->set_lk_max_locks(self->db_env, max);
4170 MYDB_END_ALLOW_THREADS;
4171 RETURN_IF_ERR();
4172 RETURN_NONE();
4173}
4174
4175
4176static PyObject*
4177DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4178{
4179 int err, max;
4180
4181 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4182 return NULL;
4183 CHECK_ENV_NOT_CLOSED(self);
4184
4185 MYDB_BEGIN_ALLOW_THREADS;
4186 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4187 MYDB_END_ALLOW_THREADS;
4188 RETURN_IF_ERR();
4189 RETURN_NONE();
4190}
4191
4192
4193static PyObject*
4194DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4195{
4196 int err, max;
4197
4198 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4199 return NULL;
4200 CHECK_ENV_NOT_CLOSED(self);
4201
4202 MYDB_BEGIN_ALLOW_THREADS;
4203 err = self->db_env->set_lk_max_objects(self->db_env, max);
4204 MYDB_END_ALLOW_THREADS;
4205 RETURN_IF_ERR();
4206 RETURN_NONE();
4207}
4208
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004209
4210static PyObject*
4211DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4212{
4213 int err, mp_mmapsize;
4214
4215 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4216 return NULL;
4217 CHECK_ENV_NOT_CLOSED(self);
4218
4219 MYDB_BEGIN_ALLOW_THREADS;
4220 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4221 MYDB_END_ALLOW_THREADS;
4222 RETURN_IF_ERR();
4223 RETURN_NONE();
4224}
4225
4226
4227static PyObject*
4228DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4229{
4230 int err;
4231 char *dir;
4232
4233 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4234 return NULL;
4235 CHECK_ENV_NOT_CLOSED(self);
4236
4237 MYDB_BEGIN_ALLOW_THREADS;
4238 err = self->db_env->set_tmp_dir(self->db_env, dir);
4239 MYDB_END_ALLOW_THREADS;
4240 RETURN_IF_ERR();
4241 RETURN_NONE();
4242}
4243
4244
4245static PyObject*
4246DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4247{
4248 int flags = 0;
4249 PyObject* txnobj = NULL;
4250 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004251 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004252
4253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4254 &txnobj, &flags))
4255 return NULL;
4256
4257 if (!checkTxnObj(txnobj, &txn))
4258 return NULL;
4259 CHECK_ENV_NOT_CLOSED(self);
4260
4261 return (PyObject*)newDBTxnObject(self, txn, flags);
4262}
4263
4264
4265static PyObject*
4266DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4267{
4268 int err, kbyte=0, min=0, flags=0;
4269
4270 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4271 return NULL;
4272 CHECK_ENV_NOT_CLOSED(self);
4273
4274 MYDB_BEGIN_ALLOW_THREADS;
4275#if (DBVER >= 40)
4276 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4277#else
4278 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4279#endif
4280 MYDB_END_ALLOW_THREADS;
4281 RETURN_IF_ERR();
4282 RETURN_NONE();
4283}
4284
4285
4286static PyObject*
4287DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4288{
4289 int err, max;
4290
4291 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4292 return NULL;
4293 CHECK_ENV_NOT_CLOSED(self);
4294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004295 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004296 RETURN_IF_ERR();
4297 RETURN_NONE();
4298}
4299
4300
4301static PyObject*
4302DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4303{
4304 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004305 long stamp;
4306 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004307
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004308 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004309 return NULL;
4310 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004311 timestamp = (time_t)stamp;
4312 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004313 RETURN_IF_ERR();
4314 RETURN_NONE();
4315}
4316
4317
4318static PyObject*
4319DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4320{
4321 int err, atype, flags=0;
4322 int aborted = 0;
4323
4324 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4325 return NULL;
4326 CHECK_ENV_NOT_CLOSED(self);
4327
4328 MYDB_BEGIN_ALLOW_THREADS;
4329#if (DBVER >= 40)
4330 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4331#else
4332 err = lock_detect(self->db_env, flags, atype, &aborted);
4333#endif
4334 MYDB_END_ALLOW_THREADS;
4335 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00004336 return PyLong_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004337}
4338
4339
4340static PyObject*
4341DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4342{
4343 int flags=0;
4344 int locker, lock_mode;
4345 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004346 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004347 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004348
4349 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4350 return NULL;
4351
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004352 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004353 return NULL;
4354
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004355 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4356 free_buf_view(objobj, obj_buf_view);
4357 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004358}
4359
4360
4361static PyObject*
4362DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4363{
4364 int err;
4365 u_int32_t theID;
4366
4367 if (!PyArg_ParseTuple(args, ":lock_id"))
4368 return NULL;
4369
4370 CHECK_ENV_NOT_CLOSED(self);
4371 MYDB_BEGIN_ALLOW_THREADS;
4372#if (DBVER >= 40)
4373 err = self->db_env->lock_id(self->db_env, &theID);
4374#else
4375 err = lock_id(self->db_env, &theID);
4376#endif
4377 MYDB_END_ALLOW_THREADS;
4378 RETURN_IF_ERR();
4379
Christian Heimes217cfd12007-12-02 14:31:20 +00004380 return PyLong_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004381}
4382
Guido van Rossum77677112007-11-05 19:43:04 +00004383#if (DBVER >= 40)
4384static PyObject*
4385DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4386{
4387 int err;
4388 u_int32_t theID;
4389
4390 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4391 return NULL;
4392
4393 CHECK_ENV_NOT_CLOSED(self);
4394 MYDB_BEGIN_ALLOW_THREADS;
4395 err = self->db_env->lock_id_free(self->db_env, theID);
4396 MYDB_END_ALLOW_THREADS;
4397 RETURN_IF_ERR();
4398 RETURN_NONE();
4399}
4400#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004401
4402static PyObject*
4403DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4404{
4405 int err;
4406 DBLockObject* dblockobj;
4407
4408 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4409 return NULL;
4410
4411 CHECK_ENV_NOT_CLOSED(self);
4412 MYDB_BEGIN_ALLOW_THREADS;
4413#if (DBVER >= 40)
4414 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4415#else
4416 err = lock_put(self->db_env, &dblockobj->lock);
4417#endif
4418 MYDB_END_ALLOW_THREADS;
4419 RETURN_IF_ERR();
4420 RETURN_NONE();
4421}
4422
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004423#if (DBVER >= 44)
4424static PyObject*
4425DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4426{
4427 int err;
4428 char *file;
4429 u_int32_t flags = 0;
4430 static char* kwnames[] = { "file", "flags", NULL};
4431
4432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4433 &file, &flags))
4434 return NULL;
4435 CHECK_ENV_NOT_CLOSED(self);
4436
4437 MYDB_BEGIN_ALLOW_THREADS;
4438 err = self->db_env->lsn_reset(self->db_env, file, flags);
4439 MYDB_END_ALLOW_THREADS;
4440 RETURN_IF_ERR();
4441 RETURN_NONE();
4442}
4443#endif /* DBVER >= 4.4 */
4444
4445#if (DBVER >= 40)
4446static PyObject*
4447DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4448{
4449 int err;
4450 DB_LOG_STAT* statp = NULL;
4451 PyObject* d = NULL;
4452 u_int32_t flags = 0;
4453
4454 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4455 return NULL;
4456 CHECK_ENV_NOT_CLOSED(self);
4457
4458 MYDB_BEGIN_ALLOW_THREADS;
4459 err = self->db_env->log_stat(self->db_env, &statp, flags);
4460 MYDB_END_ALLOW_THREADS;
4461 RETURN_IF_ERR();
4462
4463 /* Turn the stat structure into a dictionary */
4464 d = PyDict_New();
4465 if (d == NULL) {
4466 if (statp)
4467 free(statp);
4468 return NULL;
4469 }
4470
4471#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4472
4473 MAKE_ENTRY(magic);
4474 MAKE_ENTRY(version);
4475 MAKE_ENTRY(mode);
4476 MAKE_ENTRY(lg_bsize);
4477#if (DBVER >= 44)
4478 MAKE_ENTRY(lg_size);
4479 MAKE_ENTRY(record);
4480#endif
4481#if (DBVER <= 40)
4482 MAKE_ENTRY(lg_max);
4483#endif
4484 MAKE_ENTRY(w_mbytes);
4485 MAKE_ENTRY(w_bytes);
4486 MAKE_ENTRY(wc_mbytes);
4487 MAKE_ENTRY(wc_bytes);
4488 MAKE_ENTRY(wcount);
4489 MAKE_ENTRY(wcount_fill);
4490#if (DBVER >= 44)
4491 MAKE_ENTRY(rcount);
4492#endif
4493 MAKE_ENTRY(scount);
4494 MAKE_ENTRY(cur_file);
4495 MAKE_ENTRY(cur_offset);
4496 MAKE_ENTRY(disk_file);
4497 MAKE_ENTRY(disk_offset);
4498 MAKE_ENTRY(maxcommitperflush);
4499 MAKE_ENTRY(mincommitperflush);
4500 MAKE_ENTRY(regsize);
4501 MAKE_ENTRY(region_wait);
4502 MAKE_ENTRY(region_nowait);
4503
4504#undef MAKE_ENTRY
4505 free(statp);
4506 return d;
4507} /* DBEnv_log_stat */
4508#endif /* DBVER >= 4.0 for log_stat method */
4509
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510
4511static PyObject*
4512DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4513{
4514 int err;
4515 DB_LOCK_STAT* sp;
4516 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004517 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004518
4519 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4520 return NULL;
4521 CHECK_ENV_NOT_CLOSED(self);
4522
4523 MYDB_BEGIN_ALLOW_THREADS;
4524#if (DBVER >= 40)
4525 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4526#else
4527#if (DBVER >= 33)
4528 err = lock_stat(self->db_env, &sp);
4529#else
4530 err = lock_stat(self->db_env, &sp, NULL);
4531#endif
4532#endif
4533 MYDB_END_ALLOW_THREADS;
4534 RETURN_IF_ERR();
4535
4536 /* Turn the stat structure into a dictionary */
4537 d = PyDict_New();
4538 if (d == NULL) {
4539 free(sp);
4540 return NULL;
4541 }
4542
4543#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4544
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004545#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004547#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004548 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004549 MAKE_ENTRY(maxlocks);
4550 MAKE_ENTRY(maxlockers);
4551 MAKE_ENTRY(maxobjects);
4552 MAKE_ENTRY(nlocks);
4553 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004554 MAKE_ENTRY(nlockers);
4555 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004556 MAKE_ENTRY(nobjects);
4557 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004558 MAKE_ENTRY(nrequests);
4559 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004560#if (DBVER < 44)
4561 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004562 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004563#else
4564 MAKE_ENTRY(lock_nowait);
4565 MAKE_ENTRY(lock_wait);
4566#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004567 MAKE_ENTRY(ndeadlocks);
4568 MAKE_ENTRY(regsize);
4569 MAKE_ENTRY(region_wait);
4570 MAKE_ENTRY(region_nowait);
4571
4572#undef MAKE_ENTRY
4573 free(sp);
4574 return d;
4575}
4576
4577
4578static PyObject*
4579DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4580{
4581 int flags=0;
4582 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004583 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584 PyObject* list;
4585 PyObject* item = NULL;
4586
4587 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4588 return NULL;
4589
4590 CHECK_ENV_NOT_CLOSED(self);
4591 MYDB_BEGIN_ALLOW_THREADS;
4592#if (DBVER >= 40)
4593 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4594#elif (DBVER == 33)
4595 err = log_archive(self->db_env, &log_list, flags);
4596#else
4597 err = log_archive(self->db_env, &log_list, flags, NULL);
4598#endif
4599 MYDB_END_ALLOW_THREADS;
4600 RETURN_IF_ERR();
4601
4602 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004603 if (list == NULL) {
4604 if (log_list)
4605 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004607 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004608
4609 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004610 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004611 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004612 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004613 if (item == NULL) {
4614 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615 list = NULL;
4616 break;
4617 }
4618 PyList_Append(list, item);
4619 Py_DECREF(item);
4620 }
4621 free(log_list_start);
4622 }
4623 return list;
4624}
4625
4626
4627static PyObject*
4628DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4629{
4630 int err;
4631 DB_TXN_STAT* sp;
4632 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004633 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004634
4635 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4636 return NULL;
4637 CHECK_ENV_NOT_CLOSED(self);
4638
4639 MYDB_BEGIN_ALLOW_THREADS;
4640#if (DBVER >= 40)
4641 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4642#elif (DBVER == 33)
4643 err = txn_stat(self->db_env, &sp);
4644#else
4645 err = txn_stat(self->db_env, &sp, NULL);
4646#endif
4647 MYDB_END_ALLOW_THREADS;
4648 RETURN_IF_ERR();
4649
4650 /* Turn the stat structure into a dictionary */
4651 d = PyDict_New();
4652 if (d == NULL) {
4653 free(sp);
4654 return NULL;
4655 }
4656
4657#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004658#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004659
Guido van Rossumd8faa362007-04-27 19:54:29 +00004660 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661 MAKE_ENTRY(last_txnid);
4662 MAKE_ENTRY(maxtxns);
4663 MAKE_ENTRY(nactive);
4664 MAKE_ENTRY(maxnactive);
4665 MAKE_ENTRY(nbegins);
4666 MAKE_ENTRY(naborts);
4667 MAKE_ENTRY(ncommits);
4668 MAKE_ENTRY(regsize);
4669 MAKE_ENTRY(region_wait);
4670 MAKE_ENTRY(region_nowait);
4671
4672#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004673#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004674 free(sp);
4675 return d;
4676}
4677
4678
4679static PyObject*
4680DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4681{
4682 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004683 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684
4685 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4686 return NULL;
4687 CHECK_ENV_NOT_CLOSED(self);
4688
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004689 if (self->moduleFlags.getReturnsNone)
4690 ++oldValue;
4691 if (self->moduleFlags.cursorSetReturnsNone)
4692 ++oldValue;
4693 self->moduleFlags.getReturnsNone = (flags >= 1);
4694 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00004695 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004696}
4697
4698
4699/* --------------------------------------------------------------------- */
4700/* DBTxn methods */
4701
4702
4703static PyObject*
4704DBTxn_commit(DBTxnObject* self, PyObject* args)
4705{
4706 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004707 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004708
4709 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4710 return NULL;
4711
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004712 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004713 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4714 "after txn_commit or txn_abort");
4715 PyErr_SetObject(DBError, t);
4716 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004717 return NULL;
4718 }
4719 txn = self->txn;
4720 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004721 MYDB_BEGIN_ALLOW_THREADS;
4722#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004723 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004725 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004726#endif
4727 MYDB_END_ALLOW_THREADS;
4728 RETURN_IF_ERR();
4729 RETURN_NONE();
4730}
4731
4732static PyObject*
4733DBTxn_prepare(DBTxnObject* self, PyObject* args)
4734{
4735#if (DBVER >= 33)
4736 int err;
4737 char* gid=NULL;
4738 int gid_size=0;
4739
Gregory P. Smith361ed152007-08-23 07:32:27 +00004740 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004741 return NULL;
4742
4743 if (gid_size != DB_XIDDATASIZE) {
4744 PyErr_SetString(PyExc_TypeError,
4745 "gid must be DB_XIDDATASIZE bytes long");
4746 return NULL;
4747 }
4748
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004749 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004750 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4751 "after txn_commit or txn_abort");
4752 PyErr_SetObject(DBError, t);
4753 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004754 return NULL;
4755 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004756 MYDB_BEGIN_ALLOW_THREADS;
4757#if (DBVER >= 40)
4758 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4759#else
4760 err = txn_prepare(self->txn, (u_int8_t*)gid);
4761#endif
4762 MYDB_END_ALLOW_THREADS;
4763 RETURN_IF_ERR();
4764 RETURN_NONE();
4765#else
4766 int err;
4767
4768 if (!PyArg_ParseTuple(args, ":prepare"))
4769 return NULL;
4770
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004771 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004772 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4773 "after txn_commit or txn_abort");
4774 PyErr_SetObject(DBError, t);
4775 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004776 return NULL;
4777 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004778 MYDB_BEGIN_ALLOW_THREADS;
4779 err = txn_prepare(self->txn);
4780 MYDB_END_ALLOW_THREADS;
4781 RETURN_IF_ERR();
4782 RETURN_NONE();
4783#endif
4784}
4785
4786
4787static PyObject*
4788DBTxn_abort(DBTxnObject* self, PyObject* args)
4789{
4790 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004791 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004792
4793 if (!PyArg_ParseTuple(args, ":abort"))
4794 return NULL;
4795
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004796 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004797 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4798 "after txn_commit or txn_abort");
4799 PyErr_SetObject(DBError, t);
4800 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004801 return NULL;
4802 }
4803 txn = self->txn;
4804 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004805 MYDB_BEGIN_ALLOW_THREADS;
4806#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004807 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004809 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004810#endif
4811 MYDB_END_ALLOW_THREADS;
4812 RETURN_IF_ERR();
4813 RETURN_NONE();
4814}
4815
4816
4817static PyObject*
4818DBTxn_id(DBTxnObject* self, PyObject* args)
4819{
4820 int id;
4821
4822 if (!PyArg_ParseTuple(args, ":id"))
4823 return NULL;
4824
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004825 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004826 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4827 "after txn_commit or txn_abort");
4828 PyErr_SetObject(DBError, t);
4829 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004830 return NULL;
4831 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004832 MYDB_BEGIN_ALLOW_THREADS;
4833#if (DBVER >= 40)
4834 id = self->txn->id(self->txn);
4835#else
4836 id = txn_id(self->txn);
4837#endif
4838 MYDB_END_ALLOW_THREADS;
Christian Heimes217cfd12007-12-02 14:31:20 +00004839 return PyLong_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004840}
4841
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004842#if (DBVER >= 43)
4843/* --------------------------------------------------------------------- */
4844/* DBSequence methods */
4845
4846
4847static PyObject*
4848DBSequence_close(DBSequenceObject* self, PyObject* args)
4849{
4850 int err, flags=0;
4851 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4852 return NULL;
4853 CHECK_SEQUENCE_NOT_CLOSED(self)
4854
4855 MYDB_BEGIN_ALLOW_THREADS
4856 err = self->sequence->close(self->sequence, flags);
4857 self->sequence = NULL;
4858 MYDB_END_ALLOW_THREADS
4859
4860 RETURN_IF_ERR();
4861
4862 RETURN_NONE();
4863}
4864
4865static PyObject*
4866DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4867{
4868 int err, flags = 0;
4869 int delta = 1;
4870 db_seq_t value;
4871 PyObject *txnobj = NULL;
4872 DB_TXN *txn = NULL;
4873 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4874 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4875 return NULL;
4876 CHECK_SEQUENCE_NOT_CLOSED(self)
4877
4878 if (!checkTxnObj(txnobj, &txn))
4879 return NULL;
4880
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4883 MYDB_END_ALLOW_THREADS
4884
4885 RETURN_IF_ERR();
4886 return PyLong_FromLongLong(value);
4887
4888}
4889
4890static PyObject*
4891DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4892{
4893 if (!PyArg_ParseTuple(args,":get_dbp"))
4894 return NULL;
4895 CHECK_SEQUENCE_NOT_CLOSED(self)
4896 Py_INCREF(self->mydb);
4897 return (PyObject* )self->mydb;
4898}
4899
4900static PyObject*
4901DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4902{
4903 int err;
4904 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004905 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004906 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004907 CHECK_SEQUENCE_NOT_CLOSED(self)
4908 MYDB_BEGIN_ALLOW_THREADS
4909 err = self->sequence->get_key(self->sequence, &key);
4910 MYDB_END_ALLOW_THREADS
4911
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004912 if (!err)
Christian Heimes72b710a2008-05-26 13:28:38 +00004913 retval = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004914
4915 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004916 RETURN_IF_ERR();
4917
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004918 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004919}
4920
4921static PyObject*
4922DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4923{
4924 int err;
4925 db_seq_t value;
4926 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4927 return NULL;
4928 CHECK_SEQUENCE_NOT_CLOSED(self)
4929
4930 MYDB_BEGIN_ALLOW_THREADS
4931 err = self->sequence->initial_value(self->sequence, value);
4932 MYDB_END_ALLOW_THREADS
4933
4934 RETURN_IF_ERR();
4935
4936 RETURN_NONE();
4937}
4938
4939static PyObject*
4940DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4941{
4942 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004943 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004944 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004945 PyObject *txnobj = NULL;
4946 DB_TXN *txn = NULL;
4947 DBT key;
4948
4949 static char* kwnames[] = {"key", "txn", "flags", NULL };
4950 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4951 return NULL;
4952
4953 if (!checkTxnObj(txnobj, &txn))
4954 return NULL;
4955
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004956 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004957 return NULL;
4958
4959 MYDB_BEGIN_ALLOW_THREADS
4960 err = self->sequence->open(self->sequence, txn, &key, flags);
4961 MYDB_END_ALLOW_THREADS
4962
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004963 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004964 RETURN_IF_ERR();
4965
4966 RETURN_NONE();
4967}
4968
4969static PyObject*
4970DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4971{
4972 int err, flags = 0;
4973 PyObject *txnobj = NULL;
4974 DB_TXN *txn = NULL;
4975
4976 static char* kwnames[] = {"txn", "flags", NULL };
4977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4978 return NULL;
4979
4980 if (!checkTxnObj(txnobj, &txn))
4981 return NULL;
4982
4983 CHECK_SEQUENCE_NOT_CLOSED(self)
4984
4985 MYDB_BEGIN_ALLOW_THREADS
4986 err = self->sequence->remove(self->sequence, txn, flags);
4987 MYDB_END_ALLOW_THREADS
4988
4989 RETURN_IF_ERR();
4990 RETURN_NONE();
4991}
4992
4993static PyObject*
4994DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4995{
4996 int err, size;
4997 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4998 return NULL;
4999 CHECK_SEQUENCE_NOT_CLOSED(self)
5000
5001 MYDB_BEGIN_ALLOW_THREADS
5002 err = self->sequence->set_cachesize(self->sequence, size);
5003 MYDB_END_ALLOW_THREADS
5004
5005 RETURN_IF_ERR();
5006 RETURN_NONE();
5007}
5008
5009static PyObject*
5010DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5011{
5012 int err, size;
5013 if (!PyArg_ParseTuple(args,":get_cachesize"))
5014 return NULL;
5015 CHECK_SEQUENCE_NOT_CLOSED(self)
5016
5017 MYDB_BEGIN_ALLOW_THREADS
5018 err = self->sequence->get_cachesize(self->sequence, &size);
5019 MYDB_END_ALLOW_THREADS
5020
5021 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005022 return PyLong_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005023}
5024
5025static PyObject*
5026DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5027{
5028 int err, flags = 0;
5029 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5030 return NULL;
5031 CHECK_SEQUENCE_NOT_CLOSED(self)
5032
5033 MYDB_BEGIN_ALLOW_THREADS
5034 err = self->sequence->set_flags(self->sequence, flags);
5035 MYDB_END_ALLOW_THREADS
5036
5037 RETURN_IF_ERR();
5038 RETURN_NONE();
5039
5040}
5041
5042static PyObject*
5043DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5044{
5045 unsigned int flags;
5046 int err;
5047 if (!PyArg_ParseTuple(args,":get_flags"))
5048 return NULL;
5049 CHECK_SEQUENCE_NOT_CLOSED(self)
5050
5051 MYDB_BEGIN_ALLOW_THREADS
5052 err = self->sequence->get_flags(self->sequence, &flags);
5053 MYDB_END_ALLOW_THREADS
5054
5055 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005056 return PyLong_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005057}
5058
5059static PyObject*
5060DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5061{
5062 int err;
5063 db_seq_t min, max;
5064 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5065 return NULL;
5066 CHECK_SEQUENCE_NOT_CLOSED(self)
5067
5068 MYDB_BEGIN_ALLOW_THREADS
5069 err = self->sequence->set_range(self->sequence, min, max);
5070 MYDB_END_ALLOW_THREADS
5071
5072 RETURN_IF_ERR();
5073 RETURN_NONE();
5074}
5075
5076static PyObject*
5077DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5078{
5079 int err;
5080 db_seq_t min, max;
5081 if (!PyArg_ParseTuple(args,":get_range"))
5082 return NULL;
5083 CHECK_SEQUENCE_NOT_CLOSED(self)
5084
5085 MYDB_BEGIN_ALLOW_THREADS
5086 err = self->sequence->get_range(self->sequence, &min, &max);
5087 MYDB_END_ALLOW_THREADS
5088
5089 RETURN_IF_ERR();
5090 return Py_BuildValue("(LL)", min, max);
5091}
5092
5093static PyObject*
5094DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5095{
5096 int err, flags = 0;
5097 DB_SEQUENCE_STAT* sp = NULL;
5098 PyObject* dict_stat;
5099 static char* kwnames[] = {"flags", NULL };
5100 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5101 return NULL;
5102 CHECK_SEQUENCE_NOT_CLOSED(self);
5103
5104 MYDB_BEGIN_ALLOW_THREADS;
5105 err = self->sequence->stat(self->sequence, &sp, flags);
5106 MYDB_END_ALLOW_THREADS;
5107 RETURN_IF_ERR();
5108
5109 if ((dict_stat = PyDict_New()) == NULL) {
5110 free(sp);
5111 return NULL;
5112 }
5113
5114
5115#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5116#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5117
5118 MAKE_INT_ENTRY(wait);
5119 MAKE_INT_ENTRY(nowait);
5120 MAKE_LONG_LONG_ENTRY(current);
5121 MAKE_LONG_LONG_ENTRY(value);
5122 MAKE_LONG_LONG_ENTRY(last_value);
5123 MAKE_LONG_LONG_ENTRY(min);
5124 MAKE_LONG_LONG_ENTRY(max);
5125 MAKE_INT_ENTRY(cache_size);
5126 MAKE_INT_ENTRY(flags);
5127
5128#undef MAKE_INT_ENTRY
5129#undef MAKE_LONG_LONG_ENTRY
5130
5131 free(sp);
5132 return dict_stat;
5133}
5134#endif
5135
5136
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005137/* --------------------------------------------------------------------- */
5138/* Method definition tables and type objects */
5139
5140static PyMethodDef DB_methods[] = {
5141 {"append", (PyCFunction)DB_append, METH_VARARGS},
5142#if (DBVER >= 33)
5143 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5144#endif
5145 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005146 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5147 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005148 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5149 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5150 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5151 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005152#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005153 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005154#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005155 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5156 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5157 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5158 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5159 {"join", (PyCFunction)DB_join, METH_VARARGS},
5160 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5161 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5162 {"items", (PyCFunction)DB_items, METH_VARARGS},
5163 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5164 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5165 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5166 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5167 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5168 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005169#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005170 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005171#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005172 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005173#if (DBVER >= 41)
5174 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5175#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5177 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5178 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5179 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5180 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5181 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5182 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5183 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5184 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005185 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005186 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005187 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5188#if (DBVER >= 33)
5189 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5190#endif
5191 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5192 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5193 {"values", (PyCFunction)DB_values, METH_VARARGS},
5194 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5195 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5196 {NULL, NULL} /* sentinel */
5197};
5198
5199
5200static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005201 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005202 (binaryfunc)DB_subscript, /*mp_subscript*/
5203 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5204};
5205
5206
5207static PyMethodDef DBCursor_methods[] = {
5208 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5209 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5210 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5211 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5212 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5213 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5214 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005215#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005216 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005217#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5219 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5220 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5221 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5222 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5223 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5224 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5225 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005226 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005227 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005228 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5229 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5230 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5231 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5232 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5233 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5234 {NULL, NULL} /* sentinel */
5235};
5236
5237
5238static PyMethodDef DBEnv_methods[] = {
5239 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5240 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5241 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005242#if (DBVER >= 41)
5243 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5244 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5245 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5246#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005247#if (DBVER >= 40)
5248 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5249#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005250 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005251 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5252 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005253 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005254 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5255 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5256 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005257#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005258 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005259#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005260 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005261#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005262 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005263#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005264 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5265 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5266 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005267 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5268 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5269 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5270 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5271 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5272 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005273 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005274 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5275 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5276 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005277#if (DBVER >= 40)
5278 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5279#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005280 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5281 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5282 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005283#if (DBVER >= 40)
5284 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5285#endif
5286#if (DBVER >= 44)
5287 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005289 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5290 {NULL, NULL} /* sentinel */
5291};
5292
5293
5294static PyMethodDef DBTxn_methods[] = {
5295 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5296 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5297 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5298 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5299 {NULL, NULL} /* sentinel */
5300};
5301
5302
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005303#if (DBVER >= 43)
5304static PyMethodDef DBSequence_methods[] = {
5305 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5306 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5307 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5308 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5309 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5310 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5311 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5312 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5313 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5314 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5315 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5316 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5317 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5318 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5319 {NULL, NULL} /* sentinel */
5320};
5321#endif
5322
5323
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005324static PyObject*
5325DB_getattr(DBObject* self, char *name)
5326{
5327 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5328}
5329
5330
5331static PyObject*
5332DBEnv_getattr(DBEnvObject* self, char *name)
5333{
5334 if (!strcmp(name, "db_home")) {
5335 CHECK_ENV_NOT_CLOSED(self);
5336 if (self->db_env->db_home == NULL) {
5337 RETURN_NONE();
5338 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005339 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005340 }
5341
5342 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5343}
5344
5345
5346static PyObject*
5347DBCursor_getattr(DBCursorObject* self, char *name)
5348{
5349 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5350}
5351
5352static PyObject*
5353DBTxn_getattr(DBTxnObject* self, char *name)
5354{
5355 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5356}
5357
5358static PyObject*
5359DBLock_getattr(DBLockObject* self, char *name)
5360{
5361 return NULL;
5362}
5363
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005364#if (DBVER >= 43)
5365static PyObject*
5366DBSequence_getattr(DBSequenceObject* self, char *name)
5367{
5368 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5369}
5370#endif
5371
Neal Norwitz227b5332006-03-22 09:28:35 +00005372static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005373 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005374 "DB", /*tp_name*/
5375 sizeof(DBObject), /*tp_basicsize*/
5376 0, /*tp_itemsize*/
5377 /* methods */
5378 (destructor)DB_dealloc, /*tp_dealloc*/
5379 0, /*tp_print*/
5380 (getattrfunc)DB_getattr, /*tp_getattr*/
5381 0, /*tp_setattr*/
5382 0, /*tp_compare*/
5383 0, /*tp_repr*/
5384 0, /*tp_as_number*/
5385 0, /*tp_as_sequence*/
5386 &DB_mapping,/*tp_as_mapping*/
5387 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005388 0, /* tp_call */
5389 0, /* tp_str */
5390 0, /* tp_getattro */
5391 0, /* tp_setattro */
5392 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005393 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005394 0, /* tp_doc */
5395 0, /* tp_traverse */
5396 0, /* tp_clear */
5397 0, /* tp_richcompare */
5398 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005399};
5400
5401
Neal Norwitz227b5332006-03-22 09:28:35 +00005402static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005403 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005404 "DBCursor", /*tp_name*/
5405 sizeof(DBCursorObject), /*tp_basicsize*/
5406 0, /*tp_itemsize*/
5407 /* methods */
5408 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5409 0, /*tp_print*/
5410 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5411 0, /*tp_setattr*/
5412 0, /*tp_compare*/
5413 0, /*tp_repr*/
5414 0, /*tp_as_number*/
5415 0, /*tp_as_sequence*/
5416 0, /*tp_as_mapping*/
5417 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005418 0, /* tp_call */
5419 0, /* tp_str */
5420 0, /* tp_getattro */
5421 0, /* tp_setattro */
5422 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005423 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005424 0, /* tp_doc */
5425 0, /* tp_traverse */
5426 0, /* tp_clear */
5427 0, /* tp_richcompare */
5428 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005429};
5430
5431
Neal Norwitz227b5332006-03-22 09:28:35 +00005432static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005433 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005434 "DBEnv", /*tp_name*/
5435 sizeof(DBEnvObject), /*tp_basicsize*/
5436 0, /*tp_itemsize*/
5437 /* methods */
5438 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5439 0, /*tp_print*/
5440 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5441 0, /*tp_setattr*/
5442 0, /*tp_compare*/
5443 0, /*tp_repr*/
5444 0, /*tp_as_number*/
5445 0, /*tp_as_sequence*/
5446 0, /*tp_as_mapping*/
5447 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005448 0, /* tp_call */
5449 0, /* tp_str */
5450 0, /* tp_getattro */
5451 0, /* tp_setattro */
5452 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005453 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005454 0, /* tp_doc */
5455 0, /* tp_traverse */
5456 0, /* tp_clear */
5457 0, /* tp_richcompare */
5458 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005459};
5460
Neal Norwitz227b5332006-03-22 09:28:35 +00005461static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005462 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005463 "DBTxn", /*tp_name*/
5464 sizeof(DBTxnObject), /*tp_basicsize*/
5465 0, /*tp_itemsize*/
5466 /* methods */
5467 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5468 0, /*tp_print*/
5469 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5470 0, /*tp_setattr*/
5471 0, /*tp_compare*/
5472 0, /*tp_repr*/
5473 0, /*tp_as_number*/
5474 0, /*tp_as_sequence*/
5475 0, /*tp_as_mapping*/
5476 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005477 0, /* tp_call */
5478 0, /* tp_str */
5479 0, /* tp_getattro */
5480 0, /* tp_setattro */
5481 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005482 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005483 0, /* tp_doc */
5484 0, /* tp_traverse */
5485 0, /* tp_clear */
5486 0, /* tp_richcompare */
5487 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005488};
5489
5490
Neal Norwitz227b5332006-03-22 09:28:35 +00005491static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005492 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005493 "DBLock", /*tp_name*/
5494 sizeof(DBLockObject), /*tp_basicsize*/
5495 0, /*tp_itemsize*/
5496 /* methods */
5497 (destructor)DBLock_dealloc, /*tp_dealloc*/
5498 0, /*tp_print*/
5499 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5500 0, /*tp_setattr*/
5501 0, /*tp_compare*/
5502 0, /*tp_repr*/
5503 0, /*tp_as_number*/
5504 0, /*tp_as_sequence*/
5505 0, /*tp_as_mapping*/
5506 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005507 0, /* tp_call */
5508 0, /* tp_str */
5509 0, /* tp_getattro */
5510 0, /* tp_setattro */
5511 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005512 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005513 0, /* tp_doc */
5514 0, /* tp_traverse */
5515 0, /* tp_clear */
5516 0, /* tp_richcompare */
5517 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005518};
5519
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005520#if (DBVER >= 43)
5521static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005522 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005523 "DBSequence", /*tp_name*/
5524 sizeof(DBSequenceObject), /*tp_basicsize*/
5525 0, /*tp_itemsize*/
5526 /* methods */
5527 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5528 0, /*tp_print*/
5529 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5530 0, /*tp_setattr*/
5531 0, /*tp_compare*/
5532 0, /*tp_repr*/
5533 0, /*tp_as_number*/
5534 0, /*tp_as_sequence*/
5535 0, /*tp_as_mapping*/
5536 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005537 0, /* tp_call */
5538 0, /* tp_str */
5539 0, /* tp_getattro */
5540 0, /* tp_setattro */
5541 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005542 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005543 0, /* tp_doc */
5544 0, /* tp_traverse */
5545 0, /* tp_clear */
5546 0, /* tp_richcompare */
5547 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005548};
5549#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005550
5551/* --------------------------------------------------------------------- */
5552/* Module-level functions */
5553
5554static PyObject*
5555DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5556{
5557 PyObject* dbenvobj = NULL;
5558 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005559 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005560
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005561 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5562 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563 return NULL;
5564 if (dbenvobj == Py_None)
5565 dbenvobj = NULL;
5566 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5567 makeTypeError("DBEnv", dbenvobj);
5568 return NULL;
5569 }
5570
5571 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5572}
5573
5574
5575static PyObject*
5576DBEnv_construct(PyObject* self, PyObject* args)
5577{
5578 int flags = 0;
5579 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5580 return (PyObject* )newDBEnvObject(flags);
5581}
5582
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005583#if (DBVER >= 43)
5584static PyObject*
5585DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5586{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005587 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005588 int flags = 0;
5589 static char* kwnames[] = { "db", "flags", NULL};
5590
5591 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5592 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005593 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005594 makeTypeError("DB", dbobj);
5595 return NULL;
5596 }
5597 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5598}
5599#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005600
5601static char bsddb_version_doc[] =
5602"Returns a tuple of major, minor, and patch release numbers of the\n\
5603underlying DB library.";
5604
5605static PyObject*
5606bsddb_version(PyObject* self, PyObject* args)
5607{
5608 int major, minor, patch;
5609
5610 if (!PyArg_ParseTuple(args, ":version"))
5611 return NULL;
5612 db_version(&major, &minor, &patch);
5613 return Py_BuildValue("(iii)", major, minor, patch);
5614}
5615
5616
5617/* List of functions defined in the module */
5618
5619static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005620 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5621 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5622#if (DBVER >= 43)
5623 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5624#endif
5625 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005626 {NULL, NULL} /* sentinel */
5627};
5628
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005629/* API structure */
5630static BSDDB_api bsddb_api;
5631
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005632
5633/* --------------------------------------------------------------------- */
5634/* Module initialization */
5635
5636
5637/* Convenience routine to export an integer value.
5638 * Errors are silently ignored, for better or for worse...
5639 */
5640#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5641
Gregory P. Smith41631e82003-09-21 00:08:14 +00005642#define MODULE_NAME_MAX_LEN 11
5643static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644
Neal Norwitzf6657e62006-12-28 04:47:50 +00005645PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005646{
5647 PyObject* m;
5648 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005649 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5650 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5651 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005652 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005653
5654 /* Initialize the type of the new type objects here; doing it here
5655 is required for portability to Windows without requiring C++. */
Christian Heimes90aa7642007-12-19 02:45:37 +00005656 Py_TYPE(&DB_Type) = &PyType_Type;
5657 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5658 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5659 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5660 Py_TYPE(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005661#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +00005662 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005663#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005664
5665
Mark Hammonda69d4092003-04-22 23:13:27 +00005666#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005667 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005668 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005669#endif
5670
5671 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005672 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005673 if (m == NULL)
5674 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005675
5676 /* Add some symbolic constants to the module */
5677 d = PyModule_GetDict(m);
5678 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005679 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005680 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5681 Py_DECREF(pybsddb_version_s);
5682 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005683 Py_DECREF(svnid_s);
5684 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005685 Py_DECREF(db_version_s);
5686 db_version_s = NULL;
5687
5688 ADD_INT(d, DB_VERSION_MAJOR);
5689 ADD_INT(d, DB_VERSION_MINOR);
5690 ADD_INT(d, DB_VERSION_PATCH);
5691
5692 ADD_INT(d, DB_MAX_PAGES);
5693 ADD_INT(d, DB_MAX_RECORDS);
5694
Gregory P. Smith41631e82003-09-21 00:08:14 +00005695#if (DBVER >= 42)
5696 ADD_INT(d, DB_RPCCLIENT);
5697#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005698 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005699 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5700 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5701#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005702 ADD_INT(d, DB_XA_CREATE);
5703
5704 ADD_INT(d, DB_CREATE);
5705 ADD_INT(d, DB_NOMMAP);
5706 ADD_INT(d, DB_THREAD);
5707
5708 ADD_INT(d, DB_FORCE);
5709 ADD_INT(d, DB_INIT_CDB);
5710 ADD_INT(d, DB_INIT_LOCK);
5711 ADD_INT(d, DB_INIT_LOG);
5712 ADD_INT(d, DB_INIT_MPOOL);
5713 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005714 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005715
5716 ADD_INT(d, DB_RECOVER);
5717 ADD_INT(d, DB_RECOVER_FATAL);
5718 ADD_INT(d, DB_TXN_NOSYNC);
5719 ADD_INT(d, DB_USE_ENVIRON);
5720 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5721
5722 ADD_INT(d, DB_LOCKDOWN);
5723 ADD_INT(d, DB_PRIVATE);
5724 ADD_INT(d, DB_SYSTEM_MEM);
5725
5726 ADD_INT(d, DB_TXN_SYNC);
5727 ADD_INT(d, DB_TXN_NOWAIT);
5728
5729 ADD_INT(d, DB_EXCL);
5730 ADD_INT(d, DB_FCNTL_LOCKING);
5731 ADD_INT(d, DB_ODDFILESIZE);
5732 ADD_INT(d, DB_RDWRMASTER);
5733 ADD_INT(d, DB_RDONLY);
5734 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005735 ADD_INT(d, DB_EXTENT);
5736 ADD_INT(d, DB_CDB_ALLDB);
5737 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005738 ADD_INT(d, DB_UPGRADE);
5739
5740 ADD_INT(d, DB_AGGRESSIVE);
5741 ADD_INT(d, DB_NOORDERCHK);
5742 ADD_INT(d, DB_ORDERCHKONLY);
5743 ADD_INT(d, DB_PR_PAGE);
5744#if ! (DBVER >= 33)
5745 ADD_INT(d, DB_VRFY_FLAGMASK);
5746 ADD_INT(d, DB_PR_HEADERS);
5747#endif
5748 ADD_INT(d, DB_PR_RECOVERYTEST);
5749 ADD_INT(d, DB_SALVAGE);
5750
5751 ADD_INT(d, DB_LOCK_NORUN);
5752 ADD_INT(d, DB_LOCK_DEFAULT);
5753 ADD_INT(d, DB_LOCK_OLDEST);
5754 ADD_INT(d, DB_LOCK_RANDOM);
5755 ADD_INT(d, DB_LOCK_YOUNGEST);
5756#if (DBVER >= 33)
5757 ADD_INT(d, DB_LOCK_MAXLOCKS);
5758 ADD_INT(d, DB_LOCK_MINLOCKS);
5759 ADD_INT(d, DB_LOCK_MINWRITE);
5760#endif
5761
5762
5763#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005764 /* docs say to use zero instead */
5765 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005766#else
5767 ADD_INT(d, DB_LOCK_CONFLICT);
5768#endif
5769
5770 ADD_INT(d, DB_LOCK_DUMP);
5771 ADD_INT(d, DB_LOCK_GET);
5772 ADD_INT(d, DB_LOCK_INHERIT);
5773 ADD_INT(d, DB_LOCK_PUT);
5774 ADD_INT(d, DB_LOCK_PUT_ALL);
5775 ADD_INT(d, DB_LOCK_PUT_OBJ);
5776
5777 ADD_INT(d, DB_LOCK_NG);
5778 ADD_INT(d, DB_LOCK_READ);
5779 ADD_INT(d, DB_LOCK_WRITE);
5780 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005781 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005782 ADD_INT(d, DB_LOCK_IWRITE);
5783 ADD_INT(d, DB_LOCK_IREAD);
5784 ADD_INT(d, DB_LOCK_IWR);
5785#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005786#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005788#else
5789 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5790#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005791 ADD_INT(d, DB_LOCK_WWRITE);
5792#endif
5793
5794 ADD_INT(d, DB_LOCK_RECORD);
5795 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005797#if (DBVER >= 33)
5798 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5799#endif
5800
5801 ADD_INT(d, DB_LOCK_NOWAIT);
5802 ADD_INT(d, DB_LOCK_RECORD);
5803 ADD_INT(d, DB_LOCK_UPGRADE);
5804
5805#if (DBVER >= 33)
5806 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005807#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005808 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005809#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005810 ADD_INT(d, DB_LSTAT_FREE);
5811 ADD_INT(d, DB_LSTAT_HELD);
5812#if (DBVER == 33)
5813 ADD_INT(d, DB_LSTAT_NOGRANT);
5814#endif
5815 ADD_INT(d, DB_LSTAT_PENDING);
5816 ADD_INT(d, DB_LSTAT_WAITING);
5817#endif
5818
5819 ADD_INT(d, DB_ARCH_ABS);
5820 ADD_INT(d, DB_ARCH_DATA);
5821 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005822#if (DBVER >= 42)
5823 ADD_INT(d, DB_ARCH_REMOVE);
5824#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825
5826 ADD_INT(d, DB_BTREE);
5827 ADD_INT(d, DB_HASH);
5828 ADD_INT(d, DB_RECNO);
5829 ADD_INT(d, DB_QUEUE);
5830 ADD_INT(d, DB_UNKNOWN);
5831
5832 ADD_INT(d, DB_DUP);
5833 ADD_INT(d, DB_DUPSORT);
5834 ADD_INT(d, DB_RECNUM);
5835 ADD_INT(d, DB_RENUMBER);
5836 ADD_INT(d, DB_REVSPLITOFF);
5837 ADD_INT(d, DB_SNAPSHOT);
5838
5839 ADD_INT(d, DB_JOIN_NOSORT);
5840
5841 ADD_INT(d, DB_AFTER);
5842 ADD_INT(d, DB_APPEND);
5843 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005844#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005845 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005846#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005847#if (DBVER >= 41)
5848 _addIntToDict(d, "DB_CHECKPOINT", 0);
5849#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005850 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005851 ADD_INT(d, DB_CURLSN);
5852#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005853#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005854 ADD_INT(d, DB_COMMIT);
5855#endif
5856 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005858 ADD_INT(d, DB_CURRENT);
5859#if (DBVER >= 33)
5860 ADD_INT(d, DB_FAST_STAT);
5861#endif
5862 ADD_INT(d, DB_FIRST);
5863 ADD_INT(d, DB_FLUSH);
5864 ADD_INT(d, DB_GET_BOTH);
5865 ADD_INT(d, DB_GET_RECNO);
5866 ADD_INT(d, DB_JOIN_ITEM);
5867 ADD_INT(d, DB_KEYFIRST);
5868 ADD_INT(d, DB_KEYLAST);
5869 ADD_INT(d, DB_LAST);
5870 ADD_INT(d, DB_NEXT);
5871 ADD_INT(d, DB_NEXT_DUP);
5872 ADD_INT(d, DB_NEXT_NODUP);
5873 ADD_INT(d, DB_NODUPDATA);
5874 ADD_INT(d, DB_NOOVERWRITE);
5875 ADD_INT(d, DB_NOSYNC);
5876 ADD_INT(d, DB_POSITION);
5877 ADD_INT(d, DB_PREV);
5878 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005879#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005880 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005881#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005882 ADD_INT(d, DB_SET);
5883 ADD_INT(d, DB_SET_RANGE);
5884 ADD_INT(d, DB_SET_RECNO);
5885 ADD_INT(d, DB_WRITECURSOR);
5886
5887 ADD_INT(d, DB_OPFLAGS_MASK);
5888 ADD_INT(d, DB_RMW);
5889#if (DBVER >= 33)
5890 ADD_INT(d, DB_DIRTY_READ);
5891 ADD_INT(d, DB_MULTIPLE);
5892 ADD_INT(d, DB_MULTIPLE_KEY);
5893#endif
5894
Gregory P. Smith29602d22006-01-24 09:46:48 +00005895#if (DBVER >= 44)
5896 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5897 ADD_INT(d, DB_READ_COMMITTED);
5898#endif
5899
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005900#if (DBVER >= 33)
5901 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005902 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005903#endif
5904
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005905#if (DBVER >= 41)
5906 _addIntToDict(d, "DB_INCOMPLETE", 0);
5907#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005908 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005909#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005910 ADD_INT(d, DB_KEYEMPTY);
5911 ADD_INT(d, DB_KEYEXIST);
5912 ADD_INT(d, DB_LOCK_DEADLOCK);
5913 ADD_INT(d, DB_LOCK_NOTGRANTED);
5914 ADD_INT(d, DB_NOSERVER);
5915 ADD_INT(d, DB_NOSERVER_HOME);
5916 ADD_INT(d, DB_NOSERVER_ID);
5917 ADD_INT(d, DB_NOTFOUND);
5918 ADD_INT(d, DB_OLD_VERSION);
5919 ADD_INT(d, DB_RUNRECOVERY);
5920 ADD_INT(d, DB_VERIFY_BAD);
5921#if (DBVER >= 33)
5922 ADD_INT(d, DB_PAGE_NOTFOUND);
5923 ADD_INT(d, DB_SECONDARY_BAD);
5924#endif
5925#if (DBVER >= 40)
5926 ADD_INT(d, DB_STAT_CLEAR);
5927 ADD_INT(d, DB_REGION_INIT);
5928 ADD_INT(d, DB_NOLOCKING);
5929 ADD_INT(d, DB_YIELDCPU);
5930 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5931 ADD_INT(d, DB_NOPANIC);
5932#endif
5933
Guido van Rossum2cc30da2007-11-02 23:46:40 +00005934#ifdef DB_REGISTER
5935 ADD_INT(d, DB_REGISTER);
5936#endif
5937
Gregory P. Smith41631e82003-09-21 00:08:14 +00005938#if (DBVER >= 42)
5939 ADD_INT(d, DB_TIME_NOTGRANTED);
5940 ADD_INT(d, DB_TXN_NOT_DURABLE);
5941 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5942 ADD_INT(d, DB_LOG_AUTOREMOVE);
5943 ADD_INT(d, DB_DIRECT_LOG);
5944 ADD_INT(d, DB_DIRECT_DB);
5945 ADD_INT(d, DB_INIT_REP);
5946 ADD_INT(d, DB_ENCRYPT);
5947 ADD_INT(d, DB_CHKSUM);
5948#endif
5949
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005950#if (DBVER >= 43)
5951 ADD_INT(d, DB_LOG_INMEMORY);
5952 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005953 ADD_INT(d, DB_SEQ_DEC);
5954 ADD_INT(d, DB_SEQ_INC);
5955 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005956#endif
5957
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005958#if (DBVER >= 41)
5959 ADD_INT(d, DB_ENCRYPT_AES);
5960 ADD_INT(d, DB_AUTO_COMMIT);
5961#else
5962 /* allow berkeleydb 4.1 aware apps to run on older versions */
5963 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5964#endif
5965
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005966 ADD_INT(d, EINVAL);
5967 ADD_INT(d, EACCES);
5968 ADD_INT(d, ENOSPC);
5969 ADD_INT(d, ENOMEM);
5970 ADD_INT(d, EAGAIN);
5971 ADD_INT(d, EBUSY);
5972 ADD_INT(d, EEXIST);
5973 ADD_INT(d, ENOENT);
5974 ADD_INT(d, EPERM);
5975
Barry Warsaw1baa9822003-03-31 19:51:29 +00005976#if (DBVER >= 40)
5977 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5978 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5979#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005980
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005981 /* The exception name must be correct for pickled exception *
5982 * objects to unpickle properly. */
5983#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5984#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5985#else
5986#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5987#endif
5988
5989 /* All the rest of the exceptions derive only from DBError */
5990#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5991 PyDict_SetItemString(d, #name, name)
5992
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005993 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005994 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5995 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005996
Gregory P. Smithe9477062005-06-04 06:46:59 +00005997 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5998 * from both DBError and KeyError, since the API only supports
5999 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006000 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006001 {
Georg Brandl1a3284e2007-12-02 09:40:06 +00006002 PyObject *builtin_mod = PyImport_ImportModule("builtins");
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006003 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6004 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006005 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6006 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006007 Py_file_input, d, d);
6008 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006009 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010 PyDict_DelItemString(d, "KeyError");
6011
6012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013#if !INCOMPLETE_IS_WARNING
6014 MAKE_EX(DBIncompleteError);
6015#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006016 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006017 MAKE_EX(DBKeyEmptyError);
6018 MAKE_EX(DBKeyExistError);
6019 MAKE_EX(DBLockDeadlockError);
6020 MAKE_EX(DBLockNotGrantedError);
6021 MAKE_EX(DBOldVersionError);
6022 MAKE_EX(DBRunRecoveryError);
6023 MAKE_EX(DBVerifyBadError);
6024 MAKE_EX(DBNoServerError);
6025 MAKE_EX(DBNoServerHomeError);
6026 MAKE_EX(DBNoServerIDError);
6027#if (DBVER >= 33)
6028 MAKE_EX(DBPageNotFoundError);
6029 MAKE_EX(DBSecondaryBadError);
6030#endif
6031
6032 MAKE_EX(DBInvalidArgError);
6033 MAKE_EX(DBAccessError);
6034 MAKE_EX(DBNoSpaceError);
6035 MAKE_EX(DBNoMemoryError);
6036 MAKE_EX(DBAgainError);
6037 MAKE_EX(DBBusyError);
6038 MAKE_EX(DBFileExistsError);
6039 MAKE_EX(DBNoSuchFileError);
6040 MAKE_EX(DBPermissionsError);
6041
6042#undef MAKE_EX
6043
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006044 /* Initiliase the C API structure and add it to the module */
6045 bsddb_api.db_type = &DB_Type;
6046 bsddb_api.dbcursor_type = &DBCursor_Type;
6047 bsddb_api.dbenv_type = &DBEnv_Type;
6048 bsddb_api.dbtxn_type = &DBTxn_Type;
6049 bsddb_api.dblock_type = &DBLock_Type;
6050#if (DBVER >= 43)
6051 bsddb_api.dbsequence_type = &DBSequence_Type;
6052#endif
6053 bsddb_api.makeDBError = makeDBError;
6054
6055 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6056 PyDict_SetItemString(d, "api", py_api);
6057 Py_DECREF(py_api);
6058
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006059 /* Check for errors */
6060 if (PyErr_Occurred()) {
6061 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006062 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006063 }
6064}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006065
6066/* allow this module to be named _pybsddb so that it can be installed
6067 * and imported on top of python >= 2.3 that includes its own older
6068 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006069PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006070{
6071 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6072 init_bsddb();
6073}