blob: fb71161aa71fb8d5019edd7106523ec48595ddaa [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithc4119182007-09-09 20:17:22 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Gregory P. Smithc4119182007-09-09 20:17:22 +000051 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000052 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
Guido van Rossum8ce8a782007-11-01 19:42:39 +000090
91#define COMPILING_BSDDB_C
92#include "bsddb.h"
93#undef COMPILING_BSDDB_C
94
95static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000096
97/* --------------------------------------------------------------------- */
98/* Various macro definitions */
99
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000101typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102#endif
103
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000194#if PYTHON_API_VERSION < 1010
195#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000196#endif
197
Gregory P. Smith31c50652004-06-28 01:20:40 +0000198
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000199/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000200#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000201#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000202
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203
Neal Norwitz227b5332006-03-22 09:28:35 +0000204static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000205
Christian Heimes90aa7642007-12-19 02:45:37 +0000206#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
207#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
208#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
209#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
210#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000211#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +0000212#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000213#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214
215
216/* --------------------------------------------------------------------- */
217/* Utility macros and functions */
218
219#define RETURN_IF_ERR() \
220 if (makeDBError(err)) { \
221 return NULL; \
222 }
223
224#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
225
Gregory P. Smithe2767172003-11-02 08:06:29 +0000226#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
227 if ((nonNull) == NULL) { \
228 PyObject *errTuple = NULL; \
229 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
230 PyErr_SetObject((pyErrObj), errTuple); \
231 Py_DECREF(errTuple); \
232 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000233 }
234
Gregory P. Smithe2767172003-11-02 08:06:29 +0000235#define CHECK_DB_NOT_CLOSED(dbobj) \
236 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
237
238#define CHECK_ENV_NOT_CLOSED(env) \
239 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
241#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000242 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000244#if (DBVER >= 43)
245#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
246 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
247#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
250 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
251
252#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
253
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000254
255static int makeDBError(int err);
256
257
258/* Return the access method type of the DBObject */
259static int _DB_get_type(DBObject* self)
260{
261#if (DBVER >= 33)
262 DBTYPE type;
263 int err;
264 err = self->db->get_type(self->db, &type);
265 if (makeDBError(err)) {
266 return -1;
267 }
268 return type;
269#else
270 return self->db->get_type(self->db);
271#endif
272}
273
274
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000275/* Handy function to free a DBT and any self-allocated data within.
276 To be used on self created DBTs. The make_dbt and make_key_dbt
277 functions have their own free routines that do more that this. */
278static void free_dbt(DBT *dbt)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279{
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000280 if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
281 free(dbt->data);
282 dbt->data = NULL;
283 }
284}
285
286
287/* Cleanup a Python buffer API view created by make_dbt() */
Thomas Heller39763a12007-09-24 14:43:56 +0000288static void free_buf_view(PyObject *obj, Py_buffer *view)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000289{
290 if (view) {
291 PyObject_ReleaseBuffer(obj, view);
292 PyMem_Free(view);
293 }
294}
295
296
297/* Cleanup a DBT and an associated Python buffer API view
298 created by make_key_dbt() */
299#define FREE_DBT_VIEW(dbt, obj, view) \
300 do { \
301 free_dbt(&(dbt)); \
302 free_buf_view((obj), (view)); \
303 } while(0);
304
305
Thomas Heller39763a12007-09-24 14:43:56 +0000306static Py_buffer * _malloc_view(PyObject *obj)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000307{
Thomas Heller39763a12007-09-24 14:43:56 +0000308 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000309
Thomas Heller39763a12007-09-24 14:43:56 +0000310 if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000311 PyErr_SetString(PyExc_MemoryError,
Thomas Heller39763a12007-09-24 14:43:56 +0000312 "Py_buffer malloc failed");
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000313 return NULL;
314 }
315 /* XXX(gps): PyBUF_LOCKDATA is desired to prevent other theads from
316 trashing the data buffer while we release the GIL during the db
317 operation. see http://bugs.python.org/issue1035 */
318 if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
319 PyMem_Free(view);
320 return NULL;
321 }
322 if (view->ndim > 1) {
323 PyErr_SetString(PyExc_BufferError,
324 "buffers must be single dimension");
325 PyObject_ReleaseBuffer(obj, view);
326 PyMem_Free(view);
327 return NULL;
328 }
329 return view;
330}
331
332
333/* Create a DBT structure (containing key and data values) from Python
334 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000335 may be filled with a newly allocated Py_buffer view on success.
336 The caller MUST call free_buf_view() on any returned Py_buffer. */
337static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000338{
Thomas Heller39763a12007-09-24 14:43:56 +0000339 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000340
341 /* simple way to ensure the caller can detect if we've returned a
342 new buffer view or not: require their pointer to start out NULL. */
343 assert(*returned_view_p == NULL);
344
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345 CLEAR_DBT(*dbt);
346 if (obj == Py_None) {
347 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000348 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000349 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000350 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000352 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353 return 0;
354 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000355
356 if ( !(view = _malloc_view(obj)) )
357 return 0;
358
359 dbt->data = view->buf;
360 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
361 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362 return 1;
363}
364
365
366/* Recno and Queue DBs can have integer keys. This function figures out
367 what's been given, verifies that it's allowed, and then makes the DBT.
368
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000369 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000370 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000371static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000372make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000373 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000374{
375 db_recno_t recno;
376 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000377 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000378
379 /* simple way to ensure the caller can detect if we've returned a
380 new buffer view or not: require their pointer to start out NULL. */
381 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382
383 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000384 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000385 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000386 if (type == -1)
387 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000388 if (type == DB_RECNO || type == DB_QUEUE) {
389 PyErr_SetString(
390 PyExc_TypeError,
391 "None keys not allowed for Recno and Queue DB's");
392 return 0;
393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000394 /* no need to do anything, the structure has already been zeroed */
395 }
396
Christian Heimes217cfd12007-12-02 14:31:20 +0000397 else if (PyLong_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 /* verify access method type */
399 type = _DB_get_type(self);
400 if (type == -1)
401 return 0;
402 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000403 /* if BTREE then an Integer key is allowed with the
404 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000405 *pflags |= DB_SET_RECNO;
406 }
407 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000408 PyErr_SetString(
409 PyExc_TypeError,
410 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000411 return 0;
412 }
413
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414 /* Make a key out of the requested recno, use allocated space so DB
415 * will be able to realloc room for the real key if needed. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000416 recno = PyLong_AS_LONG(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000417 key->data = malloc(sizeof(db_recno_t));
418 if (key->data == NULL) {
419 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
420 return 0;
421 }
422 key->ulen = key->size = sizeof(db_recno_t);
423 memcpy(key->data, &recno, sizeof(db_recno_t));
424 key->flags = DB_DBT_REALLOC;
425 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000426
427 else if (PyObject_CheckBuffer(keyobj)) {
428 /* verify access method type */
429 type = _DB_get_type(self);
430 if (type == -1)
431 return 0;
432 if (type == DB_RECNO || type == DB_QUEUE) {
433 PyErr_SetString(
434 PyExc_TypeError,
435 "Non-integer keys not allowed for Recno and Queue DB's");
436 return 0;
437 }
438
439 if ( !(view = _malloc_view(keyobj)) )
440 return 0;
441
Gregory P. Smith568065e2007-11-01 21:55:08 +0000442 /*
443 * NOTE(gps): I don't like doing a data copy here, it seems
444 * wasteful. But without a clean way to tell FREE_DBT if it
445 * should free key->data or not we have to. Other places in
446 * the code check for DB_THREAD and forceably set DBT_MALLOC
447 * when we otherwise would leave flags 0 to indicate that.
448 */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000449 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
Gregory P. Smith568065e2007-11-01 21:55:08 +0000450 key->data = malloc(key->size);
451 if (key->data == NULL) {
452 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
453 key->size = 0;
454 return 0;
455 }
456 memcpy(key->data, view->buf, key->size);
457 key->flags = DB_DBT_REALLOC;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000458 *returned_view_p = view;
459 }
460
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 else {
462 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000463 "buffer or int object expected for key, %s found",
Christian Heimes90aa7642007-12-19 02:45:37 +0000464 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000545 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000547 _db_errmsg[0] = 0;
Skip Montanaro46fc3372007-08-12 11:44:53 +0000548 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
550#else /* do an exception instead */
551 errObj = DBIncompleteError;
552#endif
553 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000554#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000555
556 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
557 case DB_KEYEXIST: errObj = DBKeyExistError; break;
558 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
559 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
560 case DB_NOTFOUND: errObj = DBNotFoundError; break;
561 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
562 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
563 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
564 case DB_NOSERVER: errObj = DBNoServerError; break;
565 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
566 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
567#if (DBVER >= 33)
568 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
569 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
570#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000571 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000572
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000573#if (DBVER >= 43)
574 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
575 case ENOMEM: errObj = PyExc_MemoryError; break;
576#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577 case EINVAL: errObj = DBInvalidArgError; break;
578 case EACCES: errObj = DBAccessError; break;
579 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000580 case EAGAIN: errObj = DBAgainError; break;
581 case EBUSY : errObj = DBBusyError; break;
582 case EEXIST: errObj = DBFileExistsError; break;
583 case ENOENT: errObj = DBNoSuchFileError; break;
584 case EPERM : errObj = DBPermissionsError; break;
585
586 default: errObj = DBError; break;
587 }
588
589 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000590 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
591 /* Ensure that bytes_left never goes negative */
592 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
593 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
594 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000595 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000596 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000597 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000598 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000599
600 errTuple = Py_BuildValue("(is)", err, errTxt);
601 PyErr_SetObject(errObj, errTuple);
602 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 }
604
605 return ((errObj != NULL) || exceptionRaised);
606}
607
608
609
610/* set a type exception */
611static void makeTypeError(char* expected, PyObject* found)
612{
613 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000614 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000615}
616
617
618/* verify that an obj is either None or a DBTxn, and set the txn pointer */
619static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
620{
621 if (txnobj == Py_None || txnobj == NULL) {
622 *txn = NULL;
623 return 1;
624 }
625 if (DBTxnObject_Check(txnobj)) {
626 *txn = ((DBTxnObject*)txnobj)->txn;
627 return 1;
628 }
629 else
630 makeTypeError("DBTxn", txnobj);
631 return 0;
632}
633
634
635/* Delete a key from a database
636 Returns 0 on success, -1 on an error. */
637static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
638{
639 int err;
640
641 MYDB_BEGIN_ALLOW_THREADS;
642 err = self->db->del(self->db, txn, key, 0);
643 MYDB_END_ALLOW_THREADS;
644 if (makeDBError(err)) {
645 return -1;
646 }
647 self->haveStat = 0;
648 return 0;
649}
650
651
652/* Store a key into a database
653 Returns 0 on success, -1 on an error. */
654static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
655{
656 int err;
657
658 MYDB_BEGIN_ALLOW_THREADS;
659 err = self->db->put(self->db, txn, key, data, flags);
660 MYDB_END_ALLOW_THREADS;
661 if (makeDBError(err)) {
662 return -1;
663 }
664 self->haveStat = 0;
665 return 0;
666}
667
668/* Get a key/data pair from a cursor */
669static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
670 PyObject *args, PyObject *kwargs, char *format)
671{
672 int err;
673 PyObject* retval = NULL;
674 DBT key, data;
675 int dlen = -1;
676 int doff = -1;
677 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000678 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000679
680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
681 &flags, &dlen, &doff))
682 return NULL;
683
684 CHECK_CURSOR_NOT_CLOSED(self);
685
686 flags |= extra_flags;
687 CLEAR_DBT(key);
688 CLEAR_DBT(data);
689 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
690 /* Tell BerkeleyDB to malloc the return value (thread safe) */
691 data.flags = DB_DBT_MALLOC;
692 key.flags = DB_DBT_MALLOC;
693 }
694 if (!add_partial_dbt(&data, dlen, doff))
695 return NULL;
696
697 MYDB_BEGIN_ALLOW_THREADS;
698 err = self->dbc->c_get(self->dbc, &key, &data, flags);
699 MYDB_END_ALLOW_THREADS;
700
Gregory P. Smithe9477062005-06-04 06:46:59 +0000701 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
702 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 Py_INCREF(Py_None);
704 retval = Py_None;
705 }
706 else if (makeDBError(err)) {
707 retval = NULL;
708 }
709 else { /* otherwise, success! */
710
711 /* if Recno or Queue, return the key as an Int */
712 switch (_DB_get_type(self->mydb)) {
713 case -1:
714 retval = NULL;
715 break;
716
717 case DB_RECNO:
718 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000719 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000720 data.data, data.size);
721 break;
722 case DB_HASH:
723 case DB_BTREE:
724 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000725 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 data.data, data.size);
727 break;
728 }
729 }
730 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000731 free_dbt(&key);
732 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000733 }
734 return retval;
735}
736
737
738/* add an integer to a dictionary using the given name as a key */
739static void _addIntToDict(PyObject* dict, char *name, int value)
740{
Christian Heimes217cfd12007-12-02 14:31:20 +0000741 PyObject* v = PyLong_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742 if (!v || PyDict_SetItemString(dict, name, v))
743 PyErr_Clear();
744
745 Py_XDECREF(v);
746}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000747
748/* The same, when the value is a time_t */
749static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
750{
751 PyObject* v;
752 /* if the value fits in regular int, use that. */
753#ifdef HAVE_LONG_LONG
754 if (sizeof(time_t) > sizeof(long))
755 v = PyLong_FromLongLong((PY_LONG_LONG) value);
756 else
757#endif
Christian Heimes217cfd12007-12-02 14:31:20 +0000758 v = PyLong_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000759 if (!v || PyDict_SetItemString(dict, name, v))
760 PyErr_Clear();
761
762 Py_XDECREF(v);
763}
764
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000765#if (DBVER >= 43)
766/* add an db_seq_t to a dictionary using the given name as a key */
767static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
768{
769 PyObject* v = PyLong_FromLongLong(value);
770 if (!v || PyDict_SetItemString(dict, name, v))
771 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000772
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000773 Py_XDECREF(v);
774}
775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000776
777
778
779/* --------------------------------------------------------------------- */
780/* Allocators and deallocators */
781
782static DBObject*
783newDBObject(DBEnvObject* arg, int flags)
784{
785 DBObject* self;
786 DB_ENV* db_env = NULL;
787 int err;
788
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 if (self == NULL)
791 return NULL;
792
793 self->haveStat = 0;
794 self->flags = 0;
795 self->setflags = 0;
796 self->myenvobj = NULL;
797#if (DBVER >= 33)
798 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000799 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000800 self->primaryDBType = 0;
801#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000802 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000803
804 /* keep a reference to our python DBEnv object */
805 if (arg) {
806 Py_INCREF(arg);
807 self->myenvobj = arg;
808 db_env = arg->db_env;
809 }
810
811 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000812 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000814 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
815 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816
817 MYDB_BEGIN_ALLOW_THREADS;
818 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000819 if (self->db != NULL) {
820 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000822 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000824 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000825 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000826 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
827 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000828 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000829 if (makeDBError(err)) {
830 if (self->myenvobj) {
831 Py_DECREF(self->myenvobj);
832 self->myenvobj = NULL;
833 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000834 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 self = NULL;
836 }
837 return self;
838}
839
840
841static void
842DB_dealloc(DBObject* self)
843{
844 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000845 /* avoid closing a DB when its DBEnv has been closed out from under
846 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000848 (self->myenvobj && self->myenvobj->db_env))
849 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 MYDB_BEGIN_ALLOW_THREADS;
851 self->db->close(self->db, 0);
852 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000853 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000854 PyErr_WarnEx(PyExc_RuntimeWarning,
855 "DB could not be closed in destructor:"
856 " DBEnv already closed",
857 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000858 }
859 self->db = NULL;
860 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000861 if (self->in_weakreflist != NULL) {
862 PyObject_ClearWeakRefs((PyObject *) self);
863 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 if (self->myenvobj) {
865 Py_DECREF(self->myenvobj);
866 self->myenvobj = NULL;
867 }
868#if (DBVER >= 33)
869 if (self->associateCallback != NULL) {
870 Py_DECREF(self->associateCallback);
871 self->associateCallback = NULL;
872 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000873 if (self->btCompareCallback != NULL) {
874 Py_DECREF(self->btCompareCallback);
875 self->btCompareCallback = NULL;
876 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879}
880
881
882static DBCursorObject*
883newDBCursorObject(DBC* dbc, DBObject* db)
884{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000885 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886 if (self == NULL)
887 return NULL;
888
889 self->dbc = dbc;
890 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000891 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 Py_INCREF(self->mydb);
893 return self;
894}
895
896
897static void
898DBCursor_dealloc(DBCursorObject* self)
899{
900 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000901
Gregory P. Smitha703a212003-11-03 01:04:41 +0000902 if (self->in_weakreflist != NULL) {
903 PyObject_ClearWeakRefs((PyObject *) self);
904 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000905
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000906 if (self->dbc != NULL) {
907 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000908 /* If the underlying database has been closed, we don't
909 need to do anything. If the environment has been closed
910 we need to leak, as BerkeleyDB will crash trying to access
911 the environment. There was an exception when the
912 user closed the environment even though there still was
913 a database open. */
914 if (self->mydb->db && self->mydb->myenvobj &&
915 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000916 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917 self->dbc = NULL;
918 MYDB_END_ALLOW_THREADS;
919 }
920 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922}
923
924
925static DBEnvObject*
926newDBEnvObject(int flags)
927{
928 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000929 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
932
933 self->closed = 1;
934 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000935 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
936 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000937 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000938
939 MYDB_BEGIN_ALLOW_THREADS;
940 err = db_env_create(&self->db_env, flags);
941 MYDB_END_ALLOW_THREADS;
942 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000943 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 self = NULL;
945 }
946 else {
947 self->db_env->set_errcall(self->db_env, _db_errorCallback);
948 }
949 return self;
950}
951
952
953static void
954DBEnv_dealloc(DBEnvObject* self)
955{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000956 if (self->in_weakreflist != NULL) {
957 PyObject_ClearWeakRefs((PyObject *) self);
958 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000959
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000960 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000961 MYDB_BEGIN_ALLOW_THREADS;
962 self->db_env->close(self->db_env, 0);
963 MYDB_END_ALLOW_THREADS;
964 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000966}
967
968
969static DBTxnObject*
970newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
971{
972 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000973 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000974 if (self == NULL)
975 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000976 Py_INCREF(myenv);
977 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000978 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979
980 MYDB_BEGIN_ALLOW_THREADS;
981#if (DBVER >= 40)
982 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
983#else
984 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
985#endif
986 MYDB_END_ALLOW_THREADS;
987 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000988 Py_DECREF(self->env);
989 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000990 self = NULL;
991 }
992 return self;
993}
994
995
996static void
997DBTxn_dealloc(DBTxnObject* self)
998{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000999 if (self->in_weakreflist != NULL) {
1000 PyObject_ClearWeakRefs((PyObject *) self);
1001 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001002
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 if (self->txn) {
1004 /* it hasn't been finalized, abort it! */
1005 MYDB_BEGIN_ALLOW_THREADS;
1006#if (DBVER >= 40)
1007 self->txn->abort(self->txn);
1008#else
1009 txn_abort(self->txn);
1010#endif
1011 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001012 PyErr_WarnEx(PyExc_RuntimeWarning,
1013 "DBTxn aborted in destructor. "
1014 " No prior commit() or abort().",
1015 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001016 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017
Neal Norwitz62a21122006-01-25 05:21:55 +00001018 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020}
1021
1022
1023static DBLockObject*
1024newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1025 db_lockmode_t lock_mode, int flags)
1026{
1027 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001028 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029 if (self == NULL)
1030 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001031 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001032
1033 MYDB_BEGIN_ALLOW_THREADS;
1034#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001035 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1036 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037#else
1038 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1039#endif
1040 MYDB_END_ALLOW_THREADS;
1041 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001042 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001043 self = NULL;
1044 }
1045
1046 return self;
1047}
1048
1049
1050static void
1051DBLock_dealloc(DBLockObject* self)
1052{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001053 if (self->in_weakreflist != NULL) {
1054 PyObject_ClearWeakRefs((PyObject *) self);
1055 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001056 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001059}
1060
1061
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001062#if (DBVER >= 43)
1063static DBSequenceObject*
1064newDBSequenceObject(DBObject* mydb, int flags)
1065{
1066 int err;
1067 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1068 if (self == NULL)
1069 return NULL;
1070 Py_INCREF(mydb);
1071 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001072 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001073
1074
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1082 }
1083
1084 return self;
1085}
1086
1087
1088static void
1089DBSequence_dealloc(DBSequenceObject* self)
1090{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001091 if (self->in_weakreflist != NULL) {
1092 PyObject_ClearWeakRefs((PyObject *) self);
1093 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001094
1095 Py_DECREF(self->mydb);
1096 PyObject_Del(self);
1097}
1098#endif
1099
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001100/* --------------------------------------------------------------------- */
1101/* DB methods */
1102
1103static PyObject*
1104DB_append(DBObject* self, PyObject* args)
1105{
1106 PyObject* txnobj = NULL;
1107 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001108 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001109 db_recno_t recno;
1110 DBT key, data;
1111 DB_TXN *txn = NULL;
1112
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001113 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001114 return NULL;
1115
1116 CHECK_DB_NOT_CLOSED(self);
1117
1118 /* make a dummy key out of a recno */
1119 recno = 0;
1120 CLEAR_DBT(key);
1121 key.data = &recno;
1122 key.size = sizeof(recno);
1123 key.ulen = key.size;
1124 key.flags = DB_DBT_USERMEM;
1125
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001126 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001127 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001129 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1130 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001131 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001132 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001134 free_buf_view(dataobj, data_buf_view);
Christian Heimes217cfd12007-12-02 14:31:20 +00001135 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001136}
1137
1138
1139#if (DBVER >= 33)
1140
1141static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001142_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1143 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144{
1145 int retval = DB_DONOTINDEX;
1146 DBObject* secondaryDB = (DBObject*)db->app_private;
1147 PyObject* callback = secondaryDB->associateCallback;
1148 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001150 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151
1152
1153 if (callback != NULL) {
1154 MYDB_BEGIN_BLOCK_THREADS;
1155
Thomas Woutersb3153832006-03-08 01:47:19 +00001156 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001157 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001158 priData->data, priData->size);
1159 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001160 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001161 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001162 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001163 result = PyEval_CallObject(callback, args);
1164 }
1165 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001166 PyErr_Print();
1167 }
1168 else if (result == Py_None) {
1169 retval = DB_DONOTINDEX;
1170 }
Christian Heimes217cfd12007-12-02 14:31:20 +00001171 else if (PyLong_Check(result)) {
1172 retval = PyLong_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 }
Guido van Rossum98297ee2007-11-06 21:34:58 +00001174 else if (PyBytes_Check(result) || PyString_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001176 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177
1178 CLEAR_DBT(*secKey);
Christian Heimes90aa7642007-12-19 02:45:37 +00001179 size = Py_SIZE(result);
Guido van Rossum98297ee2007-11-06 21:34:58 +00001180 if (PyBytes_Check(result))
1181 data = PyBytes_AS_STRING(result);
1182 else
1183 data = PyString_AS_STRING(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1185 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001186 if (secKey->data) {
1187 memcpy(secKey->data, data, size);
1188 secKey->size = size;
1189 retval = 0;
1190 }
1191 else {
1192 PyErr_SetString(PyExc_MemoryError,
1193 "malloc failed in _db_associateCallback");
1194 PyErr_Print();
1195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001196 }
1197 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001198 PyErr_SetString(
1199 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001200 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001201 PyErr_Print();
1202 }
1203
Thomas Woutersb3153832006-03-08 01:47:19 +00001204 Py_XDECREF(args);
1205 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206
1207 MYDB_END_BLOCK_THREADS;
1208 }
1209 return retval;
1210}
1211
1212
1213static PyObject*
1214DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1215{
1216 int err, flags=0;
1217 DBObject* secondaryDB;
1218 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001219#if (DBVER >= 41)
1220 PyObject *txnobj = NULL;
1221 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001222 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001223 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001224#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001225 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001226#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1230 &secondaryDB, &callback, &flags,
1231 &txnobj)) {
1232#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001234 &secondaryDB, &callback, &flags)) {
1235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237 }
1238
1239#if (DBVER >= 41)
1240 if (!checkTxnObj(txnobj, &txn)) return NULL;
1241#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242
1243 CHECK_DB_NOT_CLOSED(self);
1244 if (!DBObject_Check(secondaryDB)) {
1245 makeTypeError("DB", (PyObject*)secondaryDB);
1246 return NULL;
1247 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001248 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001249 if (callback == Py_None) {
1250 callback = NULL;
1251 }
1252 else if (!PyCallable_Check(callback)) {
1253 makeTypeError("Callable", callback);
1254 return NULL;
1255 }
1256
1257 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001258 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001259 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 secondaryDB->associateCallback = callback;
1261 secondaryDB->primaryDBType = _DB_get_type(self);
1262
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001263 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1264 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1265 * The global interepreter lock is not initialized until the first
1266 * thread is created using thread.start_new_thread() or fork() is
1267 * called. that would cause the ALLOW_THREADS here to segfault due
1268 * to a null pointer reference if no threads or child processes
1269 * have been created. This works around that and is a no-op if
1270 * threads have already been initialized.
1271 * (see pybsddb-users mailing list post on 2002-08-07)
1272 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001273#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001274 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001275#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001277#if (DBVER >= 41)
1278 err = self->db->associate(self->db,
1279 txn,
1280 secondaryDB->db,
1281 _db_associateCallback,
1282 flags);
1283#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001284 err = self->db->associate(self->db,
1285 secondaryDB->db,
1286 _db_associateCallback,
1287 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289 MYDB_END_ALLOW_THREADS;
1290
1291 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001292 Py_XDECREF(secondaryDB->associateCallback);
1293 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294 secondaryDB->primaryDBType = 0;
1295 }
1296
1297 RETURN_IF_ERR();
1298 RETURN_NONE();
1299}
1300
1301
1302#endif
1303
1304
1305static PyObject*
1306DB_close(DBObject* self, PyObject* args)
1307{
1308 int err, flags=0;
1309 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1310 return NULL;
1311 if (self->db != NULL) {
1312 if (self->myenvobj)
1313 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 self->db = NULL;
1316 RETURN_IF_ERR();
1317 }
1318 RETURN_NONE();
1319}
1320
1321
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001322static PyObject*
1323_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1324{
1325 int err, flags=0, type;
1326 PyObject* txnobj = NULL;
1327 PyObject* retval = NULL;
1328 DBT key, data;
1329 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001330 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001331
1332 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1333 &txnobj, &flags))
1334 return NULL;
1335
1336 CHECK_DB_NOT_CLOSED(self);
1337 type = _DB_get_type(self);
1338 if (type == -1)
1339 return NULL;
1340 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001341 PyErr_SetString(PyExc_TypeError,
1342 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343 return NULL;
1344 }
1345 if (!checkTxnObj(txnobj, &txn))
1346 return NULL;
1347
1348 CLEAR_DBT(key);
1349 CLEAR_DBT(data);
1350 if (CHECK_DBFLAG(self, DB_THREAD)) {
1351 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1352 data.flags = DB_DBT_MALLOC;
1353 key.flags = DB_DBT_MALLOC;
1354 }
1355
1356 MYDB_BEGIN_ALLOW_THREADS;
1357 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1358 MYDB_END_ALLOW_THREADS;
1359
Gregory P. Smithe9477062005-06-04 06:46:59 +00001360 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1361 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362 err = 0;
1363 Py_INCREF(Py_None);
1364 retval = Py_None;
1365 }
1366 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001367 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001368 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001369 free_dbt(&key);
1370 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 }
1372
1373 RETURN_IF_ERR();
1374 return retval;
1375}
1376
1377static PyObject*
1378DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1379{
1380 return _DB_consume(self, args, kwargs, DB_CONSUME);
1381}
1382
1383static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001384DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1385 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386{
1387 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1388}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001389
1390
1391static PyObject*
1392DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1393{
1394 int err, flags=0;
1395 DBC* dbc;
1396 PyObject* txnobj = NULL;
1397 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001398 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001399
1400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1401 &txnobj, &flags))
1402 return NULL;
1403 CHECK_DB_NOT_CLOSED(self);
1404 if (!checkTxnObj(txnobj, &txn))
1405 return NULL;
1406
1407 MYDB_BEGIN_ALLOW_THREADS;
1408 err = self->db->cursor(self->db, txn, &dbc, flags);
1409 MYDB_END_ALLOW_THREADS;
1410 RETURN_IF_ERR();
1411 return (PyObject*) newDBCursorObject(dbc, self);
1412}
1413
1414
1415static PyObject*
1416DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1417{
1418 PyObject* txnobj = NULL;
1419 int flags = 0;
1420 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001421 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422 DBT key;
1423 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001424 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425
1426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1427 &keyobj, &txnobj, &flags))
1428 return NULL;
1429 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001430 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001432 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001433 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001435 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001437 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001438 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001440 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001442 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443 RETURN_NONE();
1444}
1445
1446
1447static PyObject*
1448DB_fd(DBObject* self, PyObject* args)
1449{
1450 int err, the_fd;
1451
1452 if (!PyArg_ParseTuple(args,":fd"))
1453 return NULL;
1454 CHECK_DB_NOT_CLOSED(self);
1455
1456 MYDB_BEGIN_ALLOW_THREADS;
1457 err = self->db->fd(self->db, &the_fd);
1458 MYDB_END_ALLOW_THREADS;
1459 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00001460 return PyLong_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461}
1462
1463
1464static PyObject*
1465DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1466{
1467 int err, flags=0;
1468 PyObject* txnobj = NULL;
1469 PyObject* keyobj;
1470 PyObject* dfltobj = NULL;
1471 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001472 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001473 int dlen = -1;
1474 int doff = -1;
1475 DBT key, data;
1476 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001477 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001478 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001479
1480 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001481 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1482 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001483 return NULL;
1484
1485 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001486 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001488 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001489 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001490 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001491 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001492
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
1495 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1496 data.flags = DB_DBT_MALLOC;
1497 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001498 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001499 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001500 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001501 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502
1503 MYDB_BEGIN_ALLOW_THREADS;
1504 err = self->db->get(self->db, txn, &key, &data, flags);
1505 MYDB_END_ALLOW_THREADS;
1506
Gregory P. Smithe9477062005-06-04 06:46:59 +00001507 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001508 err = 0;
1509 Py_INCREF(dfltobj);
1510 retval = dfltobj;
1511 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001512 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1513 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001514 err = 0;
1515 Py_INCREF(Py_None);
1516 retval = Py_None;
1517 }
1518 else if (!err) {
1519 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001520 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001521 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522 else /* return just the data */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001523 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001524 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001526 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001527
1528 RETURN_IF_ERR();
1529 return retval;
1530}
1531
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001532#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001533static PyObject*
1534DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1535{
1536 int err, flags=0;
1537 PyObject* txnobj = NULL;
1538 PyObject* keyobj;
1539 PyObject* dfltobj = NULL;
1540 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001541 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001542 int dlen = -1;
1543 int doff = -1;
1544 DBT key, pkey, data;
1545 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001546 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001547 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001548
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1550 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1551 &doff))
1552 return NULL;
1553
1554 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001555 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001556 return NULL;
1557 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001558 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001559 return NULL;
1560 }
1561
1562 CLEAR_DBT(data);
1563 if (CHECK_DBFLAG(self, DB_THREAD)) {
1564 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1565 data.flags = DB_DBT_MALLOC;
1566 }
1567 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001568 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001569 return NULL;
1570 }
1571
1572 CLEAR_DBT(pkey);
1573 pkey.flags = DB_DBT_MALLOC;
1574
1575 MYDB_BEGIN_ALLOW_THREADS;
1576 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1577 MYDB_END_ALLOW_THREADS;
1578
Gregory P. Smithe9477062005-06-04 06:46:59 +00001579 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001580 err = 0;
1581 Py_INCREF(dfltobj);
1582 retval = dfltobj;
1583 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001584 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1585 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001586 err = 0;
1587 Py_INCREF(Py_None);
1588 retval = Py_None;
1589 }
1590 else if (!err) {
1591 PyObject *pkeyObj;
1592 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00001593 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001594
1595 if (self->primaryDBType == DB_RECNO ||
1596 self->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001597 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001598 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001599 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001600
1601 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1602 {
1603 PyObject *keyObj;
1604 int type = _DB_get_type(self);
1605 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00001606 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00001608 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001609#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001610 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001611#else
1612 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1613#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001614 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001615 }
1616 else /* return just the pkey and data */
1617 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1622#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001623 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001624 Py_DECREF(dataObj);
1625 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001626 free_dbt(&pkey);
1627 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001628 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001629 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001630
1631 RETURN_IF_ERR();
1632 return retval;
1633}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001634#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636
1637/* Return size of entry */
1638static PyObject*
1639DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1640{
1641 int err, flags=0;
1642 PyObject* txnobj = NULL;
1643 PyObject* keyobj;
1644 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001645 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001646 DBT key, data;
1647 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001648 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649
1650 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1651 &keyobj, &txnobj))
1652 return NULL;
1653 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001654 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001656 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001657 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001659 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001660 CLEAR_DBT(data);
1661
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001662 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1663 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 data.flags = DB_DBT_USERMEM;
1665 data.ulen = 0;
1666 MYDB_BEGIN_ALLOW_THREADS;
1667 err = self->db->get(self->db, txn, &key, &data, flags);
1668 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001669 if (err == DB_BUFFER_SMALL) {
Christian Heimes217cfd12007-12-02 14:31:20 +00001670 retval = PyLong_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001671 err = 0;
1672 }
1673
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001674 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1675 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001676 RETURN_IF_ERR();
1677 return retval;
1678}
1679
1680
1681static PyObject*
1682DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1683{
1684 int err, flags=0;
1685 PyObject* txnobj = NULL;
1686 PyObject* keyobj;
1687 PyObject* dataobj;
1688 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001689 Py_buffer* data_buf_view = NULL;
1690 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001692 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001693 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001694 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001695
1696
1697 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1698 &keyobj, &dataobj, &txnobj, &flags))
1699 return NULL;
1700
1701 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001702 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001703 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001704 if ( !checkTxnObj(txnobj, &txn) ||
1705 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001706 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001707 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001708 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001709 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001710
1711 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001712 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713
1714 if (CHECK_DBFLAG(self, DB_THREAD)) {
1715 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001716 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001718 }
1719
1720 MYDB_BEGIN_ALLOW_THREADS;
1721 err = self->db->get(self->db, txn, &key, &data, flags);
1722 MYDB_END_ALLOW_THREADS;
1723
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001724 free_buf_view(dataobj, data_buf_view);
1725
Gregory P. Smithe9477062005-06-04 06:46:59 +00001726 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1727 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728 err = 0;
1729 Py_INCREF(Py_None);
1730 retval = Py_None;
1731 }
1732 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001733 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001734 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Guido van Rossum98297ee2007-11-06 21:34:58 +00001735 /* XXX(guido) But what if the input is PyString? */
1736 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001737
1738 /* Even though the flags require DB_DBT_MALLOC, data is not always
1739 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1740 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001741 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001742 }
1743
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001744 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 RETURN_IF_ERR();
1746 return retval;
1747}
1748
1749
1750static PyObject*
1751DB_get_byteswapped(DBObject* self, PyObject* args)
1752{
1753#if (DBVER >= 33)
1754 int err = 0;
1755#endif
1756 int retval = -1;
1757
1758 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1759 return NULL;
1760 CHECK_DB_NOT_CLOSED(self);
1761
1762#if (DBVER >= 33)
1763 MYDB_BEGIN_ALLOW_THREADS;
1764 err = self->db->get_byteswapped(self->db, &retval);
1765 MYDB_END_ALLOW_THREADS;
1766 RETURN_IF_ERR();
1767#else
1768 MYDB_BEGIN_ALLOW_THREADS;
1769 retval = self->db->get_byteswapped(self->db);
1770 MYDB_END_ALLOW_THREADS;
1771#endif
Christian Heimes217cfd12007-12-02 14:31:20 +00001772 return PyLong_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001773}
1774
1775
1776static PyObject*
1777DB_get_type(DBObject* self, PyObject* args)
1778{
1779 int type;
1780
1781 if (!PyArg_ParseTuple(args,":get_type"))
1782 return NULL;
1783 CHECK_DB_NOT_CLOSED(self);
1784
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001785 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786 if (type == -1)
1787 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00001788 return PyLong_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001789}
1790
1791
1792static PyObject*
1793DB_join(DBObject* self, PyObject* args)
1794{
1795 int err, flags=0;
1796 int length, x;
1797 PyObject* cursorsObj;
1798 DBC** cursors;
1799 DBC* dbc;
1800
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1802 return NULL;
1803
1804 CHECK_DB_NOT_CLOSED(self);
1805
1806 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001807 PyErr_SetString(PyExc_TypeError,
1808 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001809 return NULL;
1810 }
1811
1812 length = PyObject_Length(cursorsObj);
1813 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001814 if (!cursors) {
1815 PyErr_NoMemory();
1816 return NULL;
1817 }
1818
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001819 cursors[length] = NULL;
1820 for (x=0; x<length; x++) {
1821 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001822 if (item == NULL) {
1823 free(cursors);
1824 return NULL;
1825 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001826 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827 PyErr_SetString(PyExc_TypeError,
1828 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 free(cursors);
1830 return NULL;
1831 }
1832 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001833 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 }
1835
1836 MYDB_BEGIN_ALLOW_THREADS;
1837 err = self->db->join(self->db, cursors, &dbc, flags);
1838 MYDB_END_ALLOW_THREADS;
1839 free(cursors);
1840 RETURN_IF_ERR();
1841
Gregory P. Smith7441e652003-11-03 21:35:31 +00001842 /* FIXME: this is a buggy interface. The returned cursor
1843 contains internal references to the passed in cursors
1844 but does not hold python references to them or prevent
1845 them from being closed prematurely. This can cause
1846 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001847 return (PyObject*) newDBCursorObject(dbc, self);
1848}
1849
1850
1851static PyObject*
1852DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1853{
1854 int err, flags=0;
1855 PyObject* txnobj = NULL;
1856 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001857 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001858 DBT key;
1859 DB_TXN *txn = NULL;
1860 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001861 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001862
1863 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1864 &keyobj, &txnobj, &flags))
1865 return NULL;
1866 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001867 if (!checkTxnObj(txnobj, &txn))
1868 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001869 if (!make_dbt(keyobj, &key, &key_buf_view))
1870 /* BTree only, don't need to allow for an int key */
1871 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001872
1873 MYDB_BEGIN_ALLOW_THREADS;
1874 err = self->db->key_range(self->db, txn, &key, &range, flags);
1875 MYDB_END_ALLOW_THREADS;
1876
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001877 free_buf_view(keyobj, key_buf_view);
1878
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001879 RETURN_IF_ERR();
1880 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1881}
1882
1883
1884static PyObject*
1885DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1886{
1887 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1888 char* filename = NULL;
1889 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001890#if (DBVER >= 41)
1891 PyObject *txnobj = NULL;
1892 DB_TXN *txn = NULL;
1893 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001894 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001895 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1896 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001897 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001898 "filename", "dbtype", "flags", "mode", "txn", NULL};
1899#else
1900 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001901 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001902 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1903 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001904 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001905 "filename", "dbtype", "flags", "mode", NULL};
1906#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001907
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001908#if (DBVER >= 41)
1909 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1910 &filename, &dbname, &type, &flags, &mode,
1911 &txnobj))
1912#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001913 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001914 &filename, &dbname, &type, &flags,
1915 &mode))
1916#endif
1917 {
1918 PyErr_Clear();
1919 type = DB_UNKNOWN; flags = 0; mode = 0660;
1920 filename = NULL; dbname = NULL;
1921#if (DBVER >= 41)
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1923 kwnames_basic,
1924 &filename, &type, &flags, &mode,
1925 &txnobj))
1926 return NULL;
1927#else
1928 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1929 kwnames_basic,
1930 &filename, &type, &flags, &mode))
1931 return NULL;
1932#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001933 }
1934
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001935#if (DBVER >= 41)
1936 if (!checkTxnObj(txnobj, &txn)) return NULL;
1937#endif
1938
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001939 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001940 PyObject *t = Py_BuildValue("(is)", 0,
1941 "Cannot call open() twice for DB object");
1942 PyErr_SetObject(DBError, t);
1943 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 return NULL;
1945 }
1946
1947 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001948#if (DBVER >= 41)
1949 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1950#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001953 MYDB_END_ALLOW_THREADS;
1954 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001955 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956 self->db = NULL;
1957 return NULL;
1958 }
1959
Guido van Rossum77677112007-11-05 19:43:04 +00001960#if (DBVER >= 42)
1961 self->db->get_flags(self->db, &self->setflags);
1962#endif
1963
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001964 self->flags = flags;
1965 RETURN_NONE();
1966}
1967
1968
1969static PyObject*
1970DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1971{
1972 int flags=0;
1973 PyObject* txnobj = NULL;
1974 int dlen = -1;
1975 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001976 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00001977 Py_buffer *data_buf_view = NULL;
1978 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979 DBT key, data;
1980 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001981 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001982 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983
1984 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1985 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1986 return NULL;
1987
1988 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001989 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001990 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001991 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001992 !add_partial_dbt(&data, dlen, doff) ||
1993 !checkTxnObj(txnobj, &txn) )
1994 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001995 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1996 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001997 return NULL;
1998 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999
2000 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002001 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2002 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002003 return NULL;
2004 }
2005
2006 if (flags & DB_APPEND)
Christian Heimes217cfd12007-12-02 14:31:20 +00002007 retval = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002008 else {
2009 retval = Py_None;
2010 Py_INCREF(retval);
2011 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002012 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2013 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002014 return retval;
2015}
2016
2017
2018
2019static PyObject*
2020DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2021{
2022 char* filename;
2023 char* database = NULL;
2024 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002025 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002026
2027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2028 &filename, &database, &flags))
2029 return NULL;
2030 CHECK_DB_NOT_CLOSED(self);
2031
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002032 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002033 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002034 RETURN_IF_ERR();
2035 RETURN_NONE();
2036}
2037
2038
2039
2040static PyObject*
2041DB_rename(DBObject* self, PyObject* args)
2042{
2043 char* filename;
2044 char* database;
2045 char* newname;
2046 int err, flags=0;
2047
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002048 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2049 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002050 return NULL;
2051 CHECK_DB_NOT_CLOSED(self);
2052
2053 MYDB_BEGIN_ALLOW_THREADS;
2054 err = self->db->rename(self->db, filename, database, newname, flags);
2055 MYDB_END_ALLOW_THREADS;
2056 RETURN_IF_ERR();
2057 RETURN_NONE();
2058}
2059
2060
2061static PyObject*
2062DB_set_bt_minkey(DBObject* self, PyObject* args)
2063{
2064 int err, minkey;
2065
2066 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2067 return NULL;
2068 CHECK_DB_NOT_CLOSED(self);
2069
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->set_bt_minkey(self->db, minkey);
2072 MYDB_END_ALLOW_THREADS;
2073 RETURN_IF_ERR();
2074 RETURN_NONE();
2075}
2076
Neal Norwitz84562352005-10-20 04:30:15 +00002077#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002078static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002079_default_cmp(const DBT *leftKey,
2080 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002081{
2082 int res;
2083 int lsize = leftKey->size, rsize = rightKey->size;
2084
Georg Brandlef1701f2006-03-07 14:57:48 +00002085 res = memcmp(leftKey->data, rightKey->data,
2086 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002087
2088 if (res == 0) {
2089 if (lsize < rsize) {
2090 res = -1;
2091 }
2092 else if (lsize > rsize) {
2093 res = 1;
2094 }
2095 }
2096 return res;
2097}
2098
2099static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002100_db_compareCallback(DB* db,
2101 const DBT *leftKey,
2102 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002103{
2104 int res = 0;
2105 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002106 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002107 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108
2109 if (self == NULL || self->btCompareCallback == NULL) {
2110 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002111 PyErr_SetString(PyExc_TypeError,
2112 (self == 0
2113 ? "DB_bt_compare db is NULL."
2114 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002115 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 PyErr_Print();
2117 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002118 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002119 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120 MYDB_BEGIN_BLOCK_THREADS;
2121
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002122 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002123 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002124 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002125 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002126 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002127 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002128 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002129 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002131 PyErr_Print();
2132 res = _default_cmp(leftKey, rightKey);
Christian Heimes217cfd12007-12-02 14:31:20 +00002133 } else if (PyLong_Check(result)) {
2134 res = PyLong_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002135 } else {
2136 PyErr_SetString(PyExc_TypeError,
2137 "DB_bt_compare callback MUST return an int.");
2138 /* we're in a callback within the DB code, we can't raise */
2139 PyErr_Print();
2140 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002141 }
2142
Thomas Woutersb3153832006-03-08 01:47:19 +00002143 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002144 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002145
2146 MYDB_END_BLOCK_THREADS;
2147 }
2148 return res;
2149}
2150
2151static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002152DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002153{
2154 int err;
2155 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002156 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002157
Georg Brandlef1701f2006-03-07 14:57:48 +00002158 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002159 return NULL;
2160
Georg Brandlef1701f2006-03-07 14:57:48 +00002161 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002162
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 if (!PyCallable_Check(comparator)) {
2164 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002165 return NULL;
2166 }
2167
2168 /*
2169 * Perform a test call of the comparator function with two empty
2170 * string objects here. verify that it returns an int (0).
2171 * err if not.
2172 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002173 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002174 result = PyEval_CallObject(comparator, tuple);
2175 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002176 if (result == NULL)
2177 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002178 if (!PyLong_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002179 PyErr_SetString(PyExc_TypeError,
2180 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002181 return NULL;
Christian Heimes217cfd12007-12-02 14:31:20 +00002182 } else if (PyLong_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 PyErr_SetString(PyExc_TypeError,
2184 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002185 return NULL;
2186 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002187 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188
2189 /* We don't accept multiple set_bt_compare operations, in order to
2190 * simplify the code. This would have no real use, as one cannot
2191 * change the function once the db is opened anyway */
2192 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002193 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002194 return NULL;
2195 }
2196
Georg Brandlef1701f2006-03-07 14:57:48 +00002197 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002198 self->btCompareCallback = comparator;
2199
2200 /* This is to workaround a problem with un-initialized threads (see
2201 comment in DB_associate) */
2202#ifdef WITH_THREAD
2203 PyEval_InitThreads();
2204#endif
2205
Thomas Woutersb3153832006-03-08 01:47:19 +00002206 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
2208 if (err) {
2209 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002210 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002211 self->btCompareCallback = NULL;
2212 }
2213
Georg Brandlef1701f2006-03-07 14:57:48 +00002214 RETURN_IF_ERR();
2215 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216}
Neal Norwitz84562352005-10-20 04:30:15 +00002217#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002219
2220static PyObject*
2221DB_set_cachesize(DBObject* self, PyObject* args)
2222{
2223 int err;
2224 int gbytes = 0, bytes = 0, ncache = 0;
2225
2226 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2227 &gbytes,&bytes,&ncache))
2228 return NULL;
2229 CHECK_DB_NOT_CLOSED(self);
2230
2231 MYDB_BEGIN_ALLOW_THREADS;
2232 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2233 MYDB_END_ALLOW_THREADS;
2234 RETURN_IF_ERR();
2235 RETURN_NONE();
2236}
2237
2238
2239static PyObject*
2240DB_set_flags(DBObject* self, PyObject* args)
2241{
2242 int err, flags;
2243
2244 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_flags(self->db, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252
2253 self->setflags |= flags;
2254 RETURN_NONE();
2255}
2256
2257
2258static PyObject*
2259DB_set_h_ffactor(DBObject* self, PyObject* args)
2260{
2261 int err, ffactor;
2262
2263 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2266
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_h_ffactor(self->db, ffactor);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
2276DB_set_h_nelem(DBObject* self, PyObject* args)
2277{
2278 int err, nelem;
2279
2280 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_h_nelem(self->db, nelem);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
2291
2292static PyObject*
2293DB_set_lorder(DBObject* self, PyObject* args)
2294{
2295 int err, lorder;
2296
2297 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2298 return NULL;
2299 CHECK_DB_NOT_CLOSED(self);
2300
2301 MYDB_BEGIN_ALLOW_THREADS;
2302 err = self->db->set_lorder(self->db, lorder);
2303 MYDB_END_ALLOW_THREADS;
2304 RETURN_IF_ERR();
2305 RETURN_NONE();
2306}
2307
2308
2309static PyObject*
2310DB_set_pagesize(DBObject* self, PyObject* args)
2311{
2312 int err, pagesize;
2313
2314 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2315 return NULL;
2316 CHECK_DB_NOT_CLOSED(self);
2317
2318 MYDB_BEGIN_ALLOW_THREADS;
2319 err = self->db->set_pagesize(self->db, pagesize);
2320 MYDB_END_ALLOW_THREADS;
2321 RETURN_IF_ERR();
2322 RETURN_NONE();
2323}
2324
2325
2326static PyObject*
2327DB_set_re_delim(DBObject* self, PyObject* args)
2328{
2329 int err;
2330 char delim;
2331
2332 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2333 PyErr_Clear();
2334 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2335 return NULL;
2336 }
2337
2338 CHECK_DB_NOT_CLOSED(self);
2339
2340 MYDB_BEGIN_ALLOW_THREADS;
2341 err = self->db->set_re_delim(self->db, delim);
2342 MYDB_END_ALLOW_THREADS;
2343 RETURN_IF_ERR();
2344 RETURN_NONE();
2345}
2346
2347static PyObject*
2348DB_set_re_len(DBObject* self, PyObject* args)
2349{
2350 int err, len;
2351
2352 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2353 return NULL;
2354 CHECK_DB_NOT_CLOSED(self);
2355
2356 MYDB_BEGIN_ALLOW_THREADS;
2357 err = self->db->set_re_len(self->db, len);
2358 MYDB_END_ALLOW_THREADS;
2359 RETURN_IF_ERR();
2360 RETURN_NONE();
2361}
2362
2363
2364static PyObject*
2365DB_set_re_pad(DBObject* self, PyObject* args)
2366{
2367 int err;
2368 char pad;
2369
2370 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2371 PyErr_Clear();
2372 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2373 return NULL;
2374 }
2375 CHECK_DB_NOT_CLOSED(self);
2376
2377 MYDB_BEGIN_ALLOW_THREADS;
2378 err = self->db->set_re_pad(self->db, pad);
2379 MYDB_END_ALLOW_THREADS;
2380 RETURN_IF_ERR();
2381 RETURN_NONE();
2382}
2383
2384
2385static PyObject*
2386DB_set_re_source(DBObject* self, PyObject* args)
2387{
2388 int err;
2389 char *re_source;
2390
2391 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2392 return NULL;
2393 CHECK_DB_NOT_CLOSED(self);
2394
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_source(self->db, re_source);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2400}
2401
2402
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002403static PyObject*
2404DB_set_q_extentsize(DBObject* self, PyObject* args)
2405{
2406 int err;
2407 int extentsize;
2408
2409 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2410 return NULL;
2411 CHECK_DB_NOT_CLOSED(self);
2412
2413 MYDB_BEGIN_ALLOW_THREADS;
2414 err = self->db->set_q_extentsize(self->db, extentsize);
2415 MYDB_END_ALLOW_THREADS;
2416 RETURN_IF_ERR();
2417 RETURN_NONE();
2418}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002419
2420static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002421DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002422{
2423 int err, flags = 0, type;
2424 void* sp;
2425 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002426#if (DBVER >= 43)
2427 PyObject* txnobj = NULL;
2428 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002429 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002431 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002432#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002433
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002434#if (DBVER >= 43)
2435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2436 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002437 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438 if (!checkTxnObj(txnobj, &txn))
2439 return NULL;
2440#else
2441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2442 return NULL;
2443#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 CHECK_DB_NOT_CLOSED(self);
2445
2446 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002447#if (DBVER >= 43)
2448 err = self->db->stat(self->db, txn, &sp, flags);
2449#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002450 err = self->db->stat(self->db, &sp, flags);
2451#else
2452 err = self->db->stat(self->db, &sp, NULL, flags);
2453#endif
2454 MYDB_END_ALLOW_THREADS;
2455 RETURN_IF_ERR();
2456
2457 self->haveStat = 1;
2458
2459 /* Turn the stat structure into a dictionary */
2460 type = _DB_get_type(self);
2461 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2462 free(sp);
2463 return NULL;
2464 }
2465
2466#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2467#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2468#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2469
2470 switch (type) {
2471 case DB_HASH:
2472 MAKE_HASH_ENTRY(magic);
2473 MAKE_HASH_ENTRY(version);
2474 MAKE_HASH_ENTRY(nkeys);
2475 MAKE_HASH_ENTRY(ndata);
2476 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002477#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002478 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002479#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002480 MAKE_HASH_ENTRY(ffactor);
2481 MAKE_HASH_ENTRY(buckets);
2482 MAKE_HASH_ENTRY(free);
2483 MAKE_HASH_ENTRY(bfree);
2484 MAKE_HASH_ENTRY(bigpages);
2485 MAKE_HASH_ENTRY(big_bfree);
2486 MAKE_HASH_ENTRY(overflows);
2487 MAKE_HASH_ENTRY(ovfl_free);
2488 MAKE_HASH_ENTRY(dup);
2489 MAKE_HASH_ENTRY(dup_free);
2490 break;
2491
2492 case DB_BTREE:
2493 case DB_RECNO:
2494 MAKE_BT_ENTRY(magic);
2495 MAKE_BT_ENTRY(version);
2496 MAKE_BT_ENTRY(nkeys);
2497 MAKE_BT_ENTRY(ndata);
2498 MAKE_BT_ENTRY(pagesize);
2499 MAKE_BT_ENTRY(minkey);
2500 MAKE_BT_ENTRY(re_len);
2501 MAKE_BT_ENTRY(re_pad);
2502 MAKE_BT_ENTRY(levels);
2503 MAKE_BT_ENTRY(int_pg);
2504 MAKE_BT_ENTRY(leaf_pg);
2505 MAKE_BT_ENTRY(dup_pg);
2506 MAKE_BT_ENTRY(over_pg);
2507 MAKE_BT_ENTRY(free);
2508 MAKE_BT_ENTRY(int_pgfree);
2509 MAKE_BT_ENTRY(leaf_pgfree);
2510 MAKE_BT_ENTRY(dup_pgfree);
2511 MAKE_BT_ENTRY(over_pgfree);
2512 break;
2513
2514 case DB_QUEUE:
2515 MAKE_QUEUE_ENTRY(magic);
2516 MAKE_QUEUE_ENTRY(version);
2517 MAKE_QUEUE_ENTRY(nkeys);
2518 MAKE_QUEUE_ENTRY(ndata);
2519 MAKE_QUEUE_ENTRY(pagesize);
2520 MAKE_QUEUE_ENTRY(pages);
2521 MAKE_QUEUE_ENTRY(re_len);
2522 MAKE_QUEUE_ENTRY(re_pad);
2523 MAKE_QUEUE_ENTRY(pgfree);
2524#if (DBVER == 31)
2525 MAKE_QUEUE_ENTRY(start);
2526#endif
2527 MAKE_QUEUE_ENTRY(first_recno);
2528 MAKE_QUEUE_ENTRY(cur_recno);
2529 break;
2530
2531 default:
2532 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2533 Py_DECREF(d);
2534 d = NULL;
2535 }
2536
2537#undef MAKE_HASH_ENTRY
2538#undef MAKE_BT_ENTRY
2539#undef MAKE_QUEUE_ENTRY
2540
2541 free(sp);
2542 return d;
2543}
2544
2545static PyObject*
2546DB_sync(DBObject* self, PyObject* args)
2547{
2548 int err;
2549 int flags = 0;
2550
2551 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2552 return NULL;
2553 CHECK_DB_NOT_CLOSED(self);
2554
2555 MYDB_BEGIN_ALLOW_THREADS;
2556 err = self->db->sync(self->db, flags);
2557 MYDB_END_ALLOW_THREADS;
2558 RETURN_IF_ERR();
2559 RETURN_NONE();
2560}
2561
2562
2563#if (DBVER >= 33)
2564static PyObject*
2565DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2566{
2567 int err, flags=0;
2568 u_int32_t count=0;
2569 PyObject* txnobj = NULL;
2570 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002571 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002572
2573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2574 &txnobj, &flags))
2575 return NULL;
2576 CHECK_DB_NOT_CLOSED(self);
2577 if (!checkTxnObj(txnobj, &txn))
2578 return NULL;
2579
2580 MYDB_BEGIN_ALLOW_THREADS;
2581 err = self->db->truncate(self->db, txn, &count, flags);
2582 MYDB_END_ALLOW_THREADS;
2583 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00002584 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002585}
2586#endif
2587
2588
2589static PyObject*
2590DB_upgrade(DBObject* self, PyObject* args)
2591{
2592 int err, flags=0;
2593 char *filename;
2594
2595 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2596 return NULL;
2597 CHECK_DB_NOT_CLOSED(self);
2598
2599 MYDB_BEGIN_ALLOW_THREADS;
2600 err = self->db->upgrade(self->db, filename, flags);
2601 MYDB_END_ALLOW_THREADS;
2602 RETURN_IF_ERR();
2603 RETURN_NONE();
2604}
2605
2606
2607static PyObject*
2608DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2609{
2610 int err, flags=0;
2611 char* fileName;
2612 char* dbName=NULL;
2613 char* outFileName=NULL;
2614 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002615 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002616 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002617
2618 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2619 &fileName, &dbName, &outFileName, &flags))
2620 return NULL;
2621
2622 CHECK_DB_NOT_CLOSED(self);
2623 if (outFileName)
2624 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002625 /* XXX(nnorwitz): it should probably be an exception if outFile
2626 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002627
2628 MYDB_BEGIN_ALLOW_THREADS;
2629 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2630 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002631 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002632 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002633
2634 /* DB.verify acts as a DB handle destructor (like close); this was
2635 * documented in BerkeleyDB 4.2 but had the undocumented effect
2636 * of not being safe in prior versions while still requiring an explicit
2637 * DB.close call afterwards. Lets call close for the user to emulate
2638 * the safe 4.2 behaviour. */
2639#if (DBVER <= 41)
2640 self->db->close(self->db, 0);
2641#endif
2642 self->db = NULL;
2643
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644 RETURN_IF_ERR();
2645 RETURN_NONE();
2646}
2647
2648
2649static PyObject*
2650DB_set_get_returns_none(DBObject* self, PyObject* args)
2651{
2652 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002653 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654
2655 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2656 return NULL;
2657 CHECK_DB_NOT_CLOSED(self);
2658
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002659 if (self->moduleFlags.getReturnsNone)
2660 ++oldValue;
2661 if (self->moduleFlags.cursorSetReturnsNone)
2662 ++oldValue;
2663 self->moduleFlags.getReturnsNone = (flags >= 1);
2664 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00002665 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002666}
2667
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002668#if (DBVER >= 41)
2669static PyObject*
2670DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2671{
2672 int err;
2673 u_int32_t flags=0;
2674 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002675 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002676
2677 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2678 &passwd, &flags)) {
2679 return NULL;
2680 }
2681
2682 MYDB_BEGIN_ALLOW_THREADS;
2683 err = self->db->set_encrypt(self->db, passwd, flags);
2684 MYDB_END_ALLOW_THREADS;
2685
2686 RETURN_IF_ERR();
2687 RETURN_NONE();
2688}
2689#endif /* DBVER >= 41 */
2690
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002691
2692/*-------------------------------------------------------------- */
2693/* Mapping and Dictionary-like access routines */
2694
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002695Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696{
2697 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002698 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699 int flags = 0;
2700 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002701 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702
2703 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002704 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2705 PyErr_SetObject(DBError, t);
2706 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002707 return -1;
2708 }
2709
2710 if (self->haveStat) { /* Has the stat function been called recently? If
2711 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002712 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002713 }
2714
2715 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002716redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002717#if (DBVER >= 43)
2718 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2719#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720 err = self->db->stat(self->db, &sp, flags);
2721#else
2722 err = self->db->stat(self->db, &sp, NULL, flags);
2723#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002724
2725 /* All the stat structures have matching fields upto the ndata field,
2726 so we can use any of them for the type cast */
2727 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2728
2729 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2730 * redo a full stat to make sure.
2731 * Fixes SF python bug 1493322, pybsddb bug 1184012
2732 */
2733 if (size == 0 && (flags & DB_FAST_STAT)) {
2734 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002735 if (!err)
2736 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002737 goto redo_stat_for_length;
2738 }
2739
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 MYDB_END_ALLOW_THREADS;
2741
2742 if (err)
2743 return -1;
2744
2745 self->haveStat = 1;
2746
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002747 free(sp);
2748 return size;
2749}
2750
2751
2752PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2753{
2754 int err;
2755 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002756 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002757 DBT key;
2758 DBT data;
2759
2760 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002761 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002762 return NULL;
2763
2764 CLEAR_DBT(data);
2765 if (CHECK_DBFLAG(self, DB_THREAD)) {
2766 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2767 data.flags = DB_DBT_MALLOC;
2768 }
2769 MYDB_BEGIN_ALLOW_THREADS;
2770 err = self->db->get(self->db, NULL, &key, &data, 0);
2771 MYDB_END_ALLOW_THREADS;
2772 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2773 PyErr_SetObject(PyExc_KeyError, keyobj);
2774 retval = NULL;
2775 }
2776 else if (makeDBError(err)) {
2777 retval = NULL;
2778 }
2779 else {
Guido van Rossum98297ee2007-11-06 21:34:58 +00002780 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002781 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002782 }
2783
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002784 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002785 return retval;
2786}
2787
2788
2789static int
2790DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2791{
2792 DBT key, data;
2793 int retval;
2794 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002795 Py_buffer *data_buf_view = NULL;
2796 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002797
2798 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002799 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2800 PyErr_SetObject(DBError, t);
2801 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802 return -1;
2803 }
2804
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002805 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806 return -1;
2807
2808 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002809 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002810 retval = -1;
2811 else {
2812 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002813 /* dictionaries shouldn't have duplicate keys */
2814 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002815 retval = _DB_put(self, NULL, &key, &data, flags);
2816
2817 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002818 /* try deleting any old record that matches and then PUT it
2819 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002820 _DB_delete(self, NULL, &key, 0);
2821 PyErr_Clear();
2822 retval = _DB_put(self, NULL, &key, &data, flags);
2823 }
2824 }
2825 }
2826 else {
2827 /* dataobj == NULL, so delete the key */
2828 retval = _DB_delete(self, NULL, &key, 0);
2829 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002830 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2831 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002832 return retval;
2833}
2834
2835
2836static PyObject*
2837DB_has_key(DBObject* self, PyObject* args)
2838{
2839 int err;
2840 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002841 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002842 DBT key, data;
2843 PyObject* txnobj = NULL;
2844 DB_TXN *txn = NULL;
2845
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002846 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 return NULL;
2848 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002849 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002851 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002852 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002854 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002856 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 it has a record but can't allocate a buffer for the data. This saves
2858 having to deal with data we won't be using.
2859 */
2860 CLEAR_DBT(data);
2861 data.flags = DB_DBT_USERMEM;
2862
2863 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002864 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002865 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002866 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002867
2868 if (err == DB_BUFFER_SMALL || err == 0) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002869 return PyLong_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002870 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Christian Heimes217cfd12007-12-02 14:31:20 +00002871 return PyLong_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002872 }
2873
2874 makeDBError(err);
2875 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002876}
2877
2878
2879#define _KEYS_LIST 1
2880#define _VALUES_LIST 2
2881#define _ITEMS_LIST 3
2882
2883static PyObject*
2884_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2885{
2886 int err, dbtype;
2887 DBT key;
2888 DBT data;
2889 DBC *cursor;
2890 PyObject* list;
2891 PyObject* item = NULL;
2892
2893 CHECK_DB_NOT_CLOSED(self);
2894 CLEAR_DBT(key);
2895 CLEAR_DBT(data);
2896
2897 dbtype = _DB_get_type(self);
2898 if (dbtype == -1)
2899 return NULL;
2900
2901 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002902 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002903 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002904
2905 /* get a cursor */
2906 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002907 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002908 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002909 if (makeDBError(err)) {
2910 Py_DECREF(list);
2911 return NULL;
2912 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913
2914 if (CHECK_DBFLAG(self, DB_THREAD)) {
2915 key.flags = DB_DBT_REALLOC;
2916 data.flags = DB_DBT_REALLOC;
2917 }
2918
2919 while (1) { /* use the cursor to traverse the DB, collecting items */
2920 MYDB_BEGIN_ALLOW_THREADS;
2921 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2922 MYDB_END_ALLOW_THREADS;
2923
2924 if (err) {
2925 /* for any error, break out of the loop */
2926 break;
2927 }
2928
2929 switch (type) {
2930 case _KEYS_LIST:
2931 switch(dbtype) {
2932 case DB_BTREE:
2933 case DB_HASH:
2934 default:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002935 item = PyString_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002936 break;
2937 case DB_RECNO:
2938 case DB_QUEUE:
Christian Heimes217cfd12007-12-02 14:31:20 +00002939 item = PyLong_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002940 break;
2941 }
2942 break;
2943
2944 case _VALUES_LIST:
Guido van Rossum98297ee2007-11-06 21:34:58 +00002945 item = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002946 break;
2947
2948 case _ITEMS_LIST:
2949 switch(dbtype) {
2950 case DB_BTREE:
2951 case DB_HASH:
2952 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002953 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002954 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002955 break;
2956 case DB_RECNO:
2957 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002958 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002959 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 break;
2961 }
2962 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002963 default:
2964 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2965 item = NULL;
2966 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967 }
2968 if (item == NULL) {
2969 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002970 list = NULL;
2971 goto done;
2972 }
2973 PyList_Append(list, item);
2974 Py_DECREF(item);
2975 }
2976
Gregory P. Smithe9477062005-06-04 06:46:59 +00002977 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2978 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002979 Py_DECREF(list);
2980 list = NULL;
2981 }
2982
2983 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002984 free_dbt(&key);
2985 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986 MYDB_BEGIN_ALLOW_THREADS;
2987 cursor->c_close(cursor);
2988 MYDB_END_ALLOW_THREADS;
2989 return list;
2990}
2991
2992
2993static PyObject*
2994DB_keys(DBObject* self, PyObject* args)
2995{
2996 PyObject* txnobj = NULL;
2997 DB_TXN *txn = NULL;
2998
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002999 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003000 return NULL;
3001 if (!checkTxnObj(txnobj, &txn))
3002 return NULL;
3003 return _DB_make_list(self, txn, _KEYS_LIST);
3004}
3005
3006
3007static PyObject*
3008DB_items(DBObject* self, PyObject* args)
3009{
3010 PyObject* txnobj = NULL;
3011 DB_TXN *txn = NULL;
3012
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003013 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003014 return NULL;
3015 if (!checkTxnObj(txnobj, &txn))
3016 return NULL;
3017 return _DB_make_list(self, txn, _ITEMS_LIST);
3018}
3019
3020
3021static PyObject*
3022DB_values(DBObject* self, PyObject* args)
3023{
3024 PyObject* txnobj = NULL;
3025 DB_TXN *txn = NULL;
3026
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003027 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 return NULL;
3029 if (!checkTxnObj(txnobj, &txn))
3030 return NULL;
3031 return _DB_make_list(self, txn, _VALUES_LIST);
3032}
3033
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003034/* --------------------------------------------------------------------- */
3035/* DBCursor methods */
3036
3037
3038static PyObject*
3039DBC_close(DBCursorObject* self, PyObject* args)
3040{
3041 int err = 0;
3042
3043 if (!PyArg_ParseTuple(args, ":close"))
3044 return NULL;
3045
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046 if (self->dbc != NULL) {
3047 MYDB_BEGIN_ALLOW_THREADS;
3048 err = self->dbc->c_close(self->dbc);
3049 self->dbc = NULL;
3050 MYDB_END_ALLOW_THREADS;
3051 }
3052 RETURN_IF_ERR();
3053 RETURN_NONE();
3054}
3055
3056
3057static PyObject*
3058DBC_count(DBCursorObject* self, PyObject* args)
3059{
3060 int err = 0;
3061 db_recno_t count;
3062 int flags = 0;
3063
3064 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3065 return NULL;
3066
3067 CHECK_CURSOR_NOT_CLOSED(self);
3068
3069 MYDB_BEGIN_ALLOW_THREADS;
3070 err = self->dbc->c_count(self->dbc, &count, flags);
3071 MYDB_END_ALLOW_THREADS;
3072 RETURN_IF_ERR();
3073
Christian Heimes217cfd12007-12-02 14:31:20 +00003074 return PyLong_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003075}
3076
3077
3078static PyObject*
3079DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3080{
3081 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3082}
3083
3084
3085static PyObject*
3086DBC_delete(DBCursorObject* self, PyObject* args)
3087{
3088 int err, flags=0;
3089
3090 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3091 return NULL;
3092
3093 CHECK_CURSOR_NOT_CLOSED(self);
3094
3095 MYDB_BEGIN_ALLOW_THREADS;
3096 err = self->dbc->c_del(self->dbc, flags);
3097 MYDB_END_ALLOW_THREADS;
3098 RETURN_IF_ERR();
3099
3100 self->mydb->haveStat = 0;
3101 RETURN_NONE();
3102}
3103
3104
3105static PyObject*
3106DBC_dup(DBCursorObject* self, PyObject* args)
3107{
3108 int err, flags =0;
3109 DBC* dbc = NULL;
3110
3111 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3112 return NULL;
3113
3114 CHECK_CURSOR_NOT_CLOSED(self);
3115
3116 MYDB_BEGIN_ALLOW_THREADS;
3117 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3118 MYDB_END_ALLOW_THREADS;
3119 RETURN_IF_ERR();
3120
3121 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3122}
3123
3124static PyObject*
3125DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3126{
3127 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3128}
3129
3130
3131static PyObject*
3132DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3133{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003134 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003135 PyObject* keyobj = NULL;
3136 PyObject* dataobj = NULL;
3137 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003138 Py_buffer* data_buf_view = NULL;
3139 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003140 int dlen = -1;
3141 int doff = -1;
3142 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003143 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003144 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145
3146 CLEAR_DBT(key);
3147 CLEAR_DBT(data);
3148 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003149 &flags, &dlen, &doff))
3150 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3153 &kwnames[1],
3154 &keyobj, &flags, &dlen, &doff))
3155 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003157 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3158 kwnames, &keyobj, &dataobj,
3159 &flags, &dlen, &doff))
3160 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003161 return NULL;
3162 }
3163 }
3164 }
3165
3166 CHECK_CURSOR_NOT_CLOSED(self);
3167
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003168 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003170 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003171 (!add_partial_dbt(&data, dlen, doff)) )
3172 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003173 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3174 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003175 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003176 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177
3178 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3179 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003180 if (!(key.flags & DB_DBT_REALLOC)) {
3181 key.flags |= DB_DBT_MALLOC;
3182 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003183 }
3184
3185 MYDB_BEGIN_ALLOW_THREADS;
3186 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3187 MYDB_END_ALLOW_THREADS;
3188
Gregory P. Smithe9477062005-06-04 06:46:59 +00003189 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3190 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191 Py_INCREF(Py_None);
3192 retval = Py_None;
3193 }
3194 else if (makeDBError(err)) {
3195 retval = NULL;
3196 }
3197 else {
3198 switch (_DB_get_type(self->mydb)) {
3199 case -1:
3200 retval = NULL;
3201 break;
3202 case DB_BTREE:
3203 case DB_HASH:
3204 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003205 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003206 data.data, data.size);
3207 break;
3208 case DB_RECNO:
3209 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003210 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003211 data.data, data.size);
3212 break;
3213 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003214 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003215 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003216 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3217 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 return retval;
3219}
3220
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003221#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003222static PyObject*
3223DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3224{
3225 int err, flags=0;
3226 PyObject* keyobj = NULL;
3227 PyObject* dataobj = NULL;
3228 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003229 Py_buffer* data_buf_view = NULL;
3230 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003231 int dlen = -1;
3232 int doff = -1;
3233 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003234 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3235 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003236
3237 CLEAR_DBT(key);
3238 CLEAR_DBT(data);
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3240 &flags, &dlen, &doff))
3241 {
3242 PyErr_Clear();
3243 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003244 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003245 &keyobj, &flags, &dlen, &doff))
3246 {
3247 PyErr_Clear();
3248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3249 kwnames, &keyobj, &dataobj,
3250 &flags, &dlen, &doff))
3251 {
3252 return NULL;
3253 }
3254 }
3255 }
3256
3257 CHECK_CURSOR_NOT_CLOSED(self);
3258
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003259 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003260 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003261 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003262 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003263 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3264 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003265 return NULL;
3266 }
3267
3268 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3269 data.flags = DB_DBT_MALLOC;
3270 if (!(key.flags & DB_DBT_REALLOC)) {
3271 key.flags |= DB_DBT_MALLOC;
3272 }
3273 }
3274
3275 CLEAR_DBT(pkey);
3276 pkey.flags = DB_DBT_MALLOC;
3277
3278 MYDB_BEGIN_ALLOW_THREADS;
3279 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3280 MYDB_END_ALLOW_THREADS;
3281
Gregory P. Smithe9477062005-06-04 06:46:59 +00003282 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3283 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003284 Py_INCREF(Py_None);
3285 retval = Py_None;
3286 }
3287 else if (makeDBError(err)) {
3288 retval = NULL;
3289 }
3290 else {
3291 PyObject *pkeyObj;
3292 PyObject *dataObj;
Guido van Rossum98297ee2007-11-06 21:34:58 +00003293 dataObj = PyString_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003294
3295 if (self->mydb->primaryDBType == DB_RECNO ||
3296 self->mydb->primaryDBType == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003297 pkeyObj = PyLong_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003298 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003299 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003300
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003301 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302 {
3303 PyObject *keyObj;
3304 int type = _DB_get_type(self->mydb);
3305 if (type == DB_RECNO || type == DB_QUEUE)
Christian Heimes217cfd12007-12-02 14:31:20 +00003306 keyObj = PyLong_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003307 else
Guido van Rossum98297ee2007-11-06 21:34:58 +00003308 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003309 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003310 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003311 }
3312 else /* return just the pkey and data */
3313 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003314 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003316 Py_DECREF(dataObj);
3317 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003318 free_dbt(&pkey);
3319 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003320 }
3321 /* the only time REALLOC should be set is if we used an integer
3322 * key that make_key_dbt malloc'd for us. always free these. */
3323 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003324 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003325 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003326 free_buf_view(keyobj, key_buf_view);
3327 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003328 return retval;
3329}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003330#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003331
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003332
3333static PyObject*
3334DBC_get_recno(DBCursorObject* self, PyObject* args)
3335{
3336 int err;
3337 db_recno_t recno;
3338 DBT key;
3339 DBT data;
3340
3341 if (!PyArg_ParseTuple(args, ":get_recno"))
3342 return NULL;
3343
3344 CHECK_CURSOR_NOT_CLOSED(self);
3345
3346 CLEAR_DBT(key);
3347 CLEAR_DBT(data);
3348 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3349 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3350 data.flags = DB_DBT_MALLOC;
3351 key.flags = DB_DBT_MALLOC;
3352 }
3353
3354 MYDB_BEGIN_ALLOW_THREADS;
3355 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3356 MYDB_END_ALLOW_THREADS;
3357 RETURN_IF_ERR();
3358
3359 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003360 free_dbt(&key);
3361 free_dbt(&data);
Christian Heimes217cfd12007-12-02 14:31:20 +00003362 return PyLong_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003363}
3364
3365
3366static PyObject*
3367DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3368{
3369 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3370}
3371
3372
3373static PyObject*
3374DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3375{
3376 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3377}
3378
3379
3380static PyObject*
3381DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3382{
3383 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3384}
3385
3386
3387static PyObject*
3388DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3389{
3390 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003391 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003392 Py_buffer *data_buf_view = NULL;
3393 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003395 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003396 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003397 int dlen = -1;
3398 int doff = -1;
3399
3400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3401 &keyobj, &dataobj, &flags, &dlen, &doff))
3402 return NULL;
3403
3404 CHECK_CURSOR_NOT_CLOSED(self);
3405
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003406 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003407 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003408 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003409 !add_partial_dbt(&data, dlen, doff) )
3410 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003411 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3412 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003413 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003414 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415
3416 MYDB_BEGIN_ALLOW_THREADS;
3417 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3418 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003419 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3420 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003421 RETURN_IF_ERR();
3422 self->mydb->haveStat = 0;
3423 RETURN_NONE();
3424}
3425
3426
3427static PyObject*
3428DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3429{
3430 int err, flags = 0;
3431 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003432 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003433 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003434 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003435 int dlen = -1;
3436 int doff = -1;
3437
3438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3439 &keyobj, &flags, &dlen, &doff))
3440 return NULL;
3441
3442 CHECK_CURSOR_NOT_CLOSED(self);
3443
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003444 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 return NULL;
3446
3447 CLEAR_DBT(data);
3448 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3449 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3450 data.flags = DB_DBT_MALLOC;
3451 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003452 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003453 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003454 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003455 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003456
3457 MYDB_BEGIN_ALLOW_THREADS;
3458 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3459 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003460 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3461 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003462 Py_INCREF(Py_None);
3463 retval = Py_None;
3464 }
3465 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003466 retval = NULL;
3467 }
3468 else {
3469 switch (_DB_get_type(self->mydb)) {
3470 case -1:
3471 retval = NULL;
3472 break;
3473 case DB_BTREE:
3474 case DB_HASH:
3475 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003476 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477 data.data, data.size);
3478 break;
3479 case DB_RECNO:
3480 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003481 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 data.data, data.size);
3483 break;
3484 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003485 free_dbt(&data);
3486 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003487 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003488 /* the only time REALLOC should be set is if we used an integer
3489 * key that make_key_dbt malloc'd for us. always free these. */
3490 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003491 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003492 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003493 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494
3495 return retval;
3496}
3497
3498
3499static PyObject*
3500DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3501{
3502 int err, flags = 0;
3503 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003504 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003505 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003506 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003507 int dlen = -1;
3508 int doff = -1;
3509
3510 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3511 &keyobj, &flags, &dlen, &doff))
3512 return NULL;
3513
3514 CHECK_CURSOR_NOT_CLOSED(self);
3515
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003516 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003517 return NULL;
3518
3519 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003520 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003521 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003522 return NULL;
3523 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003524 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3525 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003526 data.flags |= DB_DBT_MALLOC;
3527 /* only BTREE databases will return anything in the key */
3528 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3529 key.flags |= DB_DBT_MALLOC;
3530 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003532 MYDB_BEGIN_ALLOW_THREADS;
3533 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3534 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003535 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3536 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003537 Py_INCREF(Py_None);
3538 retval = Py_None;
3539 }
3540 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003541 retval = NULL;
3542 }
3543 else {
3544 switch (_DB_get_type(self->mydb)) {
3545 case -1:
3546 retval = NULL;
3547 break;
3548 case DB_BTREE:
3549 case DB_HASH:
3550 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003551 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552 data.data, data.size);
3553 break;
3554 case DB_RECNO:
3555 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003556 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003557 data.data, data.size);
3558 break;
3559 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003560 free_dbt(&key);
3561 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003563 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003564 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003565 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003566 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003567 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003568 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003569
3570 return retval;
3571}
3572
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003574_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3575 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003576{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003577 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003579 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003580 Py_buffer *data_buf_view = NULL;
3581 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582
Gregory P. Smith7441e652003-11-03 21:35:31 +00003583 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003584 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003586 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3587 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003589 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003590
3591 MYDB_BEGIN_ALLOW_THREADS;
3592 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3593 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003594 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003595 Py_INCREF(Py_None);
3596 retval = Py_None;
3597 }
3598 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599 retval = NULL;
3600 }
3601 else {
3602 switch (_DB_get_type(self->mydb)) {
3603 case -1:
3604 retval = NULL;
3605 break;
3606 case DB_BTREE:
3607 case DB_HASH:
3608 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003609 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003610 data.data, data.size);
3611 break;
3612 case DB_RECNO:
3613 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003614 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003615 data.data, data.size);
3616 break;
3617 }
3618 }
3619
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003620 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3621 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003622 return retval;
3623}
3624
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003625static PyObject*
3626DBC_get_both(DBCursorObject* self, PyObject* args)
3627{
3628 int flags=0;
3629 PyObject *keyobj, *dataobj;
3630
3631 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3632 return NULL;
3633
Gregory P. Smith7441e652003-11-03 21:35:31 +00003634 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003635 CHECK_CURSOR_NOT_CLOSED(self);
3636
3637 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3638 self->mydb->moduleFlags.getReturnsNone);
3639}
3640
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003641/* Return size of entry */
3642static PyObject*
3643DBC_get_current_size(DBCursorObject* self, PyObject* args)
3644{
3645 int err, flags=DB_CURRENT;
3646 PyObject* retval = NULL;
3647 DBT key, data;
3648
3649 if (!PyArg_ParseTuple(args, ":get_current_size"))
3650 return NULL;
3651 CHECK_CURSOR_NOT_CLOSED(self);
3652 CLEAR_DBT(key);
3653 CLEAR_DBT(data);
3654
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003655 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003656 getting the record size. */
3657 data.flags = DB_DBT_USERMEM;
3658 data.ulen = 0;
3659 MYDB_BEGIN_ALLOW_THREADS;
3660 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3661 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003662 if (err == DB_BUFFER_SMALL || !err) {
3663 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Christian Heimes217cfd12007-12-02 14:31:20 +00003664 retval = PyLong_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003665 err = 0;
3666 }
3667
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003668 free_dbt(&key);
3669 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003670 RETURN_IF_ERR();
3671 return retval;
3672}
3673
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003674static PyObject*
3675DBC_set_both(DBCursorObject* self, PyObject* args)
3676{
3677 int flags=0;
3678 PyObject *keyobj, *dataobj;
3679
3680 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3681 return NULL;
3682
Gregory P. Smith7441e652003-11-03 21:35:31 +00003683 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003684 CHECK_CURSOR_NOT_CLOSED(self);
3685
3686 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3687 self->mydb->moduleFlags.cursorSetReturnsNone);
3688}
3689
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690
3691static PyObject*
3692DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3693{
3694 int err, irecno, flags=0;
3695 db_recno_t recno;
3696 DBT key, data;
3697 PyObject* retval;
3698 int dlen = -1;
3699 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003700 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701
3702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3703 &irecno, &flags, &dlen, &doff))
3704 return NULL;
3705
3706 CHECK_CURSOR_NOT_CLOSED(self);
3707
3708 CLEAR_DBT(key);
3709 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003710 /* use allocated space so DB will be able to realloc room for the real
3711 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 key.data = malloc(sizeof(db_recno_t));
3713 if (key.data == NULL) {
3714 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3715 return NULL;
3716 }
3717 key.size = sizeof(db_recno_t);
3718 key.ulen = key.size;
3719 memcpy(key.data, &recno, sizeof(db_recno_t));
3720 key.flags = DB_DBT_REALLOC;
3721
3722 CLEAR_DBT(data);
3723 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3724 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3725 data.flags = DB_DBT_MALLOC;
3726 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003727 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003728 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003729 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003730 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003731
3732 MYDB_BEGIN_ALLOW_THREADS;
3733 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3734 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003735 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3736 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003737 Py_INCREF(Py_None);
3738 retval = Py_None;
3739 }
3740 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003741 retval = NULL;
3742 }
3743 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003744 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003746 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003747 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003748 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749
3750 return retval;
3751}
3752
3753
3754static PyObject*
3755DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3756{
3757 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3758}
3759
3760
3761static PyObject*
3762DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3763{
3764 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3765}
3766
3767
3768static PyObject*
3769DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3770{
3771 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3772}
3773
3774
3775static PyObject*
3776DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3777{
3778 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3779}
3780
3781
3782static PyObject*
3783DBC_join_item(DBCursorObject* self, PyObject* args)
3784{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003785 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003786 DBT key, data;
3787 PyObject* retval;
3788
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003789 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790 return NULL;
3791
3792 CHECK_CURSOR_NOT_CLOSED(self);
3793
3794 CLEAR_DBT(key);
3795 CLEAR_DBT(data);
3796 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3797 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3798 key.flags = DB_DBT_MALLOC;
3799 }
3800
3801 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003802 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003803 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003804 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3805 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003806 Py_INCREF(Py_None);
3807 retval = Py_None;
3808 }
3809 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003810 retval = NULL;
3811 }
3812 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003813 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003814 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815 }
3816
3817 return retval;
3818}
3819
3820
3821
3822/* --------------------------------------------------------------------- */
3823/* DBEnv methods */
3824
3825
3826static PyObject*
3827DBEnv_close(DBEnvObject* self, PyObject* args)
3828{
3829 int err, flags = 0;
3830
3831 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3832 return NULL;
3833 if (!self->closed) { /* Don't close more than once */
3834 MYDB_BEGIN_ALLOW_THREADS;
3835 err = self->db_env->close(self->db_env, flags);
3836 MYDB_END_ALLOW_THREADS;
3837 /* after calling DBEnv->close, regardless of error, this DBEnv
3838 * may not be accessed again (BerkeleyDB docs). */
3839 self->closed = 1;
3840 self->db_env = NULL;
3841 RETURN_IF_ERR();
3842 }
3843 RETURN_NONE();
3844}
3845
3846
3847static PyObject*
3848DBEnv_open(DBEnvObject* self, PyObject* args)
3849{
3850 int err, flags=0, mode=0660;
3851 char *db_home;
3852
3853 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3854 return NULL;
3855
3856 CHECK_ENV_NOT_CLOSED(self);
3857
3858 MYDB_BEGIN_ALLOW_THREADS;
3859 err = self->db_env->open(self->db_env, db_home, flags, mode);
3860 MYDB_END_ALLOW_THREADS;
3861 RETURN_IF_ERR();
3862 self->closed = 0;
3863 self->flags = flags;
3864 RETURN_NONE();
3865}
3866
3867
3868static PyObject*
3869DBEnv_remove(DBEnvObject* self, PyObject* args)
3870{
3871 int err, flags=0;
3872 char *db_home;
3873
3874 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3875 return NULL;
3876 CHECK_ENV_NOT_CLOSED(self);
3877 MYDB_BEGIN_ALLOW_THREADS;
3878 err = self->db_env->remove(self->db_env, db_home, flags);
3879 MYDB_END_ALLOW_THREADS;
3880 RETURN_IF_ERR();
3881 RETURN_NONE();
3882}
3883
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003884#if (DBVER >= 41)
3885static PyObject*
3886DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3887{
3888 int err;
3889 u_int32_t flags=0;
3890 char *file = NULL;
3891 char *database = NULL;
3892 PyObject *txnobj = NULL;
3893 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003894 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003895 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003896
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003897 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003898 &file, &database, &txnobj, &flags)) {
3899 return NULL;
3900 }
3901 if (!checkTxnObj(txnobj, &txn)) {
3902 return NULL;
3903 }
3904 CHECK_ENV_NOT_CLOSED(self);
3905 MYDB_BEGIN_ALLOW_THREADS;
3906 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3910}
3911
3912static PyObject*
3913DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3914{
3915 int err;
3916 u_int32_t flags=0;
3917 char *file = NULL;
3918 char *database = NULL;
3919 char *newname = NULL;
3920 PyObject *txnobj = NULL;
3921 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003922 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003923 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003924
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003926 &file, &database, &newname, &txnobj, &flags)) {
3927 return NULL;
3928 }
3929 if (!checkTxnObj(txnobj, &txn)) {
3930 return NULL;
3931 }
3932 CHECK_ENV_NOT_CLOSED(self);
3933 MYDB_BEGIN_ALLOW_THREADS;
3934 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3935 flags);
3936 MYDB_END_ALLOW_THREADS;
3937 RETURN_IF_ERR();
3938 RETURN_NONE();
3939}
3940
3941static PyObject*
3942DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3943{
3944 int err;
3945 u_int32_t flags=0;
3946 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003947 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003948
3949 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3950 &passwd, &flags)) {
3951 return NULL;
3952 }
3953
3954 MYDB_BEGIN_ALLOW_THREADS;
3955 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3956 MYDB_END_ALLOW_THREADS;
3957
3958 RETURN_IF_ERR();
3959 RETURN_NONE();
3960}
3961#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003962
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003963#if (DBVER >= 40)
3964static PyObject*
3965DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3966{
3967 int err;
3968 u_int32_t flags=0;
3969 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003970 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003971
3972 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3973 &timeout, &flags)) {
3974 return NULL;
3975 }
3976
3977 MYDB_BEGIN_ALLOW_THREADS;
3978 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3979 MYDB_END_ALLOW_THREADS;
3980
3981 RETURN_IF_ERR();
3982 RETURN_NONE();
3983}
3984#endif /* DBVER >= 40 */
3985
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003986static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003987DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3988{
3989 int err;
3990 long shm_key = 0;
3991
3992 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3993 return NULL;
3994 CHECK_ENV_NOT_CLOSED(self);
3995
3996 err = self->db_env->set_shm_key(self->db_env, shm_key);
3997 RETURN_IF_ERR();
3998 RETURN_NONE();
3999}
4000
4001static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004002DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4003{
4004 int err, gbytes=0, bytes=0, ncache=0;
4005
4006 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4007 &gbytes, &bytes, &ncache))
4008 return NULL;
4009 CHECK_ENV_NOT_CLOSED(self);
4010
4011 MYDB_BEGIN_ALLOW_THREADS;
4012 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4013 MYDB_END_ALLOW_THREADS;
4014 RETURN_IF_ERR();
4015 RETURN_NONE();
4016}
4017
4018
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004019static PyObject*
4020DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4021{
4022 int err, flags=0, onoff=0;
4023
4024 if (!PyArg_ParseTuple(args, "ii:set_flags",
4025 &flags, &onoff))
4026 return NULL;
4027 CHECK_ENV_NOT_CLOSED(self);
4028
4029 MYDB_BEGIN_ALLOW_THREADS;
4030 err = self->db_env->set_flags(self->db_env, flags, onoff);
4031 MYDB_END_ALLOW_THREADS;
4032 RETURN_IF_ERR();
4033 RETURN_NONE();
4034}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004035
4036
4037static PyObject*
4038DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4039{
4040 int err;
4041 char *dir;
4042
4043 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4044 return NULL;
4045 CHECK_ENV_NOT_CLOSED(self);
4046
4047 MYDB_BEGIN_ALLOW_THREADS;
4048 err = self->db_env->set_data_dir(self->db_env, dir);
4049 MYDB_END_ALLOW_THREADS;
4050 RETURN_IF_ERR();
4051 RETURN_NONE();
4052}
4053
4054
4055static PyObject*
4056DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4057{
4058 int err, lg_bsize;
4059
4060 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4061 return NULL;
4062 CHECK_ENV_NOT_CLOSED(self);
4063
4064 MYDB_BEGIN_ALLOW_THREADS;
4065 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4066 MYDB_END_ALLOW_THREADS;
4067 RETURN_IF_ERR();
4068 RETURN_NONE();
4069}
4070
4071
4072static PyObject*
4073DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4074{
4075 int err;
4076 char *dir;
4077
4078 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4079 return NULL;
4080 CHECK_ENV_NOT_CLOSED(self);
4081
4082 MYDB_BEGIN_ALLOW_THREADS;
4083 err = self->db_env->set_lg_dir(self->db_env, dir);
4084 MYDB_END_ALLOW_THREADS;
4085 RETURN_IF_ERR();
4086 RETURN_NONE();
4087}
4088
4089static PyObject*
4090DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4091{
4092 int err, lg_max;
4093
4094 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4095 return NULL;
4096 CHECK_ENV_NOT_CLOSED(self);
4097
4098 MYDB_BEGIN_ALLOW_THREADS;
4099 err = self->db_env->set_lg_max(self->db_env, lg_max);
4100 MYDB_END_ALLOW_THREADS;
4101 RETURN_IF_ERR();
4102 RETURN_NONE();
4103}
4104
4105
Neal Norwitz84562352005-10-20 04:30:15 +00004106#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004107static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004108DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4109{
4110 int err, lg_max;
4111
4112 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4113 return NULL;
4114 CHECK_ENV_NOT_CLOSED(self);
4115
4116 MYDB_BEGIN_ALLOW_THREADS;
4117 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4118 MYDB_END_ALLOW_THREADS;
4119 RETURN_IF_ERR();
4120 RETURN_NONE();
4121}
Neal Norwitz84562352005-10-20 04:30:15 +00004122#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004123
4124
4125static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004126DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4127{
4128 int err, lk_detect;
4129
4130 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4131 return NULL;
4132 CHECK_ENV_NOT_CLOSED(self);
4133
4134 MYDB_BEGIN_ALLOW_THREADS;
4135 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4136 MYDB_END_ALLOW_THREADS;
4137 RETURN_IF_ERR();
4138 RETURN_NONE();
4139}
4140
4141
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004142#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004143static PyObject*
4144DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4145{
4146 int err, max;
4147
4148 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4149 return NULL;
4150 CHECK_ENV_NOT_CLOSED(self);
4151
4152 MYDB_BEGIN_ALLOW_THREADS;
4153 err = self->db_env->set_lk_max(self->db_env, max);
4154 MYDB_END_ALLOW_THREADS;
4155 RETURN_IF_ERR();
4156 RETURN_NONE();
4157}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004158#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004159
4160
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004161
4162static PyObject*
4163DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4164{
4165 int err, max;
4166
4167 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4168 return NULL;
4169 CHECK_ENV_NOT_CLOSED(self);
4170
4171 MYDB_BEGIN_ALLOW_THREADS;
4172 err = self->db_env->set_lk_max_locks(self->db_env, max);
4173 MYDB_END_ALLOW_THREADS;
4174 RETURN_IF_ERR();
4175 RETURN_NONE();
4176}
4177
4178
4179static PyObject*
4180DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4181{
4182 int err, max;
4183
4184 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4185 return NULL;
4186 CHECK_ENV_NOT_CLOSED(self);
4187
4188 MYDB_BEGIN_ALLOW_THREADS;
4189 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4190 MYDB_END_ALLOW_THREADS;
4191 RETURN_IF_ERR();
4192 RETURN_NONE();
4193}
4194
4195
4196static PyObject*
4197DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4198{
4199 int err, max;
4200
4201 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4202 return NULL;
4203 CHECK_ENV_NOT_CLOSED(self);
4204
4205 MYDB_BEGIN_ALLOW_THREADS;
4206 err = self->db_env->set_lk_max_objects(self->db_env, max);
4207 MYDB_END_ALLOW_THREADS;
4208 RETURN_IF_ERR();
4209 RETURN_NONE();
4210}
4211
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004212
4213static PyObject*
4214DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4215{
4216 int err, mp_mmapsize;
4217
4218 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4219 return NULL;
4220 CHECK_ENV_NOT_CLOSED(self);
4221
4222 MYDB_BEGIN_ALLOW_THREADS;
4223 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4224 MYDB_END_ALLOW_THREADS;
4225 RETURN_IF_ERR();
4226 RETURN_NONE();
4227}
4228
4229
4230static PyObject*
4231DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4232{
4233 int err;
4234 char *dir;
4235
4236 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4237 return NULL;
4238 CHECK_ENV_NOT_CLOSED(self);
4239
4240 MYDB_BEGIN_ALLOW_THREADS;
4241 err = self->db_env->set_tmp_dir(self->db_env, dir);
4242 MYDB_END_ALLOW_THREADS;
4243 RETURN_IF_ERR();
4244 RETURN_NONE();
4245}
4246
4247
4248static PyObject*
4249DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4250{
4251 int flags = 0;
4252 PyObject* txnobj = NULL;
4253 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004254 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004255
4256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4257 &txnobj, &flags))
4258 return NULL;
4259
4260 if (!checkTxnObj(txnobj, &txn))
4261 return NULL;
4262 CHECK_ENV_NOT_CLOSED(self);
4263
4264 return (PyObject*)newDBTxnObject(self, txn, flags);
4265}
4266
4267
4268static PyObject*
4269DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4270{
4271 int err, kbyte=0, min=0, flags=0;
4272
4273 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4274 return NULL;
4275 CHECK_ENV_NOT_CLOSED(self);
4276
4277 MYDB_BEGIN_ALLOW_THREADS;
4278#if (DBVER >= 40)
4279 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4280#else
4281 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4282#endif
4283 MYDB_END_ALLOW_THREADS;
4284 RETURN_IF_ERR();
4285 RETURN_NONE();
4286}
4287
4288
4289static PyObject*
4290DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4291{
4292 int err, max;
4293
4294 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4295 return NULL;
4296 CHECK_ENV_NOT_CLOSED(self);
4297
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004298 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004299 RETURN_IF_ERR();
4300 RETURN_NONE();
4301}
4302
4303
4304static PyObject*
4305DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4306{
4307 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004308 long stamp;
4309 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004310
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004311 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004312 return NULL;
4313 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004314 timestamp = (time_t)stamp;
4315 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004316 RETURN_IF_ERR();
4317 RETURN_NONE();
4318}
4319
4320
4321static PyObject*
4322DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4323{
4324 int err, atype, flags=0;
4325 int aborted = 0;
4326
4327 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4328 return NULL;
4329 CHECK_ENV_NOT_CLOSED(self);
4330
4331 MYDB_BEGIN_ALLOW_THREADS;
4332#if (DBVER >= 40)
4333 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4334#else
4335 err = lock_detect(self->db_env, flags, atype, &aborted);
4336#endif
4337 MYDB_END_ALLOW_THREADS;
4338 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00004339 return PyLong_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004340}
4341
4342
4343static PyObject*
4344DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4345{
4346 int flags=0;
4347 int locker, lock_mode;
4348 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004349 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004350 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004351
4352 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4353 return NULL;
4354
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004355 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004356 return NULL;
4357
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004358 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4359 free_buf_view(objobj, obj_buf_view);
4360 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004361}
4362
4363
4364static PyObject*
4365DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4366{
4367 int err;
4368 u_int32_t theID;
4369
4370 if (!PyArg_ParseTuple(args, ":lock_id"))
4371 return NULL;
4372
4373 CHECK_ENV_NOT_CLOSED(self);
4374 MYDB_BEGIN_ALLOW_THREADS;
4375#if (DBVER >= 40)
4376 err = self->db_env->lock_id(self->db_env, &theID);
4377#else
4378 err = lock_id(self->db_env, &theID);
4379#endif
4380 MYDB_END_ALLOW_THREADS;
4381 RETURN_IF_ERR();
4382
Christian Heimes217cfd12007-12-02 14:31:20 +00004383 return PyLong_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004384}
4385
Guido van Rossum77677112007-11-05 19:43:04 +00004386#if (DBVER >= 40)
4387static PyObject*
4388DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4389{
4390 int err;
4391 u_int32_t theID;
4392
4393 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4394 return NULL;
4395
4396 CHECK_ENV_NOT_CLOSED(self);
4397 MYDB_BEGIN_ALLOW_THREADS;
4398 err = self->db_env->lock_id_free(self->db_env, theID);
4399 MYDB_END_ALLOW_THREADS;
4400 RETURN_IF_ERR();
4401 RETURN_NONE();
4402}
4403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004404
4405static PyObject*
4406DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4407{
4408 int err;
4409 DBLockObject* dblockobj;
4410
4411 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4412 return NULL;
4413
4414 CHECK_ENV_NOT_CLOSED(self);
4415 MYDB_BEGIN_ALLOW_THREADS;
4416#if (DBVER >= 40)
4417 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4418#else
4419 err = lock_put(self->db_env, &dblockobj->lock);
4420#endif
4421 MYDB_END_ALLOW_THREADS;
4422 RETURN_IF_ERR();
4423 RETURN_NONE();
4424}
4425
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004426#if (DBVER >= 44)
4427static PyObject*
4428DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4429{
4430 int err;
4431 char *file;
4432 u_int32_t flags = 0;
4433 static char* kwnames[] = { "file", "flags", NULL};
4434
4435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4436 &file, &flags))
4437 return NULL;
4438 CHECK_ENV_NOT_CLOSED(self);
4439
4440 MYDB_BEGIN_ALLOW_THREADS;
4441 err = self->db_env->lsn_reset(self->db_env, file, flags);
4442 MYDB_END_ALLOW_THREADS;
4443 RETURN_IF_ERR();
4444 RETURN_NONE();
4445}
4446#endif /* DBVER >= 4.4 */
4447
4448#if (DBVER >= 40)
4449static PyObject*
4450DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4451{
4452 int err;
4453 DB_LOG_STAT* statp = NULL;
4454 PyObject* d = NULL;
4455 u_int32_t flags = 0;
4456
4457 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4458 return NULL;
4459 CHECK_ENV_NOT_CLOSED(self);
4460
4461 MYDB_BEGIN_ALLOW_THREADS;
4462 err = self->db_env->log_stat(self->db_env, &statp, flags);
4463 MYDB_END_ALLOW_THREADS;
4464 RETURN_IF_ERR();
4465
4466 /* Turn the stat structure into a dictionary */
4467 d = PyDict_New();
4468 if (d == NULL) {
4469 if (statp)
4470 free(statp);
4471 return NULL;
4472 }
4473
4474#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4475
4476 MAKE_ENTRY(magic);
4477 MAKE_ENTRY(version);
4478 MAKE_ENTRY(mode);
4479 MAKE_ENTRY(lg_bsize);
4480#if (DBVER >= 44)
4481 MAKE_ENTRY(lg_size);
4482 MAKE_ENTRY(record);
4483#endif
4484#if (DBVER <= 40)
4485 MAKE_ENTRY(lg_max);
4486#endif
4487 MAKE_ENTRY(w_mbytes);
4488 MAKE_ENTRY(w_bytes);
4489 MAKE_ENTRY(wc_mbytes);
4490 MAKE_ENTRY(wc_bytes);
4491 MAKE_ENTRY(wcount);
4492 MAKE_ENTRY(wcount_fill);
4493#if (DBVER >= 44)
4494 MAKE_ENTRY(rcount);
4495#endif
4496 MAKE_ENTRY(scount);
4497 MAKE_ENTRY(cur_file);
4498 MAKE_ENTRY(cur_offset);
4499 MAKE_ENTRY(disk_file);
4500 MAKE_ENTRY(disk_offset);
4501 MAKE_ENTRY(maxcommitperflush);
4502 MAKE_ENTRY(mincommitperflush);
4503 MAKE_ENTRY(regsize);
4504 MAKE_ENTRY(region_wait);
4505 MAKE_ENTRY(region_nowait);
4506
4507#undef MAKE_ENTRY
4508 free(statp);
4509 return d;
4510} /* DBEnv_log_stat */
4511#endif /* DBVER >= 4.0 for log_stat method */
4512
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004513
4514static PyObject*
4515DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4516{
4517 int err;
4518 DB_LOCK_STAT* sp;
4519 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004520 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004521
4522 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4523 return NULL;
4524 CHECK_ENV_NOT_CLOSED(self);
4525
4526 MYDB_BEGIN_ALLOW_THREADS;
4527#if (DBVER >= 40)
4528 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4529#else
4530#if (DBVER >= 33)
4531 err = lock_stat(self->db_env, &sp);
4532#else
4533 err = lock_stat(self->db_env, &sp, NULL);
4534#endif
4535#endif
4536 MYDB_END_ALLOW_THREADS;
4537 RETURN_IF_ERR();
4538
4539 /* Turn the stat structure into a dictionary */
4540 d = PyDict_New();
4541 if (d == NULL) {
4542 free(sp);
4543 return NULL;
4544 }
4545
4546#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4547
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004548#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004549 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004550#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004551 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004552 MAKE_ENTRY(maxlocks);
4553 MAKE_ENTRY(maxlockers);
4554 MAKE_ENTRY(maxobjects);
4555 MAKE_ENTRY(nlocks);
4556 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004557 MAKE_ENTRY(nlockers);
4558 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 MAKE_ENTRY(nobjects);
4560 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561 MAKE_ENTRY(nrequests);
4562 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004563#if (DBVER < 44)
4564 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004565 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004566#else
4567 MAKE_ENTRY(lock_nowait);
4568 MAKE_ENTRY(lock_wait);
4569#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004570 MAKE_ENTRY(ndeadlocks);
4571 MAKE_ENTRY(regsize);
4572 MAKE_ENTRY(region_wait);
4573 MAKE_ENTRY(region_nowait);
4574
4575#undef MAKE_ENTRY
4576 free(sp);
4577 return d;
4578}
4579
4580
4581static PyObject*
4582DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4583{
4584 int flags=0;
4585 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004586 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 PyObject* list;
4588 PyObject* item = NULL;
4589
4590 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4591 return NULL;
4592
4593 CHECK_ENV_NOT_CLOSED(self);
4594 MYDB_BEGIN_ALLOW_THREADS;
4595#if (DBVER >= 40)
4596 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4597#elif (DBVER == 33)
4598 err = log_archive(self->db_env, &log_list, flags);
4599#else
4600 err = log_archive(self->db_env, &log_list, flags, NULL);
4601#endif
4602 MYDB_END_ALLOW_THREADS;
4603 RETURN_IF_ERR();
4604
4605 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004606 if (list == NULL) {
4607 if (log_list)
4608 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004609 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004611
4612 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004613 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004615 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004616 if (item == NULL) {
4617 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004618 list = NULL;
4619 break;
4620 }
4621 PyList_Append(list, item);
4622 Py_DECREF(item);
4623 }
4624 free(log_list_start);
4625 }
4626 return list;
4627}
4628
4629
4630static PyObject*
4631DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4632{
4633 int err;
4634 DB_TXN_STAT* sp;
4635 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004636 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004637
4638 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4639 return NULL;
4640 CHECK_ENV_NOT_CLOSED(self);
4641
4642 MYDB_BEGIN_ALLOW_THREADS;
4643#if (DBVER >= 40)
4644 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4645#elif (DBVER == 33)
4646 err = txn_stat(self->db_env, &sp);
4647#else
4648 err = txn_stat(self->db_env, &sp, NULL);
4649#endif
4650 MYDB_END_ALLOW_THREADS;
4651 RETURN_IF_ERR();
4652
4653 /* Turn the stat structure into a dictionary */
4654 d = PyDict_New();
4655 if (d == NULL) {
4656 free(sp);
4657 return NULL;
4658 }
4659
4660#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004661#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004662
Guido van Rossumd8faa362007-04-27 19:54:29 +00004663 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 MAKE_ENTRY(last_txnid);
4665 MAKE_ENTRY(maxtxns);
4666 MAKE_ENTRY(nactive);
4667 MAKE_ENTRY(maxnactive);
4668 MAKE_ENTRY(nbegins);
4669 MAKE_ENTRY(naborts);
4670 MAKE_ENTRY(ncommits);
4671 MAKE_ENTRY(regsize);
4672 MAKE_ENTRY(region_wait);
4673 MAKE_ENTRY(region_nowait);
4674
4675#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004676#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004677 free(sp);
4678 return d;
4679}
4680
4681
4682static PyObject*
4683DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4684{
4685 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004686 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687
4688 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4689 return NULL;
4690 CHECK_ENV_NOT_CLOSED(self);
4691
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004692 if (self->moduleFlags.getReturnsNone)
4693 ++oldValue;
4694 if (self->moduleFlags.cursorSetReturnsNone)
4695 ++oldValue;
4696 self->moduleFlags.getReturnsNone = (flags >= 1);
4697 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Christian Heimes217cfd12007-12-02 14:31:20 +00004698 return PyLong_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004699}
4700
4701
4702/* --------------------------------------------------------------------- */
4703/* DBTxn methods */
4704
4705
4706static PyObject*
4707DBTxn_commit(DBTxnObject* self, PyObject* args)
4708{
4709 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004710 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004711
4712 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4713 return NULL;
4714
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004715 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004716 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4717 "after txn_commit or txn_abort");
4718 PyErr_SetObject(DBError, t);
4719 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004720 return NULL;
4721 }
4722 txn = self->txn;
4723 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724 MYDB_BEGIN_ALLOW_THREADS;
4725#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004726 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004727#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004728 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004729#endif
4730 MYDB_END_ALLOW_THREADS;
4731 RETURN_IF_ERR();
4732 RETURN_NONE();
4733}
4734
4735static PyObject*
4736DBTxn_prepare(DBTxnObject* self, PyObject* args)
4737{
4738#if (DBVER >= 33)
4739 int err;
4740 char* gid=NULL;
4741 int gid_size=0;
4742
Gregory P. Smith361ed152007-08-23 07:32:27 +00004743 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004744 return NULL;
4745
4746 if (gid_size != DB_XIDDATASIZE) {
4747 PyErr_SetString(PyExc_TypeError,
4748 "gid must be DB_XIDDATASIZE bytes long");
4749 return NULL;
4750 }
4751
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004752 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004753 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4754 "after txn_commit or txn_abort");
4755 PyErr_SetObject(DBError, t);
4756 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004757 return NULL;
4758 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004759 MYDB_BEGIN_ALLOW_THREADS;
4760#if (DBVER >= 40)
4761 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4762#else
4763 err = txn_prepare(self->txn, (u_int8_t*)gid);
4764#endif
4765 MYDB_END_ALLOW_THREADS;
4766 RETURN_IF_ERR();
4767 RETURN_NONE();
4768#else
4769 int err;
4770
4771 if (!PyArg_ParseTuple(args, ":prepare"))
4772 return NULL;
4773
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004774 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004775 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4776 "after txn_commit or txn_abort");
4777 PyErr_SetObject(DBError, t);
4778 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004779 return NULL;
4780 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004781 MYDB_BEGIN_ALLOW_THREADS;
4782 err = txn_prepare(self->txn);
4783 MYDB_END_ALLOW_THREADS;
4784 RETURN_IF_ERR();
4785 RETURN_NONE();
4786#endif
4787}
4788
4789
4790static PyObject*
4791DBTxn_abort(DBTxnObject* self, PyObject* args)
4792{
4793 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004794 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004795
4796 if (!PyArg_ParseTuple(args, ":abort"))
4797 return NULL;
4798
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004799 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004800 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4801 "after txn_commit or txn_abort");
4802 PyErr_SetObject(DBError, t);
4803 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004804 return NULL;
4805 }
4806 txn = self->txn;
4807 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808 MYDB_BEGIN_ALLOW_THREADS;
4809#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004810 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004811#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004812 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813#endif
4814 MYDB_END_ALLOW_THREADS;
4815 RETURN_IF_ERR();
4816 RETURN_NONE();
4817}
4818
4819
4820static PyObject*
4821DBTxn_id(DBTxnObject* self, PyObject* args)
4822{
4823 int id;
4824
4825 if (!PyArg_ParseTuple(args, ":id"))
4826 return NULL;
4827
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004828 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004829 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4830 "after txn_commit or txn_abort");
4831 PyErr_SetObject(DBError, t);
4832 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004833 return NULL;
4834 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004835 MYDB_BEGIN_ALLOW_THREADS;
4836#if (DBVER >= 40)
4837 id = self->txn->id(self->txn);
4838#else
4839 id = txn_id(self->txn);
4840#endif
4841 MYDB_END_ALLOW_THREADS;
Christian Heimes217cfd12007-12-02 14:31:20 +00004842 return PyLong_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004843}
4844
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004845#if (DBVER >= 43)
4846/* --------------------------------------------------------------------- */
4847/* DBSequence methods */
4848
4849
4850static PyObject*
4851DBSequence_close(DBSequenceObject* self, PyObject* args)
4852{
4853 int err, flags=0;
4854 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4855 return NULL;
4856 CHECK_SEQUENCE_NOT_CLOSED(self)
4857
4858 MYDB_BEGIN_ALLOW_THREADS
4859 err = self->sequence->close(self->sequence, flags);
4860 self->sequence = NULL;
4861 MYDB_END_ALLOW_THREADS
4862
4863 RETURN_IF_ERR();
4864
4865 RETURN_NONE();
4866}
4867
4868static PyObject*
4869DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4870{
4871 int err, flags = 0;
4872 int delta = 1;
4873 db_seq_t value;
4874 PyObject *txnobj = NULL;
4875 DB_TXN *txn = NULL;
4876 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4877 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4878 return NULL;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880
4881 if (!checkTxnObj(txnobj, &txn))
4882 return NULL;
4883
4884 MYDB_BEGIN_ALLOW_THREADS
4885 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4886 MYDB_END_ALLOW_THREADS
4887
4888 RETURN_IF_ERR();
4889 return PyLong_FromLongLong(value);
4890
4891}
4892
4893static PyObject*
4894DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4895{
4896 if (!PyArg_ParseTuple(args,":get_dbp"))
4897 return NULL;
4898 CHECK_SEQUENCE_NOT_CLOSED(self)
4899 Py_INCREF(self->mydb);
4900 return (PyObject* )self->mydb;
4901}
4902
4903static PyObject*
4904DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4905{
4906 int err;
4907 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00004908 PyObject *retval = NULL;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004909 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004910 CHECK_SEQUENCE_NOT_CLOSED(self)
4911 MYDB_BEGIN_ALLOW_THREADS
4912 err = self->sequence->get_key(self->sequence, &key);
4913 MYDB_END_ALLOW_THREADS
4914
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004915 if (!err)
Guido van Rossum98297ee2007-11-06 21:34:58 +00004916 retval = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004917
4918 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004919 RETURN_IF_ERR();
4920
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00004921 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004922}
4923
4924static PyObject*
4925DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4926{
4927 int err;
4928 db_seq_t value;
4929 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4930 return NULL;
4931 CHECK_SEQUENCE_NOT_CLOSED(self)
4932
4933 MYDB_BEGIN_ALLOW_THREADS
4934 err = self->sequence->initial_value(self->sequence, value);
4935 MYDB_END_ALLOW_THREADS
4936
4937 RETURN_IF_ERR();
4938
4939 RETURN_NONE();
4940}
4941
4942static PyObject*
4943DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4944{
4945 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004946 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00004947 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004948 PyObject *txnobj = NULL;
4949 DB_TXN *txn = NULL;
4950 DBT key;
4951
4952 static char* kwnames[] = {"key", "txn", "flags", NULL };
4953 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4954 return NULL;
4955
4956 if (!checkTxnObj(txnobj, &txn))
4957 return NULL;
4958
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004959 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004960 return NULL;
4961
4962 MYDB_BEGIN_ALLOW_THREADS
4963 err = self->sequence->open(self->sequence, txn, &key, flags);
4964 MYDB_END_ALLOW_THREADS
4965
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004966 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004967 RETURN_IF_ERR();
4968
4969 RETURN_NONE();
4970}
4971
4972static PyObject*
4973DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4974{
4975 int err, flags = 0;
4976 PyObject *txnobj = NULL;
4977 DB_TXN *txn = NULL;
4978
4979 static char* kwnames[] = {"txn", "flags", NULL };
4980 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4981 return NULL;
4982
4983 if (!checkTxnObj(txnobj, &txn))
4984 return NULL;
4985
4986 CHECK_SEQUENCE_NOT_CLOSED(self)
4987
4988 MYDB_BEGIN_ALLOW_THREADS
4989 err = self->sequence->remove(self->sequence, txn, flags);
4990 MYDB_END_ALLOW_THREADS
4991
4992 RETURN_IF_ERR();
4993 RETURN_NONE();
4994}
4995
4996static PyObject*
4997DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4998{
4999 int err, size;
5000 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5001 return NULL;
5002 CHECK_SEQUENCE_NOT_CLOSED(self)
5003
5004 MYDB_BEGIN_ALLOW_THREADS
5005 err = self->sequence->set_cachesize(self->sequence, size);
5006 MYDB_END_ALLOW_THREADS
5007
5008 RETURN_IF_ERR();
5009 RETURN_NONE();
5010}
5011
5012static PyObject*
5013DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5014{
5015 int err, size;
5016 if (!PyArg_ParseTuple(args,":get_cachesize"))
5017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5019
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->get_cachesize(self->sequence, &size);
5022 MYDB_END_ALLOW_THREADS
5023
5024 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005025 return PyLong_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005026}
5027
5028static PyObject*
5029DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5030{
5031 int err, flags = 0;
5032 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5033 return NULL;
5034 CHECK_SEQUENCE_NOT_CLOSED(self)
5035
5036 MYDB_BEGIN_ALLOW_THREADS
5037 err = self->sequence->set_flags(self->sequence, flags);
5038 MYDB_END_ALLOW_THREADS
5039
5040 RETURN_IF_ERR();
5041 RETURN_NONE();
5042
5043}
5044
5045static PyObject*
5046DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5047{
5048 unsigned int flags;
5049 int err;
5050 if (!PyArg_ParseTuple(args,":get_flags"))
5051 return NULL;
5052 CHECK_SEQUENCE_NOT_CLOSED(self)
5053
5054 MYDB_BEGIN_ALLOW_THREADS
5055 err = self->sequence->get_flags(self->sequence, &flags);
5056 MYDB_END_ALLOW_THREADS
5057
5058 RETURN_IF_ERR();
Christian Heimes217cfd12007-12-02 14:31:20 +00005059 return PyLong_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005060}
5061
5062static PyObject*
5063DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5064{
5065 int err;
5066 db_seq_t min, max;
5067 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5068 return NULL;
5069 CHECK_SEQUENCE_NOT_CLOSED(self)
5070
5071 MYDB_BEGIN_ALLOW_THREADS
5072 err = self->sequence->set_range(self->sequence, min, max);
5073 MYDB_END_ALLOW_THREADS
5074
5075 RETURN_IF_ERR();
5076 RETURN_NONE();
5077}
5078
5079static PyObject*
5080DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5081{
5082 int err;
5083 db_seq_t min, max;
5084 if (!PyArg_ParseTuple(args,":get_range"))
5085 return NULL;
5086 CHECK_SEQUENCE_NOT_CLOSED(self)
5087
5088 MYDB_BEGIN_ALLOW_THREADS
5089 err = self->sequence->get_range(self->sequence, &min, &max);
5090 MYDB_END_ALLOW_THREADS
5091
5092 RETURN_IF_ERR();
5093 return Py_BuildValue("(LL)", min, max);
5094}
5095
5096static PyObject*
5097DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5098{
5099 int err, flags = 0;
5100 DB_SEQUENCE_STAT* sp = NULL;
5101 PyObject* dict_stat;
5102 static char* kwnames[] = {"flags", NULL };
5103 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5104 return NULL;
5105 CHECK_SEQUENCE_NOT_CLOSED(self);
5106
5107 MYDB_BEGIN_ALLOW_THREADS;
5108 err = self->sequence->stat(self->sequence, &sp, flags);
5109 MYDB_END_ALLOW_THREADS;
5110 RETURN_IF_ERR();
5111
5112 if ((dict_stat = PyDict_New()) == NULL) {
5113 free(sp);
5114 return NULL;
5115 }
5116
5117
5118#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5119#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5120
5121 MAKE_INT_ENTRY(wait);
5122 MAKE_INT_ENTRY(nowait);
5123 MAKE_LONG_LONG_ENTRY(current);
5124 MAKE_LONG_LONG_ENTRY(value);
5125 MAKE_LONG_LONG_ENTRY(last_value);
5126 MAKE_LONG_LONG_ENTRY(min);
5127 MAKE_LONG_LONG_ENTRY(max);
5128 MAKE_INT_ENTRY(cache_size);
5129 MAKE_INT_ENTRY(flags);
5130
5131#undef MAKE_INT_ENTRY
5132#undef MAKE_LONG_LONG_ENTRY
5133
5134 free(sp);
5135 return dict_stat;
5136}
5137#endif
5138
5139
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005140/* --------------------------------------------------------------------- */
5141/* Method definition tables and type objects */
5142
5143static PyMethodDef DB_methods[] = {
5144 {"append", (PyCFunction)DB_append, METH_VARARGS},
5145#if (DBVER >= 33)
5146 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5147#endif
5148 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005149 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5150 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005151 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5152 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5153 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5154 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005155#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005156 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005157#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5159 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5160 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5161 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5162 {"join", (PyCFunction)DB_join, METH_VARARGS},
5163 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5164 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5165 {"items", (PyCFunction)DB_items, METH_VARARGS},
5166 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5167 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5168 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5169 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5170 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5171 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005172#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005173 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005174#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005175 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005176#if (DBVER >= 41)
5177 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5178#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005179 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5180 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5181 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5182 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5183 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5184 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5185 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5186 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5187 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005188 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005189 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005190 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5191#if (DBVER >= 33)
5192 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5193#endif
5194 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5195 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5196 {"values", (PyCFunction)DB_values, METH_VARARGS},
5197 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5198 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5199 {NULL, NULL} /* sentinel */
5200};
5201
5202
5203static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005204 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005205 (binaryfunc)DB_subscript, /*mp_subscript*/
5206 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5207};
5208
5209
5210static PyMethodDef DBCursor_methods[] = {
5211 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5212 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5213 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5214 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5215 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5216 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5217 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005218#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005219 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005220#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005221 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5222 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5223 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5224 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5225 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5226 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5227 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5228 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005229 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005230 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005231 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5232 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5233 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5234 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5235 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5236 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5237 {NULL, NULL} /* sentinel */
5238};
5239
5240
5241static PyMethodDef DBEnv_methods[] = {
5242 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5243 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5244 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005245#if (DBVER >= 41)
5246 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5247 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5248 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5249#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005250#if (DBVER >= 40)
5251 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5252#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005253 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005254 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5255 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005256 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005257 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5258 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5259 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005260#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005261 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005263 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005264#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005265 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005266#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005267 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5268 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5269 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005270 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5271 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5272 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5273 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5274 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5275 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005276 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005277 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5278 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5279 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00005280#if (DBVER >= 40)
5281 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5282#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005283 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5284 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5285 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005286#if (DBVER >= 40)
5287 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5288#endif
5289#if (DBVER >= 44)
5290 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5291#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005292 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5293 {NULL, NULL} /* sentinel */
5294};
5295
5296
5297static PyMethodDef DBTxn_methods[] = {
5298 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5299 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5300 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5301 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5302 {NULL, NULL} /* sentinel */
5303};
5304
5305
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005306#if (DBVER >= 43)
5307static PyMethodDef DBSequence_methods[] = {
5308 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5309 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5310 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5311 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5312 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5313 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5314 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5315 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5316 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5317 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5318 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5319 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5320 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5321 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5322 {NULL, NULL} /* sentinel */
5323};
5324#endif
5325
5326
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005327static PyObject*
5328DB_getattr(DBObject* self, char *name)
5329{
5330 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5331}
5332
5333
5334static PyObject*
5335DBEnv_getattr(DBEnvObject* self, char *name)
5336{
5337 if (!strcmp(name, "db_home")) {
5338 CHECK_ENV_NOT_CLOSED(self);
5339 if (self->db_env->db_home == NULL) {
5340 RETURN_NONE();
5341 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005342 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005343 }
5344
5345 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5346}
5347
5348
5349static PyObject*
5350DBCursor_getattr(DBCursorObject* self, char *name)
5351{
5352 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5353}
5354
5355static PyObject*
5356DBTxn_getattr(DBTxnObject* self, char *name)
5357{
5358 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5359}
5360
5361static PyObject*
5362DBLock_getattr(DBLockObject* self, char *name)
5363{
5364 return NULL;
5365}
5366
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005367#if (DBVER >= 43)
5368static PyObject*
5369DBSequence_getattr(DBSequenceObject* self, char *name)
5370{
5371 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5372}
5373#endif
5374
Neal Norwitz227b5332006-03-22 09:28:35 +00005375static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005376 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005377 "DB", /*tp_name*/
5378 sizeof(DBObject), /*tp_basicsize*/
5379 0, /*tp_itemsize*/
5380 /* methods */
5381 (destructor)DB_dealloc, /*tp_dealloc*/
5382 0, /*tp_print*/
5383 (getattrfunc)DB_getattr, /*tp_getattr*/
5384 0, /*tp_setattr*/
5385 0, /*tp_compare*/
5386 0, /*tp_repr*/
5387 0, /*tp_as_number*/
5388 0, /*tp_as_sequence*/
5389 &DB_mapping,/*tp_as_mapping*/
5390 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005391 0, /* tp_call */
5392 0, /* tp_str */
5393 0, /* tp_getattro */
5394 0, /* tp_setattro */
5395 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005396 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005397 0, /* tp_doc */
5398 0, /* tp_traverse */
5399 0, /* tp_clear */
5400 0, /* tp_richcompare */
5401 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005402};
5403
5404
Neal Norwitz227b5332006-03-22 09:28:35 +00005405static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005406 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005407 "DBCursor", /*tp_name*/
5408 sizeof(DBCursorObject), /*tp_basicsize*/
5409 0, /*tp_itemsize*/
5410 /* methods */
5411 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5412 0, /*tp_print*/
5413 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5414 0, /*tp_setattr*/
5415 0, /*tp_compare*/
5416 0, /*tp_repr*/
5417 0, /*tp_as_number*/
5418 0, /*tp_as_sequence*/
5419 0, /*tp_as_mapping*/
5420 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005421 0, /* tp_call */
5422 0, /* tp_str */
5423 0, /* tp_getattro */
5424 0, /* tp_setattro */
5425 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005426 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005427 0, /* tp_doc */
5428 0, /* tp_traverse */
5429 0, /* tp_clear */
5430 0, /* tp_richcompare */
5431 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005432};
5433
5434
Neal Norwitz227b5332006-03-22 09:28:35 +00005435static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005436 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005437 "DBEnv", /*tp_name*/
5438 sizeof(DBEnvObject), /*tp_basicsize*/
5439 0, /*tp_itemsize*/
5440 /* methods */
5441 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5442 0, /*tp_print*/
5443 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5444 0, /*tp_setattr*/
5445 0, /*tp_compare*/
5446 0, /*tp_repr*/
5447 0, /*tp_as_number*/
5448 0, /*tp_as_sequence*/
5449 0, /*tp_as_mapping*/
5450 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005451 0, /* tp_call */
5452 0, /* tp_str */
5453 0, /* tp_getattro */
5454 0, /* tp_setattro */
5455 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005456 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005457 0, /* tp_doc */
5458 0, /* tp_traverse */
5459 0, /* tp_clear */
5460 0, /* tp_richcompare */
5461 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005462};
5463
Neal Norwitz227b5332006-03-22 09:28:35 +00005464static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005465 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005466 "DBTxn", /*tp_name*/
5467 sizeof(DBTxnObject), /*tp_basicsize*/
5468 0, /*tp_itemsize*/
5469 /* methods */
5470 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5471 0, /*tp_print*/
5472 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5473 0, /*tp_setattr*/
5474 0, /*tp_compare*/
5475 0, /*tp_repr*/
5476 0, /*tp_as_number*/
5477 0, /*tp_as_sequence*/
5478 0, /*tp_as_mapping*/
5479 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005480 0, /* tp_call */
5481 0, /* tp_str */
5482 0, /* tp_getattro */
5483 0, /* tp_setattro */
5484 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005485 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005486 0, /* tp_doc */
5487 0, /* tp_traverse */
5488 0, /* tp_clear */
5489 0, /* tp_richcompare */
5490 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005491};
5492
5493
Neal Norwitz227b5332006-03-22 09:28:35 +00005494static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005495 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005496 "DBLock", /*tp_name*/
5497 sizeof(DBLockObject), /*tp_basicsize*/
5498 0, /*tp_itemsize*/
5499 /* methods */
5500 (destructor)DBLock_dealloc, /*tp_dealloc*/
5501 0, /*tp_print*/
5502 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5503 0, /*tp_setattr*/
5504 0, /*tp_compare*/
5505 0, /*tp_repr*/
5506 0, /*tp_as_number*/
5507 0, /*tp_as_sequence*/
5508 0, /*tp_as_mapping*/
5509 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005510 0, /* tp_call */
5511 0, /* tp_str */
5512 0, /* tp_getattro */
5513 0, /* tp_setattro */
5514 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005515 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005516 0, /* tp_doc */
5517 0, /* tp_traverse */
5518 0, /* tp_clear */
5519 0, /* tp_richcompare */
5520 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005521};
5522
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005523#if (DBVER >= 43)
5524static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005525 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005526 "DBSequence", /*tp_name*/
5527 sizeof(DBSequenceObject), /*tp_basicsize*/
5528 0, /*tp_itemsize*/
5529 /* methods */
5530 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5531 0, /*tp_print*/
5532 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5533 0, /*tp_setattr*/
5534 0, /*tp_compare*/
5535 0, /*tp_repr*/
5536 0, /*tp_as_number*/
5537 0, /*tp_as_sequence*/
5538 0, /*tp_as_mapping*/
5539 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005540 0, /* tp_call */
5541 0, /* tp_str */
5542 0, /* tp_getattro */
5543 0, /* tp_setattro */
5544 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005545 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005546 0, /* tp_doc */
5547 0, /* tp_traverse */
5548 0, /* tp_clear */
5549 0, /* tp_richcompare */
5550 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005551};
5552#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005553
5554/* --------------------------------------------------------------------- */
5555/* Module-level functions */
5556
5557static PyObject*
5558DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5559{
5560 PyObject* dbenvobj = NULL;
5561 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005562 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005563
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5565 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005566 return NULL;
5567 if (dbenvobj == Py_None)
5568 dbenvobj = NULL;
5569 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5570 makeTypeError("DBEnv", dbenvobj);
5571 return NULL;
5572 }
5573
5574 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5575}
5576
5577
5578static PyObject*
5579DBEnv_construct(PyObject* self, PyObject* args)
5580{
5581 int flags = 0;
5582 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5583 return (PyObject* )newDBEnvObject(flags);
5584}
5585
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005586#if (DBVER >= 43)
5587static PyObject*
5588DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5589{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005590 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005591 int flags = 0;
5592 static char* kwnames[] = { "db", "flags", NULL};
5593
5594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5595 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005596 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005597 makeTypeError("DB", dbobj);
5598 return NULL;
5599 }
5600 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5601}
5602#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005603
5604static char bsddb_version_doc[] =
5605"Returns a tuple of major, minor, and patch release numbers of the\n\
5606underlying DB library.";
5607
5608static PyObject*
5609bsddb_version(PyObject* self, PyObject* args)
5610{
5611 int major, minor, patch;
5612
5613 if (!PyArg_ParseTuple(args, ":version"))
5614 return NULL;
5615 db_version(&major, &minor, &patch);
5616 return Py_BuildValue("(iii)", major, minor, patch);
5617}
5618
5619
5620/* List of functions defined in the module */
5621
5622static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005623 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5624 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5625#if (DBVER >= 43)
5626 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5627#endif
5628 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005629 {NULL, NULL} /* sentinel */
5630};
5631
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005632/* API structure */
5633static BSDDB_api bsddb_api;
5634
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005635
5636/* --------------------------------------------------------------------- */
5637/* Module initialization */
5638
5639
5640/* Convenience routine to export an integer value.
5641 * Errors are silently ignored, for better or for worse...
5642 */
5643#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5644
Gregory P. Smith41631e82003-09-21 00:08:14 +00005645#define MODULE_NAME_MAX_LEN 11
5646static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005647
Neal Norwitzf6657e62006-12-28 04:47:50 +00005648PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649{
5650 PyObject* m;
5651 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005652 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5653 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5654 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005655 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005656
5657 /* Initialize the type of the new type objects here; doing it here
5658 is required for portability to Windows without requiring C++. */
Christian Heimes90aa7642007-12-19 02:45:37 +00005659 Py_TYPE(&DB_Type) = &PyType_Type;
5660 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5661 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5662 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5663 Py_TYPE(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005664#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +00005665 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005666#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005667
5668
Mark Hammonda69d4092003-04-22 23:13:27 +00005669#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005670 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005671 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005672#endif
5673
5674 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005675 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005676 if (m == NULL)
5677 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005678
5679 /* Add some symbolic constants to the module */
5680 d = PyModule_GetDict(m);
5681 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005682 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005683 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5684 Py_DECREF(pybsddb_version_s);
5685 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005686 Py_DECREF(svnid_s);
5687 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005688 Py_DECREF(db_version_s);
5689 db_version_s = NULL;
5690
5691 ADD_INT(d, DB_VERSION_MAJOR);
5692 ADD_INT(d, DB_VERSION_MINOR);
5693 ADD_INT(d, DB_VERSION_PATCH);
5694
5695 ADD_INT(d, DB_MAX_PAGES);
5696 ADD_INT(d, DB_MAX_RECORDS);
5697
Gregory P. Smith41631e82003-09-21 00:08:14 +00005698#if (DBVER >= 42)
5699 ADD_INT(d, DB_RPCCLIENT);
5700#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005701 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005702 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5703 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5704#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005705 ADD_INT(d, DB_XA_CREATE);
5706
5707 ADD_INT(d, DB_CREATE);
5708 ADD_INT(d, DB_NOMMAP);
5709 ADD_INT(d, DB_THREAD);
5710
5711 ADD_INT(d, DB_FORCE);
5712 ADD_INT(d, DB_INIT_CDB);
5713 ADD_INT(d, DB_INIT_LOCK);
5714 ADD_INT(d, DB_INIT_LOG);
5715 ADD_INT(d, DB_INIT_MPOOL);
5716 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005717 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005718
5719 ADD_INT(d, DB_RECOVER);
5720 ADD_INT(d, DB_RECOVER_FATAL);
5721 ADD_INT(d, DB_TXN_NOSYNC);
5722 ADD_INT(d, DB_USE_ENVIRON);
5723 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5724
5725 ADD_INT(d, DB_LOCKDOWN);
5726 ADD_INT(d, DB_PRIVATE);
5727 ADD_INT(d, DB_SYSTEM_MEM);
5728
5729 ADD_INT(d, DB_TXN_SYNC);
5730 ADD_INT(d, DB_TXN_NOWAIT);
5731
5732 ADD_INT(d, DB_EXCL);
5733 ADD_INT(d, DB_FCNTL_LOCKING);
5734 ADD_INT(d, DB_ODDFILESIZE);
5735 ADD_INT(d, DB_RDWRMASTER);
5736 ADD_INT(d, DB_RDONLY);
5737 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005738 ADD_INT(d, DB_EXTENT);
5739 ADD_INT(d, DB_CDB_ALLDB);
5740 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005741 ADD_INT(d, DB_UPGRADE);
5742
5743 ADD_INT(d, DB_AGGRESSIVE);
5744 ADD_INT(d, DB_NOORDERCHK);
5745 ADD_INT(d, DB_ORDERCHKONLY);
5746 ADD_INT(d, DB_PR_PAGE);
5747#if ! (DBVER >= 33)
5748 ADD_INT(d, DB_VRFY_FLAGMASK);
5749 ADD_INT(d, DB_PR_HEADERS);
5750#endif
5751 ADD_INT(d, DB_PR_RECOVERYTEST);
5752 ADD_INT(d, DB_SALVAGE);
5753
5754 ADD_INT(d, DB_LOCK_NORUN);
5755 ADD_INT(d, DB_LOCK_DEFAULT);
5756 ADD_INT(d, DB_LOCK_OLDEST);
5757 ADD_INT(d, DB_LOCK_RANDOM);
5758 ADD_INT(d, DB_LOCK_YOUNGEST);
5759#if (DBVER >= 33)
5760 ADD_INT(d, DB_LOCK_MAXLOCKS);
5761 ADD_INT(d, DB_LOCK_MINLOCKS);
5762 ADD_INT(d, DB_LOCK_MINWRITE);
5763#endif
5764
5765
5766#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005767 /* docs say to use zero instead */
5768 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005769#else
5770 ADD_INT(d, DB_LOCK_CONFLICT);
5771#endif
5772
5773 ADD_INT(d, DB_LOCK_DUMP);
5774 ADD_INT(d, DB_LOCK_GET);
5775 ADD_INT(d, DB_LOCK_INHERIT);
5776 ADD_INT(d, DB_LOCK_PUT);
5777 ADD_INT(d, DB_LOCK_PUT_ALL);
5778 ADD_INT(d, DB_LOCK_PUT_OBJ);
5779
5780 ADD_INT(d, DB_LOCK_NG);
5781 ADD_INT(d, DB_LOCK_READ);
5782 ADD_INT(d, DB_LOCK_WRITE);
5783 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005784 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785 ADD_INT(d, DB_LOCK_IWRITE);
5786 ADD_INT(d, DB_LOCK_IREAD);
5787 ADD_INT(d, DB_LOCK_IWR);
5788#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005789#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005790 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005791#else
5792 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5793#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005794 ADD_INT(d, DB_LOCK_WWRITE);
5795#endif
5796
5797 ADD_INT(d, DB_LOCK_RECORD);
5798 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005800#if (DBVER >= 33)
5801 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5802#endif
5803
5804 ADD_INT(d, DB_LOCK_NOWAIT);
5805 ADD_INT(d, DB_LOCK_RECORD);
5806 ADD_INT(d, DB_LOCK_UPGRADE);
5807
5808#if (DBVER >= 33)
5809 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005810#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005811 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005813 ADD_INT(d, DB_LSTAT_FREE);
5814 ADD_INT(d, DB_LSTAT_HELD);
5815#if (DBVER == 33)
5816 ADD_INT(d, DB_LSTAT_NOGRANT);
5817#endif
5818 ADD_INT(d, DB_LSTAT_PENDING);
5819 ADD_INT(d, DB_LSTAT_WAITING);
5820#endif
5821
5822 ADD_INT(d, DB_ARCH_ABS);
5823 ADD_INT(d, DB_ARCH_DATA);
5824 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005825#if (DBVER >= 42)
5826 ADD_INT(d, DB_ARCH_REMOVE);
5827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005828
5829 ADD_INT(d, DB_BTREE);
5830 ADD_INT(d, DB_HASH);
5831 ADD_INT(d, DB_RECNO);
5832 ADD_INT(d, DB_QUEUE);
5833 ADD_INT(d, DB_UNKNOWN);
5834
5835 ADD_INT(d, DB_DUP);
5836 ADD_INT(d, DB_DUPSORT);
5837 ADD_INT(d, DB_RECNUM);
5838 ADD_INT(d, DB_RENUMBER);
5839 ADD_INT(d, DB_REVSPLITOFF);
5840 ADD_INT(d, DB_SNAPSHOT);
5841
5842 ADD_INT(d, DB_JOIN_NOSORT);
5843
5844 ADD_INT(d, DB_AFTER);
5845 ADD_INT(d, DB_APPEND);
5846 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005847#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005848 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005849#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005850#if (DBVER >= 41)
5851 _addIntToDict(d, "DB_CHECKPOINT", 0);
5852#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005853 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005854 ADD_INT(d, DB_CURLSN);
5855#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005856#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857 ADD_INT(d, DB_COMMIT);
5858#endif
5859 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005860 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005861 ADD_INT(d, DB_CURRENT);
5862#if (DBVER >= 33)
5863 ADD_INT(d, DB_FAST_STAT);
5864#endif
5865 ADD_INT(d, DB_FIRST);
5866 ADD_INT(d, DB_FLUSH);
5867 ADD_INT(d, DB_GET_BOTH);
5868 ADD_INT(d, DB_GET_RECNO);
5869 ADD_INT(d, DB_JOIN_ITEM);
5870 ADD_INT(d, DB_KEYFIRST);
5871 ADD_INT(d, DB_KEYLAST);
5872 ADD_INT(d, DB_LAST);
5873 ADD_INT(d, DB_NEXT);
5874 ADD_INT(d, DB_NEXT_DUP);
5875 ADD_INT(d, DB_NEXT_NODUP);
5876 ADD_INT(d, DB_NODUPDATA);
5877 ADD_INT(d, DB_NOOVERWRITE);
5878 ADD_INT(d, DB_NOSYNC);
5879 ADD_INT(d, DB_POSITION);
5880 ADD_INT(d, DB_PREV);
5881 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005882#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005883 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005885 ADD_INT(d, DB_SET);
5886 ADD_INT(d, DB_SET_RANGE);
5887 ADD_INT(d, DB_SET_RECNO);
5888 ADD_INT(d, DB_WRITECURSOR);
5889
5890 ADD_INT(d, DB_OPFLAGS_MASK);
5891 ADD_INT(d, DB_RMW);
5892#if (DBVER >= 33)
5893 ADD_INT(d, DB_DIRTY_READ);
5894 ADD_INT(d, DB_MULTIPLE);
5895 ADD_INT(d, DB_MULTIPLE_KEY);
5896#endif
5897
Gregory P. Smith29602d22006-01-24 09:46:48 +00005898#if (DBVER >= 44)
5899 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5900 ADD_INT(d, DB_READ_COMMITTED);
5901#endif
5902
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005903#if (DBVER >= 33)
5904 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00005905 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005906#endif
5907
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005908#if (DBVER >= 41)
5909 _addIntToDict(d, "DB_INCOMPLETE", 0);
5910#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005911 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005912#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005913 ADD_INT(d, DB_KEYEMPTY);
5914 ADD_INT(d, DB_KEYEXIST);
5915 ADD_INT(d, DB_LOCK_DEADLOCK);
5916 ADD_INT(d, DB_LOCK_NOTGRANTED);
5917 ADD_INT(d, DB_NOSERVER);
5918 ADD_INT(d, DB_NOSERVER_HOME);
5919 ADD_INT(d, DB_NOSERVER_ID);
5920 ADD_INT(d, DB_NOTFOUND);
5921 ADD_INT(d, DB_OLD_VERSION);
5922 ADD_INT(d, DB_RUNRECOVERY);
5923 ADD_INT(d, DB_VERIFY_BAD);
5924#if (DBVER >= 33)
5925 ADD_INT(d, DB_PAGE_NOTFOUND);
5926 ADD_INT(d, DB_SECONDARY_BAD);
5927#endif
5928#if (DBVER >= 40)
5929 ADD_INT(d, DB_STAT_CLEAR);
5930 ADD_INT(d, DB_REGION_INIT);
5931 ADD_INT(d, DB_NOLOCKING);
5932 ADD_INT(d, DB_YIELDCPU);
5933 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5934 ADD_INT(d, DB_NOPANIC);
5935#endif
5936
Guido van Rossum2cc30da2007-11-02 23:46:40 +00005937#ifdef DB_REGISTER
5938 ADD_INT(d, DB_REGISTER);
5939#endif
5940
Gregory P. Smith41631e82003-09-21 00:08:14 +00005941#if (DBVER >= 42)
5942 ADD_INT(d, DB_TIME_NOTGRANTED);
5943 ADD_INT(d, DB_TXN_NOT_DURABLE);
5944 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5945 ADD_INT(d, DB_LOG_AUTOREMOVE);
5946 ADD_INT(d, DB_DIRECT_LOG);
5947 ADD_INT(d, DB_DIRECT_DB);
5948 ADD_INT(d, DB_INIT_REP);
5949 ADD_INT(d, DB_ENCRYPT);
5950 ADD_INT(d, DB_CHKSUM);
5951#endif
5952
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005953#if (DBVER >= 43)
5954 ADD_INT(d, DB_LOG_INMEMORY);
5955 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005956 ADD_INT(d, DB_SEQ_DEC);
5957 ADD_INT(d, DB_SEQ_INC);
5958 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005959#endif
5960
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005961#if (DBVER >= 41)
5962 ADD_INT(d, DB_ENCRYPT_AES);
5963 ADD_INT(d, DB_AUTO_COMMIT);
5964#else
5965 /* allow berkeleydb 4.1 aware apps to run on older versions */
5966 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5967#endif
5968
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005969 ADD_INT(d, EINVAL);
5970 ADD_INT(d, EACCES);
5971 ADD_INT(d, ENOSPC);
5972 ADD_INT(d, ENOMEM);
5973 ADD_INT(d, EAGAIN);
5974 ADD_INT(d, EBUSY);
5975 ADD_INT(d, EEXIST);
5976 ADD_INT(d, ENOENT);
5977 ADD_INT(d, EPERM);
5978
Barry Warsaw1baa9822003-03-31 19:51:29 +00005979#if (DBVER >= 40)
5980 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5981 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5982#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005983
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005984 /* The exception name must be correct for pickled exception *
5985 * objects to unpickle properly. */
5986#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5987#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5988#else
5989#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5990#endif
5991
5992 /* All the rest of the exceptions derive only from DBError */
5993#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5994 PyDict_SetItemString(d, #name, name)
5995
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005996 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005997 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5998 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005999
Gregory P. Smithe9477062005-06-04 06:46:59 +00006000 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6001 * from both DBError and KeyError, since the API only supports
6002 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006003 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006004 {
Georg Brandl1a3284e2007-12-02 09:40:06 +00006005 PyObject *builtin_mod = PyImport_ImportModule("builtins");
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006006 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6007 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006008 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6009 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010 Py_file_input, d, d);
6011 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006012 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013 PyDict_DelItemString(d, "KeyError");
6014
6015
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016#if !INCOMPLETE_IS_WARNING
6017 MAKE_EX(DBIncompleteError);
6018#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006019 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006020 MAKE_EX(DBKeyEmptyError);
6021 MAKE_EX(DBKeyExistError);
6022 MAKE_EX(DBLockDeadlockError);
6023 MAKE_EX(DBLockNotGrantedError);
6024 MAKE_EX(DBOldVersionError);
6025 MAKE_EX(DBRunRecoveryError);
6026 MAKE_EX(DBVerifyBadError);
6027 MAKE_EX(DBNoServerError);
6028 MAKE_EX(DBNoServerHomeError);
6029 MAKE_EX(DBNoServerIDError);
6030#if (DBVER >= 33)
6031 MAKE_EX(DBPageNotFoundError);
6032 MAKE_EX(DBSecondaryBadError);
6033#endif
6034
6035 MAKE_EX(DBInvalidArgError);
6036 MAKE_EX(DBAccessError);
6037 MAKE_EX(DBNoSpaceError);
6038 MAKE_EX(DBNoMemoryError);
6039 MAKE_EX(DBAgainError);
6040 MAKE_EX(DBBusyError);
6041 MAKE_EX(DBFileExistsError);
6042 MAKE_EX(DBNoSuchFileError);
6043 MAKE_EX(DBPermissionsError);
6044
6045#undef MAKE_EX
6046
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006047 /* Initiliase the C API structure and add it to the module */
6048 bsddb_api.db_type = &DB_Type;
6049 bsddb_api.dbcursor_type = &DBCursor_Type;
6050 bsddb_api.dbenv_type = &DBEnv_Type;
6051 bsddb_api.dbtxn_type = &DBTxn_Type;
6052 bsddb_api.dblock_type = &DBLock_Type;
6053#if (DBVER >= 43)
6054 bsddb_api.dbsequence_type = &DBSequence_Type;
6055#endif
6056 bsddb_api.makeDBError = makeDBError;
6057
6058 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
6059 PyDict_SetItemString(d, "api", py_api);
6060 Py_DECREF(py_api);
6061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006062 /* Check for errors */
6063 if (PyErr_Occurred()) {
6064 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006065 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006066 }
6067}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006068
6069/* allow this module to be named _pybsddb so that it can be installed
6070 * and imported on top of python >= 2.3 that includes its own older
6071 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006072PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006073{
6074 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6075 init_bsddb();
6076}