blob: 175dec3d49d27b5a78b59a4a5dbcc5412749baf7 [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>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000101#define PY_BSDDB_VERSION "4.5.0"
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000102static char *svn_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000103
104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000106typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298static PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
Neal Norwitz227b5332006-03-22 09:28:35 +0000301static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000302
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000303#define DBObject_Check(v) (Py_Type(v) == &DB_Type)
304#define DBCursorObject_Check(v) (Py_Type(v) == &DBCursor_Type)
305#define DBEnvObject_Check(v) (Py_Type(v) == &DBEnv_Type)
306#define DBTxnObject_Check(v) (Py_Type(v) == &DBTxn_Type)
307#define DBLockObject_Check(v) (Py_Type(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000308#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000309#define DBSequenceObject_Check(v) (Py_Type(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351
352static int makeDBError(int err);
353
354
355/* Return the access method type of the DBObject */
356static int _DB_get_type(DBObject* self)
357{
358#if (DBVER >= 33)
359 DBTYPE type;
360 int err;
361 err = self->db->get_type(self->db, &type);
362 if (makeDBError(err)) {
363 return -1;
364 }
365 return type;
366#else
367 return self->db->get_type(self->db);
368#endif
369}
370
371
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000372/* Handy function to free a DBT and any self-allocated data within.
373 To be used on self created DBTs. The make_dbt and make_key_dbt
374 functions have their own free routines that do more that this. */
375static void free_dbt(DBT *dbt)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000376{
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000377 if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
378 free(dbt->data);
379 dbt->data = NULL;
380 }
381}
382
383
384/* Cleanup a Python buffer API view created by make_dbt() */
Thomas Heller39763a12007-09-24 14:43:56 +0000385static void free_buf_view(PyObject *obj, Py_buffer *view)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000386{
387 if (view) {
388 PyObject_ReleaseBuffer(obj, view);
389 PyMem_Free(view);
390 }
391}
392
393
394/* Cleanup a DBT and an associated Python buffer API view
395 created by make_key_dbt() */
396#define FREE_DBT_VIEW(dbt, obj, view) \
397 do { \
398 free_dbt(&(dbt)); \
399 free_buf_view((obj), (view)); \
400 } while(0);
401
402
Thomas Heller39763a12007-09-24 14:43:56 +0000403static Py_buffer * _malloc_view(PyObject *obj)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000404{
Thomas Heller39763a12007-09-24 14:43:56 +0000405 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000406
Thomas Heller39763a12007-09-24 14:43:56 +0000407 if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000408 PyErr_SetString(PyExc_MemoryError,
Thomas Heller39763a12007-09-24 14:43:56 +0000409 "Py_buffer malloc failed");
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000410 return NULL;
411 }
412 /* XXX(gps): PyBUF_LOCKDATA is desired to prevent other theads from
413 trashing the data buffer while we release the GIL during the db
414 operation. see http://bugs.python.org/issue1035 */
415 if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
416 PyMem_Free(view);
417 return NULL;
418 }
419 if (view->ndim > 1) {
420 PyErr_SetString(PyExc_BufferError,
421 "buffers must be single dimension");
422 PyObject_ReleaseBuffer(obj, view);
423 PyMem_Free(view);
424 return NULL;
425 }
426 return view;
427}
428
429
430/* Create a DBT structure (containing key and data values) from Python
431 strings. Returns >= 1 on success, 0 on an error. The returned_view_p
Thomas Heller39763a12007-09-24 14:43:56 +0000432 may be filled with a newly allocated Py_buffer view on success.
433 The caller MUST call free_buf_view() on any returned Py_buffer. */
434static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000435{
Thomas Heller39763a12007-09-24 14:43:56 +0000436 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000437
438 /* simple way to ensure the caller can detect if we've returned a
439 new buffer view or not: require their pointer to start out NULL. */
440 assert(*returned_view_p == NULL);
441
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000442 CLEAR_DBT(*dbt);
443 if (obj == Py_None) {
444 /* no need to do anything, the structure has already been zeroed */
Guido van Rossumfc5fafc2007-08-24 05:08:58 +0000445 return 1;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000447 if (!PyObject_CheckBuffer(obj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000448 PyErr_SetString(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000449 "Data values must support the buffer API or be None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 return 0;
451 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000452
453 if ( !(view = _malloc_view(obj)) )
454 return 0;
455
456 dbt->data = view->buf;
457 dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
458 *returned_view_p = view;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000459 return 1;
460}
461
462
463/* Recno and Queue DBs can have integer keys. This function figures out
464 what's been given, verifies that it's allowed, and then makes the DBT.
465
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000466 Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
Thomas Heller39763a12007-09-24 14:43:56 +0000467 returned DBT and Py_buffer values when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000468static int
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000469make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
Thomas Heller39763a12007-09-24 14:43:56 +0000470 Py_buffer** returned_view_p)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000471{
472 db_recno_t recno;
473 int type;
Thomas Heller39763a12007-09-24 14:43:56 +0000474 Py_buffer *view;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000475
476 /* simple way to ensure the caller can detect if we've returned a
477 new buffer view or not: require their pointer to start out NULL. */
478 assert(*returned_view_p == NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000479
480 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000481 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000482 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000483 if (type == -1)
484 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000485 if (type == DB_RECNO || type == DB_QUEUE) {
486 PyErr_SetString(
487 PyExc_TypeError,
488 "None keys not allowed for Recno and Queue DB's");
489 return 0;
490 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000491 /* no need to do anything, the structure has already been zeroed */
492 }
493
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000494 else if (PyInt_Check(keyobj)) {
495 /* verify access method type */
496 type = _DB_get_type(self);
497 if (type == -1)
498 return 0;
499 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000500 /* if BTREE then an Integer key is allowed with the
501 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000502 *pflags |= DB_SET_RECNO;
503 }
504 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000505 PyErr_SetString(
506 PyExc_TypeError,
507 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508 return 0;
509 }
510
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000511 /* Make a key out of the requested recno, use allocated space so DB
512 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513 recno = PyInt_AS_LONG(keyobj);
514 key->data = malloc(sizeof(db_recno_t));
515 if (key->data == NULL) {
516 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
517 return 0;
518 }
519 key->ulen = key->size = sizeof(db_recno_t);
520 memcpy(key->data, &recno, sizeof(db_recno_t));
521 key->flags = DB_DBT_REALLOC;
522 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000523
524 else if (PyObject_CheckBuffer(keyobj)) {
525 /* verify access method type */
526 type = _DB_get_type(self);
527 if (type == -1)
528 return 0;
529 if (type == DB_RECNO || type == DB_QUEUE) {
530 PyErr_SetString(
531 PyExc_TypeError,
532 "Non-integer keys not allowed for Recno and Queue DB's");
533 return 0;
534 }
535
536 if ( !(view = _malloc_view(keyobj)) )
537 return 0;
538
539 key->data = view->buf;
540 key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
541 *returned_view_p = view;
542 }
543
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000544 else {
545 PyErr_Format(PyExc_TypeError,
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000546 "buffer or int object expected for key, %s found",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000547 Py_Type(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000548 return 0;
549 }
550
551 return 1;
552}
553
554
555/* Add partial record access to an existing DBT data struct.
556 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
557 and the data storage/retrieval will be done using dlen and doff. */
558static int add_partial_dbt(DBT* d, int dlen, int doff) {
559 /* if neither were set we do nothing (-1 is the default value) */
560 if ((dlen == -1) && (doff == -1)) {
561 return 1;
562 }
563
564 if ((dlen < 0) || (doff < 0)) {
565 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
566 return 0;
567 }
568
569 d->flags = d->flags | DB_DBT_PARTIAL;
570 d->dlen = (unsigned int) dlen;
571 d->doff = (unsigned int) doff;
572 return 1;
573}
574
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000575/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
576/* TODO: make this use the native libc strlcpy() when available (BSD) */
577unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
578{
579 unsigned int srclen, copylen;
580
581 srclen = strlen(src);
582 if (n <= 0)
583 return srclen;
584 copylen = (srclen > n-1) ? n-1 : srclen;
585 /* populate dest[0] thru dest[copylen-1] */
586 memcpy(dest, src, copylen);
587 /* guarantee null termination */
588 dest[copylen] = 0;
589
590 return srclen;
591}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000592
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000593/* Callback used to save away more information about errors from the DB
594 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000595static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000596#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000597static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000598#else
599static void _db_errorCallback(const DB_ENV *db_env,
600 const char* prefix, const char* msg)
601#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000603 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000604}
605
606
607/* make a nice exception object to raise for errors. */
608static int makeDBError(int err)
609{
610 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000611 PyObject *errObj = NULL;
612 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000613 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000614 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000615
616 switch (err) {
617 case 0: /* successful, no error */ break;
618
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000619#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620 case DB_INCOMPLETE:
621#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000622 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
623 /* Ensure that bytes_left never goes negative */
624 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
625 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
626 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000627 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000628 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000629 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000630 _db_errmsg[0] = 0;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000631#ifdef HAVE_WARNINGS
Skip Montanaro46fc3372007-08-12 11:44:53 +0000632 exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000633#else
634 fprintf(stderr, errTxt);
635 fprintf(stderr, "\n");
636#endif
637
638#else /* do an exception instead */
639 errObj = DBIncompleteError;
640#endif
641 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000642#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000643
644 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
645 case DB_KEYEXIST: errObj = DBKeyExistError; break;
646 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
647 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
648 case DB_NOTFOUND: errObj = DBNotFoundError; break;
649 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
650 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
651 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
652 case DB_NOSERVER: errObj = DBNoServerError; break;
653 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
654 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
655#if (DBVER >= 33)
656 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
657 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
658#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000659 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000661#if (DBVER >= 43)
662 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
663 case ENOMEM: errObj = PyExc_MemoryError; break;
664#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000665 case EINVAL: errObj = DBInvalidArgError; break;
666 case EACCES: errObj = DBAccessError; break;
667 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000668 case EAGAIN: errObj = DBAgainError; break;
669 case EBUSY : errObj = DBBusyError; break;
670 case EEXIST: errObj = DBFileExistsError; break;
671 case ENOENT: errObj = DBNoSuchFileError; break;
672 case EPERM : errObj = DBPermissionsError; break;
673
674 default: errObj = DBError; break;
675 }
676
677 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000678 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
679 /* Ensure that bytes_left never goes negative */
680 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
681 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
682 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000683 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000684 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000685 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000686 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000687
688 errTuple = Py_BuildValue("(is)", err, errTxt);
689 PyErr_SetObject(errObj, errTuple);
690 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691 }
692
693 return ((errObj != NULL) || exceptionRaised);
694}
695
696
697
698/* set a type exception */
699static void makeTypeError(char* expected, PyObject* found)
700{
701 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000702 expected, Py_Type(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703}
704
705
706/* verify that an obj is either None or a DBTxn, and set the txn pointer */
707static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
708{
709 if (txnobj == Py_None || txnobj == NULL) {
710 *txn = NULL;
711 return 1;
712 }
713 if (DBTxnObject_Check(txnobj)) {
714 *txn = ((DBTxnObject*)txnobj)->txn;
715 return 1;
716 }
717 else
718 makeTypeError("DBTxn", txnobj);
719 return 0;
720}
721
722
723/* Delete a key from a database
724 Returns 0 on success, -1 on an error. */
725static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
726{
727 int err;
728
729 MYDB_BEGIN_ALLOW_THREADS;
730 err = self->db->del(self->db, txn, key, 0);
731 MYDB_END_ALLOW_THREADS;
732 if (makeDBError(err)) {
733 return -1;
734 }
735 self->haveStat = 0;
736 return 0;
737}
738
739
740/* Store a key into a database
741 Returns 0 on success, -1 on an error. */
742static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
743{
744 int err;
745
746 MYDB_BEGIN_ALLOW_THREADS;
747 err = self->db->put(self->db, txn, key, data, flags);
748 MYDB_END_ALLOW_THREADS;
749 if (makeDBError(err)) {
750 return -1;
751 }
752 self->haveStat = 0;
753 return 0;
754}
755
756/* Get a key/data pair from a cursor */
757static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
758 PyObject *args, PyObject *kwargs, char *format)
759{
760 int err;
761 PyObject* retval = NULL;
762 DBT key, data;
763 int dlen = -1;
764 int doff = -1;
765 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000766 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000767
768 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
769 &flags, &dlen, &doff))
770 return NULL;
771
772 CHECK_CURSOR_NOT_CLOSED(self);
773
774 flags |= extra_flags;
775 CLEAR_DBT(key);
776 CLEAR_DBT(data);
777 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
778 /* Tell BerkeleyDB to malloc the return value (thread safe) */
779 data.flags = DB_DBT_MALLOC;
780 key.flags = DB_DBT_MALLOC;
781 }
782 if (!add_partial_dbt(&data, dlen, doff))
783 return NULL;
784
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->dbc->c_get(self->dbc, &key, &data, flags);
787 MYDB_END_ALLOW_THREADS;
788
Gregory P. Smithe9477062005-06-04 06:46:59 +0000789 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
790 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000791 Py_INCREF(Py_None);
792 retval = Py_None;
793 }
794 else if (makeDBError(err)) {
795 retval = NULL;
796 }
797 else { /* otherwise, success! */
798
799 /* if Recno or Queue, return the key as an Int */
800 switch (_DB_get_type(self->mydb)) {
801 case -1:
802 retval = NULL;
803 break;
804
805 case DB_RECNO:
806 case DB_QUEUE:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000807 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000808 data.data, data.size);
809 break;
810 case DB_HASH:
811 case DB_BTREE:
812 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +0000813 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000814 data.data, data.size);
815 break;
816 }
817 }
818 if (!err) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000819 free_dbt(&key);
820 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000821 }
822 return retval;
823}
824
825
826/* add an integer to a dictionary using the given name as a key */
827static void _addIntToDict(PyObject* dict, char *name, int value)
828{
829 PyObject* v = PyInt_FromLong((long) value);
830 if (!v || PyDict_SetItemString(dict, name, v))
831 PyErr_Clear();
832
833 Py_XDECREF(v);
834}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000835
836/* The same, when the value is a time_t */
837static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
838{
839 PyObject* v;
840 /* if the value fits in regular int, use that. */
841#ifdef HAVE_LONG_LONG
842 if (sizeof(time_t) > sizeof(long))
843 v = PyLong_FromLongLong((PY_LONG_LONG) value);
844 else
845#endif
846 v = PyInt_FromLong((long) value);
847 if (!v || PyDict_SetItemString(dict, name, v))
848 PyErr_Clear();
849
850 Py_XDECREF(v);
851}
852
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000853#if (DBVER >= 43)
854/* add an db_seq_t to a dictionary using the given name as a key */
855static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
856{
857 PyObject* v = PyLong_FromLongLong(value);
858 if (!v || PyDict_SetItemString(dict, name, v))
859 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000861 Py_XDECREF(v);
862}
863#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864
865
866
867/* --------------------------------------------------------------------- */
868/* Allocators and deallocators */
869
870static DBObject*
871newDBObject(DBEnvObject* arg, int flags)
872{
873 DBObject* self;
874 DB_ENV* db_env = NULL;
875 int err;
876
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 if (self == NULL)
879 return NULL;
880
881 self->haveStat = 0;
882 self->flags = 0;
883 self->setflags = 0;
884 self->myenvobj = NULL;
885#if (DBVER >= 33)
886 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000887 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888 self->primaryDBType = 0;
889#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000890#ifdef HAVE_WEAKREF
891 self->in_weakreflist = NULL;
892#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893
894 /* keep a reference to our python DBEnv object */
895 if (arg) {
896 Py_INCREF(arg);
897 self->myenvobj = arg;
898 db_env = arg->db_env;
899 }
900
901 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000902 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000904 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
905 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000906
907 MYDB_BEGIN_ALLOW_THREADS;
908 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000909 if (self->db != NULL) {
910 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000911#if (DBVER >= 33)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000912 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000913#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000914 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000916 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
917 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000918 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919 if (makeDBError(err)) {
920 if (self->myenvobj) {
921 Py_DECREF(self->myenvobj);
922 self->myenvobj = NULL;
923 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000924 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925 self = NULL;
926 }
927 return self;
928}
929
930
931static void
932DB_dealloc(DBObject* self)
933{
934 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000935 /* avoid closing a DB when its DBEnv has been closed out from under
936 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000938 (self->myenvobj && self->myenvobj->db_env))
939 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000940 MYDB_BEGIN_ALLOW_THREADS;
941 self->db->close(self->db, 0);
942 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000943#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 } else {
Skip Montanaro46fc3372007-08-12 11:44:53 +0000945 PyErr_WarnEx(PyExc_RuntimeWarning,
946 "DB could not be closed in destructor:"
947 " DBEnv already closed",
948 1);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000949#endif
950 }
951 self->db = NULL;
952 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953#ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
956 }
957#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 if (self->myenvobj) {
959 Py_DECREF(self->myenvobj);
960 self->myenvobj = NULL;
961 }
962#if (DBVER >= 33)
963 if (self->associateCallback != NULL) {
964 Py_DECREF(self->associateCallback);
965 self->associateCallback = NULL;
966 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000967 if (self->btCompareCallback != NULL) {
968 Py_DECREF(self->btCompareCallback);
969 self->btCompareCallback = NULL;
970 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000973}
974
975
976static DBCursorObject*
977newDBCursorObject(DBC* dbc, DBObject* db)
978{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000979 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000980 if (self == NULL)
981 return NULL;
982
983 self->dbc = dbc;
984 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000985#ifdef HAVE_WEAKREF
986 self->in_weakreflist = NULL;
987#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000988 Py_INCREF(self->mydb);
989 return self;
990}
991
992
993static void
994DBCursor_dealloc(DBCursorObject* self)
995{
996 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000997
998#ifdef HAVE_WEAKREF
999 if (self->in_weakreflist != NULL) {
1000 PyObject_ClearWeakRefs((PyObject *) self);
1001 }
1002#endif
1003
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001004 if (self->dbc != NULL) {
1005 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +00001006 /* If the underlying database has been closed, we don't
1007 need to do anything. If the environment has been closed
1008 we need to leak, as BerkeleyDB will crash trying to access
1009 the environment. There was an exception when the
1010 user closed the environment even though there still was
1011 a database open. */
1012 if (self->mydb->db && self->mydb->myenvobj &&
1013 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001014 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001015 self->dbc = NULL;
1016 MYDB_END_ALLOW_THREADS;
1017 }
1018 Py_XDECREF( self->mydb );
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 DBEnvObject*
1024newDBEnvObject(int flags)
1025{
1026 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001027 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001028 if (self == NULL)
1029 return NULL;
1030
1031 self->closed = 1;
1032 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001033 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1034 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001035#ifdef HAVE_WEAKREF
1036 self->in_weakreflist = NULL;
1037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001038
1039 MYDB_BEGIN_ALLOW_THREADS;
1040 err = db_env_create(&self->db_env, flags);
1041 MYDB_END_ALLOW_THREADS;
1042 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001043 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 self = NULL;
1045 }
1046 else {
1047 self->db_env->set_errcall(self->db_env, _db_errorCallback);
1048 }
1049 return self;
1050}
1051
1052
1053static void
1054DBEnv_dealloc(DBEnvObject* self)
1055{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001056#ifdef HAVE_WEAKREF
1057 if (self->in_weakreflist != NULL) {
1058 PyObject_ClearWeakRefs((PyObject *) self);
1059 }
1060#endif
1061
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001062 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063 MYDB_BEGIN_ALLOW_THREADS;
1064 self->db_env->close(self->db_env, 0);
1065 MYDB_END_ALLOW_THREADS;
1066 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001068}
1069
1070
1071static DBTxnObject*
1072newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
1073{
1074 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001075 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001076 if (self == NULL)
1077 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +00001078 Py_INCREF(myenv);
1079 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001080#ifdef HAVE_WEAKREF
1081 self->in_weakreflist = NULL;
1082#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001083
1084 MYDB_BEGIN_ALLOW_THREADS;
1085#if (DBVER >= 40)
1086 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1087#else
1088 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1089#endif
1090 MYDB_END_ALLOW_THREADS;
1091 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +00001092 Py_DECREF(self->env);
1093 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001094 self = NULL;
1095 }
1096 return self;
1097}
1098
1099
1100static void
1101DBTxn_dealloc(DBTxnObject* self)
1102{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001103#ifdef HAVE_WEAKREF
1104 if (self->in_weakreflist != NULL) {
1105 PyObject_ClearWeakRefs((PyObject *) self);
1106 }
1107#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001108
Gregory P. Smith31c50652004-06-28 01:20:40 +00001109#ifdef HAVE_WARNINGS
1110 if (self->txn) {
1111 /* it hasn't been finalized, abort it! */
1112 MYDB_BEGIN_ALLOW_THREADS;
1113#if (DBVER >= 40)
1114 self->txn->abort(self->txn);
1115#else
1116 txn_abort(self->txn);
1117#endif
1118 MYDB_END_ALLOW_THREADS;
Skip Montanaro46fc3372007-08-12 11:44:53 +00001119 PyErr_WarnEx(PyExc_RuntimeWarning,
1120 "DBTxn aborted in destructor. "
1121 " No prior commit() or abort().",
1122 1);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001123 }
1124#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125
Neal Norwitz62a21122006-01-25 05:21:55 +00001126 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128}
1129
1130
1131static DBLockObject*
1132newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1133 db_lockmode_t lock_mode, int flags)
1134{
1135 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001136 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001137 if (self == NULL)
1138 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001139#ifdef HAVE_WEAKREF
1140 self->in_weakreflist = NULL;
1141#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001142
1143 MYDB_BEGIN_ALLOW_THREADS;
1144#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001145 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1146 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147#else
1148 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1149#endif
1150 MYDB_END_ALLOW_THREADS;
1151 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001152 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001153 self = NULL;
1154 }
1155
1156 return self;
1157}
1158
1159
1160static void
1161DBLock_dealloc(DBLockObject* self)
1162{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001163#ifdef HAVE_WEAKREF
1164 if (self->in_weakreflist != NULL) {
1165 PyObject_ClearWeakRefs((PyObject *) self);
1166 }
1167#endif
1168 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171}
1172
1173
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001174#if (DBVER >= 43)
1175static DBSequenceObject*
1176newDBSequenceObject(DBObject* mydb, int flags)
1177{
1178 int err;
1179 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1180 if (self == NULL)
1181 return NULL;
1182 Py_INCREF(mydb);
1183 self->mydb = mydb;
1184#ifdef HAVE_WEAKREF
1185 self->in_weakreflist = NULL;
1186#endif
1187
1188
1189 MYDB_BEGIN_ALLOW_THREADS;
1190 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1191 MYDB_END_ALLOW_THREADS;
1192 if (makeDBError(err)) {
1193 Py_DECREF(self->mydb);
1194 PyObject_Del(self);
1195 self = NULL;
1196 }
1197
1198 return self;
1199}
1200
1201
1202static void
1203DBSequence_dealloc(DBSequenceObject* self)
1204{
1205#ifdef HAVE_WEAKREF
1206 if (self->in_weakreflist != NULL) {
1207 PyObject_ClearWeakRefs((PyObject *) self);
1208 }
1209#endif
1210
1211 Py_DECREF(self->mydb);
1212 PyObject_Del(self);
1213}
1214#endif
1215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001216/* --------------------------------------------------------------------- */
1217/* DB methods */
1218
1219static PyObject*
1220DB_append(DBObject* self, PyObject* args)
1221{
1222 PyObject* txnobj = NULL;
1223 PyObject* dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001224 Py_buffer* data_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225 db_recno_t recno;
1226 DBT key, data;
1227 DB_TXN *txn = NULL;
1228
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001229 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001230 return NULL;
1231
1232 CHECK_DB_NOT_CLOSED(self);
1233
1234 /* make a dummy key out of a recno */
1235 recno = 0;
1236 CLEAR_DBT(key);
1237 key.data = &recno;
1238 key.size = sizeof(recno);
1239 key.ulen = key.size;
1240 key.flags = DB_DBT_USERMEM;
1241
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242 if (!checkTxnObj(txnobj, &txn)) return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001243 if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001244
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001245 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
1246 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001247 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001248 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001249
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001250 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251 return PyInt_FromLong(recno);
1252}
1253
1254
1255#if (DBVER >= 33)
1256
1257static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001258_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1259 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260{
1261 int retval = DB_DONOTINDEX;
1262 DBObject* secondaryDB = (DBObject*)db->app_private;
1263 PyObject* callback = secondaryDB->associateCallback;
1264 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001266 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001267
1268
1269 if (callback != NULL) {
1270 MYDB_BEGIN_BLOCK_THREADS;
1271
Thomas Woutersb3153832006-03-08 01:47:19 +00001272 if (type == DB_RECNO || type == DB_QUEUE)
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001273 args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
Thomas Woutersb3153832006-03-08 01:47:19 +00001274 priData->data, priData->size);
1275 else
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001276 args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00001277 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001278 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001279 result = PyEval_CallObject(callback, args);
1280 }
1281 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001282 PyErr_Print();
1283 }
1284 else if (result == Py_None) {
1285 retval = DB_DONOTINDEX;
1286 }
1287 else if (PyInt_Check(result)) {
1288 retval = PyInt_AsLong(result);
1289 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001290 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001291 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001292 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001293
1294 CLEAR_DBT(*secKey);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001295 size = PyBytes_Size(result);
1296 data = PyBytes_AsString(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1298 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001299 if (secKey->data) {
1300 memcpy(secKey->data, data, size);
1301 secKey->size = size;
1302 retval = 0;
1303 }
1304 else {
1305 PyErr_SetString(PyExc_MemoryError,
1306 "malloc failed in _db_associateCallback");
1307 PyErr_Print();
1308 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001309 }
1310 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001311 PyErr_SetString(
1312 PyExc_TypeError,
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001313 "DB associate callback should return DB_DONOTINDEX or bytes.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 PyErr_Print();
1315 }
1316
Thomas Woutersb3153832006-03-08 01:47:19 +00001317 Py_XDECREF(args);
1318 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319
1320 MYDB_END_BLOCK_THREADS;
1321 }
1322 return retval;
1323}
1324
1325
1326static PyObject*
1327DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1328{
1329 int err, flags=0;
1330 DBObject* secondaryDB;
1331 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001332#if (DBVER >= 41)
1333 PyObject *txnobj = NULL;
1334 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001335 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001336 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001337#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001338 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001339#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001341#if (DBVER >= 41)
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1343 &secondaryDB, &callback, &flags,
1344 &txnobj)) {
1345#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001347 &secondaryDB, &callback, &flags)) {
1348#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001349 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001350 }
1351
1352#if (DBVER >= 41)
1353 if (!checkTxnObj(txnobj, &txn)) return NULL;
1354#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001355
1356 CHECK_DB_NOT_CLOSED(self);
1357 if (!DBObject_Check(secondaryDB)) {
1358 makeTypeError("DB", (PyObject*)secondaryDB);
1359 return NULL;
1360 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001361 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362 if (callback == Py_None) {
1363 callback = NULL;
1364 }
1365 else if (!PyCallable_Check(callback)) {
1366 makeTypeError("Callable", callback);
1367 return NULL;
1368 }
1369
1370 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001371 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001372 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001373 secondaryDB->associateCallback = callback;
1374 secondaryDB->primaryDBType = _DB_get_type(self);
1375
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001376 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1377 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1378 * The global interepreter lock is not initialized until the first
1379 * thread is created using thread.start_new_thread() or fork() is
1380 * called. that would cause the ALLOW_THREADS here to segfault due
1381 * to a null pointer reference if no threads or child processes
1382 * have been created. This works around that and is a no-op if
1383 * threads have already been initialized.
1384 * (see pybsddb-users mailing list post on 2002-08-07)
1385 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001386#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001387 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001388#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001389 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001390#if (DBVER >= 41)
1391 err = self->db->associate(self->db,
1392 txn,
1393 secondaryDB->db,
1394 _db_associateCallback,
1395 flags);
1396#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001397 err = self->db->associate(self->db,
1398 secondaryDB->db,
1399 _db_associateCallback,
1400 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001401#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402 MYDB_END_ALLOW_THREADS;
1403
1404 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001405 Py_XDECREF(secondaryDB->associateCallback);
1406 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001407 secondaryDB->primaryDBType = 0;
1408 }
1409
1410 RETURN_IF_ERR();
1411 RETURN_NONE();
1412}
1413
1414
1415#endif
1416
1417
1418static PyObject*
1419DB_close(DBObject* self, PyObject* args)
1420{
1421 int err, flags=0;
1422 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1423 return NULL;
1424 if (self->db != NULL) {
1425 if (self->myenvobj)
1426 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428 self->db = NULL;
1429 RETURN_IF_ERR();
1430 }
1431 RETURN_NONE();
1432}
1433
1434
1435#if (DBVER >= 32)
1436static PyObject*
1437_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1438{
1439 int err, flags=0, type;
1440 PyObject* txnobj = NULL;
1441 PyObject* retval = NULL;
1442 DBT key, data;
1443 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001444 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445
1446 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1447 &txnobj, &flags))
1448 return NULL;
1449
1450 CHECK_DB_NOT_CLOSED(self);
1451 type = _DB_get_type(self);
1452 if (type == -1)
1453 return NULL;
1454 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001455 PyErr_SetString(PyExc_TypeError,
1456 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001457 return NULL;
1458 }
1459 if (!checkTxnObj(txnobj, &txn))
1460 return NULL;
1461
1462 CLEAR_DBT(key);
1463 CLEAR_DBT(data);
1464 if (CHECK_DBFLAG(self, DB_THREAD)) {
1465 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1466 data.flags = DB_DBT_MALLOC;
1467 key.flags = DB_DBT_MALLOC;
1468 }
1469
1470 MYDB_BEGIN_ALLOW_THREADS;
1471 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1472 MYDB_END_ALLOW_THREADS;
1473
Gregory P. Smithe9477062005-06-04 06:46:59 +00001474 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1475 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476 err = 0;
1477 Py_INCREF(Py_None);
1478 retval = Py_None;
1479 }
1480 else if (!err) {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001481 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001482 data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001483 free_dbt(&key);
1484 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001485 }
1486
1487 RETURN_IF_ERR();
1488 return retval;
1489}
1490
1491static PyObject*
1492DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1493{
1494 return _DB_consume(self, args, kwargs, DB_CONSUME);
1495}
1496
1497static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001498DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1499 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001500{
1501 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1502}
1503#endif
1504
1505
1506
1507static PyObject*
1508DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1509{
1510 int err, flags=0;
1511 DBC* dbc;
1512 PyObject* txnobj = NULL;
1513 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001514 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515
1516 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1517 &txnobj, &flags))
1518 return NULL;
1519 CHECK_DB_NOT_CLOSED(self);
1520 if (!checkTxnObj(txnobj, &txn))
1521 return NULL;
1522
1523 MYDB_BEGIN_ALLOW_THREADS;
1524 err = self->db->cursor(self->db, txn, &dbc, flags);
1525 MYDB_END_ALLOW_THREADS;
1526 RETURN_IF_ERR();
1527 return (PyObject*) newDBCursorObject(dbc, self);
1528}
1529
1530
1531static PyObject*
1532DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1533{
1534 PyObject* txnobj = NULL;
1535 int flags = 0;
1536 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001537 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001538 DBT key;
1539 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001540 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001541
1542 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1543 &keyobj, &txnobj, &flags))
1544 return NULL;
1545 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001546 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001547 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001548 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001549 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001550 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001551 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001552
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001553 if (-1 == _DB_delete(self, txn, &key, 0)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001554 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001556 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001557
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001558 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001559 RETURN_NONE();
1560}
1561
1562
1563static PyObject*
1564DB_fd(DBObject* self, PyObject* args)
1565{
1566 int err, the_fd;
1567
1568 if (!PyArg_ParseTuple(args,":fd"))
1569 return NULL;
1570 CHECK_DB_NOT_CLOSED(self);
1571
1572 MYDB_BEGIN_ALLOW_THREADS;
1573 err = self->db->fd(self->db, &the_fd);
1574 MYDB_END_ALLOW_THREADS;
1575 RETURN_IF_ERR();
1576 return PyInt_FromLong(the_fd);
1577}
1578
1579
1580static PyObject*
1581DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1582{
1583 int err, flags=0;
1584 PyObject* txnobj = NULL;
1585 PyObject* keyobj;
1586 PyObject* dfltobj = NULL;
1587 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001588 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589 int dlen = -1;
1590 int doff = -1;
1591 DBT key, data;
1592 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001593 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001594 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001595
1596 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001597 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1598 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599 return NULL;
1600
1601 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001602 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001603 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001604 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001605 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001606 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001607 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001608
1609 CLEAR_DBT(data);
1610 if (CHECK_DBFLAG(self, DB_THREAD)) {
1611 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1612 data.flags = DB_DBT_MALLOC;
1613 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001614 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001615 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001616 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001617 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001618
1619 MYDB_BEGIN_ALLOW_THREADS;
1620 err = self->db->get(self->db, txn, &key, &data, flags);
1621 MYDB_END_ALLOW_THREADS;
1622
Gregory P. Smithe9477062005-06-04 06:46:59 +00001623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001624 err = 0;
1625 Py_INCREF(dfltobj);
1626 retval = dfltobj;
1627 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001628 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1629 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001630 err = 0;
1631 Py_INCREF(Py_None);
1632 retval = Py_None;
1633 }
1634 else if (!err) {
1635 if (flags & DB_SET_RECNO) /* return both key and data */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00001636 retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001637 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001638 else /* return just the data */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001639 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001640 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001641 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001642 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643
1644 RETURN_IF_ERR();
1645 return retval;
1646}
1647
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001648#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001649static PyObject*
1650DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1651{
1652 int err, flags=0;
1653 PyObject* txnobj = NULL;
1654 PyObject* keyobj;
1655 PyObject* dfltobj = NULL;
1656 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001657 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00001658 int dlen = -1;
1659 int doff = -1;
1660 DBT key, pkey, data;
1661 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001662 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001663 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001664
1665 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1666 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1667 &doff))
1668 return NULL;
1669
1670 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001671 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001672 return NULL;
1673 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001674 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001675 return NULL;
1676 }
1677
1678 CLEAR_DBT(data);
1679 if (CHECK_DBFLAG(self, DB_THREAD)) {
1680 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1681 data.flags = DB_DBT_MALLOC;
1682 }
1683 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001684 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001685 return NULL;
1686 }
1687
1688 CLEAR_DBT(pkey);
1689 pkey.flags = DB_DBT_MALLOC;
1690
1691 MYDB_BEGIN_ALLOW_THREADS;
1692 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1693 MYDB_END_ALLOW_THREADS;
1694
Gregory P. Smithe9477062005-06-04 06:46:59 +00001695 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001696 err = 0;
1697 Py_INCREF(dfltobj);
1698 retval = dfltobj;
1699 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001700 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1701 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001702 err = 0;
1703 Py_INCREF(Py_None);
1704 retval = Py_None;
1705 }
1706 else if (!err) {
1707 PyObject *pkeyObj;
1708 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001709 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001710
1711 if (self->primaryDBType == DB_RECNO ||
1712 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001713 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001714 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001715 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001716
1717 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1718 {
1719 PyObject *keyObj;
1720 int type = _DB_get_type(self);
1721 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001722 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001723 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001724 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001725#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001726 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001727#else
1728 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1729#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001730 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001731 }
1732 else /* return just the pkey and data */
1733 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001734#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001735 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001736#else
1737 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1738#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001739 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001740 Py_DECREF(dataObj);
1741 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001742 free_dbt(&pkey);
1743 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001744 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001745 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001746
1747 RETURN_IF_ERR();
1748 return retval;
1749}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001750#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001751
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001752
1753/* Return size of entry */
1754static PyObject*
1755DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1756{
1757 int err, flags=0;
1758 PyObject* txnobj = NULL;
1759 PyObject* keyobj;
1760 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001761 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001762 DBT key, data;
1763 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001764 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001765
1766 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1767 &keyobj, &txnobj))
1768 return NULL;
1769 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001770 if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001771 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001772 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001773 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001774 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001775 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001776 CLEAR_DBT(data);
1777
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001778 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1779 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001780 data.flags = DB_DBT_USERMEM;
1781 data.ulen = 0;
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 err = self->db->get(self->db, txn, &key, &data, flags);
1784 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001785 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786 retval = PyInt_FromLong((long)data.size);
1787 err = 0;
1788 }
1789
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001790 FREE_DBT_VIEW(key, keyobj, key_buf_view);
1791 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001792 RETURN_IF_ERR();
1793 return retval;
1794}
1795
1796
1797static PyObject*
1798DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1799{
1800 int err, flags=0;
1801 PyObject* txnobj = NULL;
1802 PyObject* keyobj;
1803 PyObject* dataobj;
1804 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00001805 Py_buffer* data_buf_view = NULL;
1806 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001807 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001808 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001809 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001810 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001811
1812
1813 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1814 &keyobj, &dataobj, &txnobj, &flags))
1815 return NULL;
1816
1817 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001818 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001819 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001820 if ( !checkTxnObj(txnobj, &txn) ||
1821 !make_dbt(dataobj, &data, &data_buf_view) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001822 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001823 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001824 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001825 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001826
1827 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001828 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829
1830 if (CHECK_DBFLAG(self, DB_THREAD)) {
1831 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001832 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 }
1835
1836 MYDB_BEGIN_ALLOW_THREADS;
1837 err = self->db->get(self->db, txn, &key, &data, flags);
1838 MYDB_END_ALLOW_THREADS;
1839
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001840 free_buf_view(dataobj, data_buf_view);
1841
Gregory P. Smithe9477062005-06-04 06:46:59 +00001842 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1843 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 err = 0;
1845 Py_INCREF(Py_None);
1846 retval = Py_None;
1847 }
1848 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001849 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001850 /* XXX(gps) I think not: buffer API input vs. bytes object output. */
Martin v. Löwis64ce5052007-08-05 15:39:16 +00001851 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001852
1853 /* Even though the flags require DB_DBT_MALLOC, data is not always
1854 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1855 if (data.data != orig_data)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001856 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001857 }
1858
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001859 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860 RETURN_IF_ERR();
1861 return retval;
1862}
1863
1864
1865static PyObject*
1866DB_get_byteswapped(DBObject* self, PyObject* args)
1867{
1868#if (DBVER >= 33)
1869 int err = 0;
1870#endif
1871 int retval = -1;
1872
1873 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1874 return NULL;
1875 CHECK_DB_NOT_CLOSED(self);
1876
1877#if (DBVER >= 33)
1878 MYDB_BEGIN_ALLOW_THREADS;
1879 err = self->db->get_byteswapped(self->db, &retval);
1880 MYDB_END_ALLOW_THREADS;
1881 RETURN_IF_ERR();
1882#else
1883 MYDB_BEGIN_ALLOW_THREADS;
1884 retval = self->db->get_byteswapped(self->db);
1885 MYDB_END_ALLOW_THREADS;
1886#endif
1887 return PyInt_FromLong(retval);
1888}
1889
1890
1891static PyObject*
1892DB_get_type(DBObject* self, PyObject* args)
1893{
1894 int type;
1895
1896 if (!PyArg_ParseTuple(args,":get_type"))
1897 return NULL;
1898 CHECK_DB_NOT_CLOSED(self);
1899
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001900 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001901 if (type == -1)
1902 return NULL;
1903 return PyInt_FromLong(type);
1904}
1905
1906
1907static PyObject*
1908DB_join(DBObject* self, PyObject* args)
1909{
1910 int err, flags=0;
1911 int length, x;
1912 PyObject* cursorsObj;
1913 DBC** cursors;
1914 DBC* dbc;
1915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1917 return NULL;
1918
1919 CHECK_DB_NOT_CLOSED(self);
1920
1921 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001922 PyErr_SetString(PyExc_TypeError,
1923 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 return NULL;
1925 }
1926
1927 length = PyObject_Length(cursorsObj);
1928 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001929 if (!cursors) {
1930 PyErr_NoMemory();
1931 return NULL;
1932 }
1933
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001934 cursors[length] = NULL;
1935 for (x=0; x<length; x++) {
1936 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001937 if (item == NULL) {
1938 free(cursors);
1939 return NULL;
1940 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001941 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001942 PyErr_SetString(PyExc_TypeError,
1943 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 free(cursors);
1945 return NULL;
1946 }
1947 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001948 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 }
1950
1951 MYDB_BEGIN_ALLOW_THREADS;
1952 err = self->db->join(self->db, cursors, &dbc, flags);
1953 MYDB_END_ALLOW_THREADS;
1954 free(cursors);
1955 RETURN_IF_ERR();
1956
Gregory P. Smith7441e652003-11-03 21:35:31 +00001957 /* FIXME: this is a buggy interface. The returned cursor
1958 contains internal references to the passed in cursors
1959 but does not hold python references to them or prevent
1960 them from being closed prematurely. This can cause
1961 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962 return (PyObject*) newDBCursorObject(dbc, self);
1963}
1964
1965
1966static PyObject*
1967DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1968{
1969 int err, flags=0;
1970 PyObject* txnobj = NULL;
1971 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00001972 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001973 DBT key;
1974 DB_TXN *txn = NULL;
1975 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001976 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001977
1978 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1979 &keyobj, &txnobj, &flags))
1980 return NULL;
1981 CHECK_DB_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001982 if (!checkTxnObj(txnobj, &txn))
1983 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001984 if (!make_dbt(keyobj, &key, &key_buf_view))
1985 /* BTree only, don't need to allow for an int key */
1986 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001987
1988 MYDB_BEGIN_ALLOW_THREADS;
1989 err = self->db->key_range(self->db, txn, &key, &range, flags);
1990 MYDB_END_ALLOW_THREADS;
1991
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00001992 free_buf_view(keyobj, key_buf_view);
1993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001994 RETURN_IF_ERR();
1995 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1996}
1997
1998
1999static PyObject*
2000DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2001{
2002 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2003 char* filename = NULL;
2004 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002005#if (DBVER >= 41)
2006 PyObject *txnobj = NULL;
2007 DB_TXN *txn = NULL;
2008 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002009 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002010 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2011 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002012 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002013 "filename", "dbtype", "flags", "mode", "txn", NULL};
2014#else
2015 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002016 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002017 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2018 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002019 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002020 "filename", "dbtype", "flags", "mode", NULL};
2021#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002022
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002023#if (DBVER >= 41)
2024 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2025 &filename, &dbname, &type, &flags, &mode,
2026 &txnobj))
2027#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002028 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002029 &filename, &dbname, &type, &flags,
2030 &mode))
2031#endif
2032 {
2033 PyErr_Clear();
2034 type = DB_UNKNOWN; flags = 0; mode = 0660;
2035 filename = NULL; dbname = NULL;
2036#if (DBVER >= 41)
2037 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2038 kwnames_basic,
2039 &filename, &type, &flags, &mode,
2040 &txnobj))
2041 return NULL;
2042#else
2043 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2044 kwnames_basic,
2045 &filename, &type, &flags, &mode))
2046 return NULL;
2047#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002048 }
2049
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002050#if (DBVER >= 41)
2051 if (!checkTxnObj(txnobj, &txn)) return NULL;
2052#endif
2053
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002054 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002055 PyObject *t = Py_BuildValue("(is)", 0,
2056 "Cannot call open() twice for DB object");
2057 PyErr_SetObject(DBError, t);
2058 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002059 return NULL;
2060 }
2061
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002062#if 0 && (DBVER >= 41)
2063 if ((!txn) && (txnobj != Py_None) && self->myenvobj
2064 && (self->myenvobj->flags & DB_INIT_TXN))
2065 {
2066 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
2067 * explicitly passed) but we are in a transaction ready environment:
2068 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
2069 * to work on BerkeleyDB 4.1 without needing to modify their
2070 * DBEnv or DB open calls.
2071 * TODO make this behaviour of the library configurable.
2072 */
2073 flags |= DB_AUTO_COMMIT;
2074 }
2075#endif
2076
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002077 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002078#if (DBVER >= 41)
2079 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2080#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002081 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002082#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002083 MYDB_END_ALLOW_THREADS;
2084 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00002085 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002086 self->db = NULL;
2087 return NULL;
2088 }
2089
2090 self->flags = flags;
2091 RETURN_NONE();
2092}
2093
2094
2095static PyObject*
2096DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2097{
2098 int flags=0;
2099 PyObject* txnobj = NULL;
2100 int dlen = -1;
2101 int doff = -1;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002102 PyObject *keyobj, *dataobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002103 Py_buffer *data_buf_view = NULL;
2104 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002105 DBT key, data;
2106 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002107 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002108 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002109
2110 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2111 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2112 return NULL;
2113
2114 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002115 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002116 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002117 if ( !make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002118 !add_partial_dbt(&data, dlen, doff) ||
2119 !checkTxnObj(txnobj, &txn) )
2120 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002121 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2122 free_buf_view(dataobj, data_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002123 return NULL;
2124 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002125
2126 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002127 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2128 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002129 return NULL;
2130 }
2131
2132 if (flags & DB_APPEND)
2133 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2134 else {
2135 retval = Py_None;
2136 Py_INCREF(retval);
2137 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002138 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2139 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002140 return retval;
2141}
2142
2143
2144
2145static PyObject*
2146DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2147{
2148 char* filename;
2149 char* database = NULL;
2150 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002151 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002152
2153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2154 &filename, &database, &flags))
2155 return NULL;
2156 CHECK_DB_NOT_CLOSED(self);
2157
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002158 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002159 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002160 RETURN_IF_ERR();
2161 RETURN_NONE();
2162}
2163
2164
2165
2166static PyObject*
2167DB_rename(DBObject* self, PyObject* args)
2168{
2169 char* filename;
2170 char* database;
2171 char* newname;
2172 int err, flags=0;
2173
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002174 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2175 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002176 return NULL;
2177 CHECK_DB_NOT_CLOSED(self);
2178
2179 MYDB_BEGIN_ALLOW_THREADS;
2180 err = self->db->rename(self->db, filename, database, newname, flags);
2181 MYDB_END_ALLOW_THREADS;
2182 RETURN_IF_ERR();
2183 RETURN_NONE();
2184}
2185
2186
2187static PyObject*
2188DB_set_bt_minkey(DBObject* self, PyObject* args)
2189{
2190 int err, minkey;
2191
2192 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2193 return NULL;
2194 CHECK_DB_NOT_CLOSED(self);
2195
2196 MYDB_BEGIN_ALLOW_THREADS;
2197 err = self->db->set_bt_minkey(self->db, minkey);
2198 MYDB_END_ALLOW_THREADS;
2199 RETURN_IF_ERR();
2200 RETURN_NONE();
2201}
2202
Neal Norwitz84562352005-10-20 04:30:15 +00002203#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002204static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002205_default_cmp(const DBT *leftKey,
2206 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207{
2208 int res;
2209 int lsize = leftKey->size, rsize = rightKey->size;
2210
Georg Brandlef1701f2006-03-07 14:57:48 +00002211 res = memcmp(leftKey->data, rightKey->data,
2212 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002213
2214 if (res == 0) {
2215 if (lsize < rsize) {
2216 res = -1;
2217 }
2218 else if (lsize > rsize) {
2219 res = 1;
2220 }
2221 }
2222 return res;
2223}
2224
2225static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002226_db_compareCallback(DB* db,
2227 const DBT *leftKey,
2228 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002229{
2230 int res = 0;
2231 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002232 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002233 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002234
2235 if (self == NULL || self->btCompareCallback == NULL) {
2236 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002237 PyErr_SetString(PyExc_TypeError,
2238 (self == 0
2239 ? "DB_bt_compare db is NULL."
2240 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002241 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002242 PyErr_Print();
2243 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002244 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002245 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002246 MYDB_BEGIN_BLOCK_THREADS;
2247
Martin v. Löwis918f49e2007-08-08 22:08:30 +00002248 args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
Thomas Woutersb3153832006-03-08 01:47:19 +00002249 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002250 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002251 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002252 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002253 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002254 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002255 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002256 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002257 PyErr_Print();
2258 res = _default_cmp(leftKey, rightKey);
2259 } else if (PyInt_Check(result)) {
2260 res = PyInt_AsLong(result);
2261 } else {
2262 PyErr_SetString(PyExc_TypeError,
2263 "DB_bt_compare callback MUST return an int.");
2264 /* we're in a callback within the DB code, we can't raise */
2265 PyErr_Print();
2266 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002267 }
2268
Thomas Woutersb3153832006-03-08 01:47:19 +00002269 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002270 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002271
2272 MYDB_END_BLOCK_THREADS;
2273 }
2274 return res;
2275}
2276
2277static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002278DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002279{
2280 int err;
2281 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002282 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002283
Georg Brandlef1701f2006-03-07 14:57:48 +00002284 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002285 return NULL;
2286
Georg Brandlef1701f2006-03-07 14:57:48 +00002287 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002288
Georg Brandlef1701f2006-03-07 14:57:48 +00002289 if (!PyCallable_Check(comparator)) {
2290 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002291 return NULL;
2292 }
2293
2294 /*
2295 * Perform a test call of the comparator function with two empty
2296 * string objects here. verify that it returns an int (0).
2297 * err if not.
2298 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002299 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002300 result = PyEval_CallObject(comparator, tuple);
2301 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002302 if (result == NULL)
2303 return NULL;
2304 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002305 PyErr_SetString(PyExc_TypeError,
2306 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002307 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002308 } else if (PyInt_AsLong(result) != 0) {
2309 PyErr_SetString(PyExc_TypeError,
2310 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002311 return NULL;
2312 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002313 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002314
2315 /* We don't accept multiple set_bt_compare operations, in order to
2316 * simplify the code. This would have no real use, as one cannot
2317 * change the function once the db is opened anyway */
2318 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002319 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002320 return NULL;
2321 }
2322
Georg Brandlef1701f2006-03-07 14:57:48 +00002323 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002324 self->btCompareCallback = comparator;
2325
2326 /* This is to workaround a problem with un-initialized threads (see
2327 comment in DB_associate) */
2328#ifdef WITH_THREAD
2329 PyEval_InitThreads();
2330#endif
2331
Thomas Woutersb3153832006-03-08 01:47:19 +00002332 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002333
2334 if (err) {
2335 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002336 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002337 self->btCompareCallback = NULL;
2338 }
2339
Georg Brandlef1701f2006-03-07 14:57:48 +00002340 RETURN_IF_ERR();
2341 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002342}
Neal Norwitz84562352005-10-20 04:30:15 +00002343#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002344
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002345
2346static PyObject*
2347DB_set_cachesize(DBObject* self, PyObject* args)
2348{
2349 int err;
2350 int gbytes = 0, bytes = 0, ncache = 0;
2351
2352 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2353 &gbytes,&bytes,&ncache))
2354 return NULL;
2355 CHECK_DB_NOT_CLOSED(self);
2356
2357 MYDB_BEGIN_ALLOW_THREADS;
2358 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2359 MYDB_END_ALLOW_THREADS;
2360 RETURN_IF_ERR();
2361 RETURN_NONE();
2362}
2363
2364
2365static PyObject*
2366DB_set_flags(DBObject* self, PyObject* args)
2367{
2368 int err, flags;
2369
2370 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2371 return NULL;
2372 CHECK_DB_NOT_CLOSED(self);
2373
2374 MYDB_BEGIN_ALLOW_THREADS;
2375 err = self->db->set_flags(self->db, flags);
2376 MYDB_END_ALLOW_THREADS;
2377 RETURN_IF_ERR();
2378
2379 self->setflags |= flags;
2380 RETURN_NONE();
2381}
2382
2383
2384static PyObject*
2385DB_set_h_ffactor(DBObject* self, PyObject* args)
2386{
2387 int err, ffactor;
2388
2389 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2390 return NULL;
2391 CHECK_DB_NOT_CLOSED(self);
2392
2393 MYDB_BEGIN_ALLOW_THREADS;
2394 err = self->db->set_h_ffactor(self->db, ffactor);
2395 MYDB_END_ALLOW_THREADS;
2396 RETURN_IF_ERR();
2397 RETURN_NONE();
2398}
2399
2400
2401static PyObject*
2402DB_set_h_nelem(DBObject* self, PyObject* args)
2403{
2404 int err, nelem;
2405
2406 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2407 return NULL;
2408 CHECK_DB_NOT_CLOSED(self);
2409
2410 MYDB_BEGIN_ALLOW_THREADS;
2411 err = self->db->set_h_nelem(self->db, nelem);
2412 MYDB_END_ALLOW_THREADS;
2413 RETURN_IF_ERR();
2414 RETURN_NONE();
2415}
2416
2417
2418static PyObject*
2419DB_set_lorder(DBObject* self, PyObject* args)
2420{
2421 int err, lorder;
2422
2423 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2424 return NULL;
2425 CHECK_DB_NOT_CLOSED(self);
2426
2427 MYDB_BEGIN_ALLOW_THREADS;
2428 err = self->db->set_lorder(self->db, lorder);
2429 MYDB_END_ALLOW_THREADS;
2430 RETURN_IF_ERR();
2431 RETURN_NONE();
2432}
2433
2434
2435static PyObject*
2436DB_set_pagesize(DBObject* self, PyObject* args)
2437{
2438 int err, pagesize;
2439
2440 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2441 return NULL;
2442 CHECK_DB_NOT_CLOSED(self);
2443
2444 MYDB_BEGIN_ALLOW_THREADS;
2445 err = self->db->set_pagesize(self->db, pagesize);
2446 MYDB_END_ALLOW_THREADS;
2447 RETURN_IF_ERR();
2448 RETURN_NONE();
2449}
2450
2451
2452static PyObject*
2453DB_set_re_delim(DBObject* self, PyObject* args)
2454{
2455 int err;
2456 char delim;
2457
2458 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2459 PyErr_Clear();
2460 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2461 return NULL;
2462 }
2463
2464 CHECK_DB_NOT_CLOSED(self);
2465
2466 MYDB_BEGIN_ALLOW_THREADS;
2467 err = self->db->set_re_delim(self->db, delim);
2468 MYDB_END_ALLOW_THREADS;
2469 RETURN_IF_ERR();
2470 RETURN_NONE();
2471}
2472
2473static PyObject*
2474DB_set_re_len(DBObject* self, PyObject* args)
2475{
2476 int err, len;
2477
2478 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2479 return NULL;
2480 CHECK_DB_NOT_CLOSED(self);
2481
2482 MYDB_BEGIN_ALLOW_THREADS;
2483 err = self->db->set_re_len(self->db, len);
2484 MYDB_END_ALLOW_THREADS;
2485 RETURN_IF_ERR();
2486 RETURN_NONE();
2487}
2488
2489
2490static PyObject*
2491DB_set_re_pad(DBObject* self, PyObject* args)
2492{
2493 int err;
2494 char pad;
2495
2496 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2497 PyErr_Clear();
2498 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2499 return NULL;
2500 }
2501 CHECK_DB_NOT_CLOSED(self);
2502
2503 MYDB_BEGIN_ALLOW_THREADS;
2504 err = self->db->set_re_pad(self->db, pad);
2505 MYDB_END_ALLOW_THREADS;
2506 RETURN_IF_ERR();
2507 RETURN_NONE();
2508}
2509
2510
2511static PyObject*
2512DB_set_re_source(DBObject* self, PyObject* args)
2513{
2514 int err;
2515 char *re_source;
2516
2517 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2518 return NULL;
2519 CHECK_DB_NOT_CLOSED(self);
2520
2521 MYDB_BEGIN_ALLOW_THREADS;
2522 err = self->db->set_re_source(self->db, re_source);
2523 MYDB_END_ALLOW_THREADS;
2524 RETURN_IF_ERR();
2525 RETURN_NONE();
2526}
2527
2528
2529#if (DBVER >= 32)
2530static PyObject*
2531DB_set_q_extentsize(DBObject* self, PyObject* args)
2532{
2533 int err;
2534 int extentsize;
2535
2536 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2537 return NULL;
2538 CHECK_DB_NOT_CLOSED(self);
2539
2540 MYDB_BEGIN_ALLOW_THREADS;
2541 err = self->db->set_q_extentsize(self->db, extentsize);
2542 MYDB_END_ALLOW_THREADS;
2543 RETURN_IF_ERR();
2544 RETURN_NONE();
2545}
2546#endif
2547
2548static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002549DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002550{
2551 int err, flags = 0, type;
2552 void* sp;
2553 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002554#if (DBVER >= 43)
2555 PyObject* txnobj = NULL;
2556 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002557 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002558#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002559 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002560#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002561
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002562#if (DBVER >= 43)
2563 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2564 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002565 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002566 if (!checkTxnObj(txnobj, &txn))
2567 return NULL;
2568#else
2569 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2570 return NULL;
2571#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002572 CHECK_DB_NOT_CLOSED(self);
2573
2574 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002575#if (DBVER >= 43)
2576 err = self->db->stat(self->db, txn, &sp, flags);
2577#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002578 err = self->db->stat(self->db, &sp, flags);
2579#else
2580 err = self->db->stat(self->db, &sp, NULL, flags);
2581#endif
2582 MYDB_END_ALLOW_THREADS;
2583 RETURN_IF_ERR();
2584
2585 self->haveStat = 1;
2586
2587 /* Turn the stat structure into a dictionary */
2588 type = _DB_get_type(self);
2589 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2590 free(sp);
2591 return NULL;
2592 }
2593
2594#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2595#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2596#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2597
2598 switch (type) {
2599 case DB_HASH:
2600 MAKE_HASH_ENTRY(magic);
2601 MAKE_HASH_ENTRY(version);
2602 MAKE_HASH_ENTRY(nkeys);
2603 MAKE_HASH_ENTRY(ndata);
2604 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002605#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002606 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002607#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002608 MAKE_HASH_ENTRY(ffactor);
2609 MAKE_HASH_ENTRY(buckets);
2610 MAKE_HASH_ENTRY(free);
2611 MAKE_HASH_ENTRY(bfree);
2612 MAKE_HASH_ENTRY(bigpages);
2613 MAKE_HASH_ENTRY(big_bfree);
2614 MAKE_HASH_ENTRY(overflows);
2615 MAKE_HASH_ENTRY(ovfl_free);
2616 MAKE_HASH_ENTRY(dup);
2617 MAKE_HASH_ENTRY(dup_free);
2618 break;
2619
2620 case DB_BTREE:
2621 case DB_RECNO:
2622 MAKE_BT_ENTRY(magic);
2623 MAKE_BT_ENTRY(version);
2624 MAKE_BT_ENTRY(nkeys);
2625 MAKE_BT_ENTRY(ndata);
2626 MAKE_BT_ENTRY(pagesize);
2627 MAKE_BT_ENTRY(minkey);
2628 MAKE_BT_ENTRY(re_len);
2629 MAKE_BT_ENTRY(re_pad);
2630 MAKE_BT_ENTRY(levels);
2631 MAKE_BT_ENTRY(int_pg);
2632 MAKE_BT_ENTRY(leaf_pg);
2633 MAKE_BT_ENTRY(dup_pg);
2634 MAKE_BT_ENTRY(over_pg);
2635 MAKE_BT_ENTRY(free);
2636 MAKE_BT_ENTRY(int_pgfree);
2637 MAKE_BT_ENTRY(leaf_pgfree);
2638 MAKE_BT_ENTRY(dup_pgfree);
2639 MAKE_BT_ENTRY(over_pgfree);
2640 break;
2641
2642 case DB_QUEUE:
2643 MAKE_QUEUE_ENTRY(magic);
2644 MAKE_QUEUE_ENTRY(version);
2645 MAKE_QUEUE_ENTRY(nkeys);
2646 MAKE_QUEUE_ENTRY(ndata);
2647 MAKE_QUEUE_ENTRY(pagesize);
2648 MAKE_QUEUE_ENTRY(pages);
2649 MAKE_QUEUE_ENTRY(re_len);
2650 MAKE_QUEUE_ENTRY(re_pad);
2651 MAKE_QUEUE_ENTRY(pgfree);
2652#if (DBVER == 31)
2653 MAKE_QUEUE_ENTRY(start);
2654#endif
2655 MAKE_QUEUE_ENTRY(first_recno);
2656 MAKE_QUEUE_ENTRY(cur_recno);
2657 break;
2658
2659 default:
2660 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2661 Py_DECREF(d);
2662 d = NULL;
2663 }
2664
2665#undef MAKE_HASH_ENTRY
2666#undef MAKE_BT_ENTRY
2667#undef MAKE_QUEUE_ENTRY
2668
2669 free(sp);
2670 return d;
2671}
2672
2673static PyObject*
2674DB_sync(DBObject* self, PyObject* args)
2675{
2676 int err;
2677 int flags = 0;
2678
2679 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2680 return NULL;
2681 CHECK_DB_NOT_CLOSED(self);
2682
2683 MYDB_BEGIN_ALLOW_THREADS;
2684 err = self->db->sync(self->db, flags);
2685 MYDB_END_ALLOW_THREADS;
2686 RETURN_IF_ERR();
2687 RETURN_NONE();
2688}
2689
2690
2691#if (DBVER >= 33)
2692static PyObject*
2693DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2694{
2695 int err, flags=0;
2696 u_int32_t count=0;
2697 PyObject* txnobj = NULL;
2698 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002699 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700
2701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2702 &txnobj, &flags))
2703 return NULL;
2704 CHECK_DB_NOT_CLOSED(self);
2705 if (!checkTxnObj(txnobj, &txn))
2706 return NULL;
2707
2708 MYDB_BEGIN_ALLOW_THREADS;
2709 err = self->db->truncate(self->db, txn, &count, flags);
2710 MYDB_END_ALLOW_THREADS;
2711 RETURN_IF_ERR();
2712 return PyInt_FromLong(count);
2713}
2714#endif
2715
2716
2717static PyObject*
2718DB_upgrade(DBObject* self, PyObject* args)
2719{
2720 int err, flags=0;
2721 char *filename;
2722
2723 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2724 return NULL;
2725 CHECK_DB_NOT_CLOSED(self);
2726
2727 MYDB_BEGIN_ALLOW_THREADS;
2728 err = self->db->upgrade(self->db, filename, flags);
2729 MYDB_END_ALLOW_THREADS;
2730 RETURN_IF_ERR();
2731 RETURN_NONE();
2732}
2733
2734
2735static PyObject*
2736DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2737{
2738 int err, flags=0;
2739 char* fileName;
2740 char* dbName=NULL;
2741 char* outFileName=NULL;
2742 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002743 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002744 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002745
2746 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2747 &fileName, &dbName, &outFileName, &flags))
2748 return NULL;
2749
2750 CHECK_DB_NOT_CLOSED(self);
2751 if (outFileName)
2752 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002753 /* XXX(nnorwitz): it should probably be an exception if outFile
2754 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002755
2756 MYDB_BEGIN_ALLOW_THREADS;
2757 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2758 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002759 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002760 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002761
2762 /* DB.verify acts as a DB handle destructor (like close); this was
2763 * documented in BerkeleyDB 4.2 but had the undocumented effect
2764 * of not being safe in prior versions while still requiring an explicit
2765 * DB.close call afterwards. Lets call close for the user to emulate
2766 * the safe 4.2 behaviour. */
2767#if (DBVER <= 41)
2768 self->db->close(self->db, 0);
2769#endif
2770 self->db = NULL;
2771
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002772 RETURN_IF_ERR();
2773 RETURN_NONE();
2774}
2775
2776
2777static PyObject*
2778DB_set_get_returns_none(DBObject* self, PyObject* args)
2779{
2780 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002781 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002782
2783 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2784 return NULL;
2785 CHECK_DB_NOT_CLOSED(self);
2786
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002787 if (self->moduleFlags.getReturnsNone)
2788 ++oldValue;
2789 if (self->moduleFlags.cursorSetReturnsNone)
2790 ++oldValue;
2791 self->moduleFlags.getReturnsNone = (flags >= 1);
2792 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002793 return PyInt_FromLong(oldValue);
2794}
2795
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002796#if (DBVER >= 41)
2797static PyObject*
2798DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2799{
2800 int err;
2801 u_int32_t flags=0;
2802 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002803 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002804
2805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2806 &passwd, &flags)) {
2807 return NULL;
2808 }
2809
2810 MYDB_BEGIN_ALLOW_THREADS;
2811 err = self->db->set_encrypt(self->db, passwd, flags);
2812 MYDB_END_ALLOW_THREADS;
2813
2814 RETURN_IF_ERR();
2815 RETURN_NONE();
2816}
2817#endif /* DBVER >= 41 */
2818
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002819
2820/*-------------------------------------------------------------- */
2821/* Mapping and Dictionary-like access routines */
2822
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002823Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824{
2825 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002826 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002827 int flags = 0;
2828 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002829 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002830
2831 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002832 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2833 PyErr_SetObject(DBError, t);
2834 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 return -1;
2836 }
2837
2838 if (self->haveStat) { /* Has the stat function been called recently? If
2839 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002840 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002841 }
2842
2843 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002844redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002845#if (DBVER >= 43)
2846 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2847#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002848 err = self->db->stat(self->db, &sp, flags);
2849#else
2850 err = self->db->stat(self->db, &sp, NULL, flags);
2851#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002852
2853 /* All the stat structures have matching fields upto the ndata field,
2854 so we can use any of them for the type cast */
2855 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2856
2857 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2858 * redo a full stat to make sure.
2859 * Fixes SF python bug 1493322, pybsddb bug 1184012
2860 */
2861 if (size == 0 && (flags & DB_FAST_STAT)) {
2862 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002863 if (!err)
2864 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002865 goto redo_stat_for_length;
2866 }
2867
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868 MYDB_END_ALLOW_THREADS;
2869
2870 if (err)
2871 return -1;
2872
2873 self->haveStat = 1;
2874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002875 free(sp);
2876 return size;
2877}
2878
2879
2880PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2881{
2882 int err;
2883 PyObject* retval;
Thomas Heller39763a12007-09-24 14:43:56 +00002884 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002885 DBT key;
2886 DBT data;
2887
2888 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002889 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002890 return NULL;
2891
2892 CLEAR_DBT(data);
2893 if (CHECK_DBFLAG(self, DB_THREAD)) {
2894 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2895 data.flags = DB_DBT_MALLOC;
2896 }
2897 MYDB_BEGIN_ALLOW_THREADS;
2898 err = self->db->get(self->db, NULL, &key, &data, 0);
2899 MYDB_END_ALLOW_THREADS;
2900 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2901 PyErr_SetObject(PyExc_KeyError, keyobj);
2902 retval = NULL;
2903 }
2904 else if (makeDBError(err)) {
2905 retval = NULL;
2906 }
2907 else {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00002908 retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002909 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910 }
2911
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002912 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 return retval;
2914}
2915
2916
2917static int
2918DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2919{
2920 DBT key, data;
2921 int retval;
2922 int flags = 0;
Thomas Heller39763a12007-09-24 14:43:56 +00002923 Py_buffer *data_buf_view = NULL;
2924 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925
2926 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002927 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2928 PyErr_SetObject(DBError, t);
2929 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002930 return -1;
2931 }
2932
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002933 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002934 return -1;
2935
2936 if (dataobj != NULL) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002937 if (!make_dbt(dataobj, &data, &data_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002938 retval = -1;
2939 else {
2940 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002941 /* dictionaries shouldn't have duplicate keys */
2942 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002943 retval = _DB_put(self, NULL, &key, &data, flags);
2944
2945 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002946 /* try deleting any old record that matches and then PUT it
2947 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 _DB_delete(self, NULL, &key, 0);
2949 PyErr_Clear();
2950 retval = _DB_put(self, NULL, &key, &data, flags);
2951 }
2952 }
2953 }
2954 else {
2955 /* dataobj == NULL, so delete the key */
2956 retval = _DB_delete(self, NULL, &key, 0);
2957 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002958 FREE_DBT_VIEW(key, keyobj, key_buf_view);
2959 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 return retval;
2961}
2962
2963
2964static PyObject*
2965DB_has_key(DBObject* self, PyObject* args)
2966{
2967 int err;
2968 PyObject* keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00002969 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002970 DBT key, data;
2971 PyObject* txnobj = NULL;
2972 DB_TXN *txn = NULL;
2973
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002974 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975 return NULL;
2976 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002977 if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002978 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002979 if (!checkTxnObj(txnobj, &txn)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002980 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002981 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002982 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002984 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002985 it has a record but can't allocate a buffer for the data. This saves
2986 having to deal with data we won't be using.
2987 */
2988 CLEAR_DBT(data);
2989 data.flags = DB_DBT_USERMEM;
2990
2991 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002992 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002993 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002994 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002995
2996 if (err == DB_BUFFER_SMALL || err == 0) {
2997 return PyInt_FromLong(1);
2998 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2999 return PyInt_FromLong(0);
3000 }
3001
3002 makeDBError(err);
3003 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003004}
3005
3006
3007#define _KEYS_LIST 1
3008#define _VALUES_LIST 2
3009#define _ITEMS_LIST 3
3010
3011static PyObject*
3012_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3013{
3014 int err, dbtype;
3015 DBT key;
3016 DBT data;
3017 DBC *cursor;
3018 PyObject* list;
3019 PyObject* item = NULL;
3020
3021 CHECK_DB_NOT_CLOSED(self);
3022 CLEAR_DBT(key);
3023 CLEAR_DBT(data);
3024
3025 dbtype = _DB_get_type(self);
3026 if (dbtype == -1)
3027 return NULL;
3028
3029 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003030 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003032
3033 /* get a cursor */
3034 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003035 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003036 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003037 if (makeDBError(err)) {
3038 Py_DECREF(list);
3039 return NULL;
3040 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003041
3042 if (CHECK_DBFLAG(self, DB_THREAD)) {
3043 key.flags = DB_DBT_REALLOC;
3044 data.flags = DB_DBT_REALLOC;
3045 }
3046
3047 while (1) { /* use the cursor to traverse the DB, collecting items */
3048 MYDB_BEGIN_ALLOW_THREADS;
3049 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
3050 MYDB_END_ALLOW_THREADS;
3051
3052 if (err) {
3053 /* for any error, break out of the loop */
3054 break;
3055 }
3056
3057 switch (type) {
3058 case _KEYS_LIST:
3059 switch(dbtype) {
3060 case DB_BTREE:
3061 case DB_HASH:
3062 default:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003063 item = PyBytes_FromStringAndSize((char*)key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003064 break;
3065 case DB_RECNO:
3066 case DB_QUEUE:
3067 item = PyInt_FromLong(*((db_recno_t*)key.data));
3068 break;
3069 }
3070 break;
3071
3072 case _VALUES_LIST:
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003073 item = PyBytes_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003074 break;
3075
3076 case _ITEMS_LIST:
3077 switch(dbtype) {
3078 case DB_BTREE:
3079 case DB_HASH:
3080 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003081 item = Py_BuildValue("y#y#", key.data, key.size, data.data,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003082 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003083 break;
3084 case DB_RECNO:
3085 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003086 item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003087 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003088 break;
3089 }
3090 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003091 default:
3092 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3093 item = NULL;
3094 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003095 }
3096 if (item == NULL) {
3097 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003098 list = NULL;
3099 goto done;
3100 }
3101 PyList_Append(list, item);
3102 Py_DECREF(item);
3103 }
3104
Gregory P. Smithe9477062005-06-04 06:46:59 +00003105 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3106 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003107 Py_DECREF(list);
3108 list = NULL;
3109 }
3110
3111 done:
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003112 free_dbt(&key);
3113 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003114 MYDB_BEGIN_ALLOW_THREADS;
3115 cursor->c_close(cursor);
3116 MYDB_END_ALLOW_THREADS;
3117 return list;
3118}
3119
3120
3121static PyObject*
3122DB_keys(DBObject* self, PyObject* args)
3123{
3124 PyObject* txnobj = NULL;
3125 DB_TXN *txn = NULL;
3126
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003127 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 return NULL;
3129 if (!checkTxnObj(txnobj, &txn))
3130 return NULL;
3131 return _DB_make_list(self, txn, _KEYS_LIST);
3132}
3133
3134
3135static PyObject*
3136DB_items(DBObject* self, PyObject* args)
3137{
3138 PyObject* txnobj = NULL;
3139 DB_TXN *txn = NULL;
3140
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003141 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142 return NULL;
3143 if (!checkTxnObj(txnobj, &txn))
3144 return NULL;
3145 return _DB_make_list(self, txn, _ITEMS_LIST);
3146}
3147
3148
3149static PyObject*
3150DB_values(DBObject* self, PyObject* args)
3151{
3152 PyObject* txnobj = NULL;
3153 DB_TXN *txn = NULL;
3154
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003155 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 return NULL;
3157 if (!checkTxnObj(txnobj, &txn))
3158 return NULL;
3159 return _DB_make_list(self, txn, _VALUES_LIST);
3160}
3161
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162/* --------------------------------------------------------------------- */
3163/* DBCursor methods */
3164
3165
3166static PyObject*
3167DBC_close(DBCursorObject* self, PyObject* args)
3168{
3169 int err = 0;
3170
3171 if (!PyArg_ParseTuple(args, ":close"))
3172 return NULL;
3173
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 if (self->dbc != NULL) {
3175 MYDB_BEGIN_ALLOW_THREADS;
3176 err = self->dbc->c_close(self->dbc);
3177 self->dbc = NULL;
3178 MYDB_END_ALLOW_THREADS;
3179 }
3180 RETURN_IF_ERR();
3181 RETURN_NONE();
3182}
3183
3184
3185static PyObject*
3186DBC_count(DBCursorObject* self, PyObject* args)
3187{
3188 int err = 0;
3189 db_recno_t count;
3190 int flags = 0;
3191
3192 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3193 return NULL;
3194
3195 CHECK_CURSOR_NOT_CLOSED(self);
3196
3197 MYDB_BEGIN_ALLOW_THREADS;
3198 err = self->dbc->c_count(self->dbc, &count, flags);
3199 MYDB_END_ALLOW_THREADS;
3200 RETURN_IF_ERR();
3201
3202 return PyInt_FromLong(count);
3203}
3204
3205
3206static PyObject*
3207DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3208{
3209 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3210}
3211
3212
3213static PyObject*
3214DBC_delete(DBCursorObject* self, PyObject* args)
3215{
3216 int err, flags=0;
3217
3218 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3219 return NULL;
3220
3221 CHECK_CURSOR_NOT_CLOSED(self);
3222
3223 MYDB_BEGIN_ALLOW_THREADS;
3224 err = self->dbc->c_del(self->dbc, flags);
3225 MYDB_END_ALLOW_THREADS;
3226 RETURN_IF_ERR();
3227
3228 self->mydb->haveStat = 0;
3229 RETURN_NONE();
3230}
3231
3232
3233static PyObject*
3234DBC_dup(DBCursorObject* self, PyObject* args)
3235{
3236 int err, flags =0;
3237 DBC* dbc = NULL;
3238
3239 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3240 return NULL;
3241
3242 CHECK_CURSOR_NOT_CLOSED(self);
3243
3244 MYDB_BEGIN_ALLOW_THREADS;
3245 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3246 MYDB_END_ALLOW_THREADS;
3247 RETURN_IF_ERR();
3248
3249 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3250}
3251
3252static PyObject*
3253DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3254{
3255 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3256}
3257
3258
3259static PyObject*
3260DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3261{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003262 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003263 PyObject* keyobj = NULL;
3264 PyObject* dataobj = NULL;
3265 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003266 Py_buffer* data_buf_view = NULL;
3267 Py_buffer* key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003268 int dlen = -1;
3269 int doff = -1;
3270 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003271 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003272 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003273
3274 CLEAR_DBT(key);
3275 CLEAR_DBT(data);
3276 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003277 &flags, &dlen, &doff))
3278 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003279 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003280 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3281 &kwnames[1],
3282 &keyobj, &flags, &dlen, &doff))
3283 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003284 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003285 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3286 kwnames, &keyobj, &dataobj,
3287 &flags, &dlen, &doff))
3288 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003289 return NULL;
3290 }
3291 }
3292 }
3293
3294 CHECK_CURSOR_NOT_CLOSED(self);
3295
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003296 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003297 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003298 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003299 (!add_partial_dbt(&data, dlen, doff)) )
3300 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003301 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3302 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003304 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305
3306 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3307 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003308 if (!(key.flags & DB_DBT_REALLOC)) {
3309 key.flags |= DB_DBT_MALLOC;
3310 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003311 }
3312
3313 MYDB_BEGIN_ALLOW_THREADS;
3314 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3315 MYDB_END_ALLOW_THREADS;
3316
Gregory P. Smithe9477062005-06-04 06:46:59 +00003317 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3318 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319 Py_INCREF(Py_None);
3320 retval = Py_None;
3321 }
3322 else if (makeDBError(err)) {
3323 retval = NULL;
3324 }
3325 else {
3326 switch (_DB_get_type(self->mydb)) {
3327 case -1:
3328 retval = NULL;
3329 break;
3330 case DB_BTREE:
3331 case DB_HASH:
3332 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003333 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003334 data.data, data.size);
3335 break;
3336 case DB_RECNO:
3337 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003338 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003339 data.data, data.size);
3340 break;
3341 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003342 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003343 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003344 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3345 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346 return retval;
3347}
3348
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003349#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003350static PyObject*
3351DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3352{
3353 int err, flags=0;
3354 PyObject* keyobj = NULL;
3355 PyObject* dataobj = NULL;
3356 PyObject* retval = NULL;
Thomas Heller39763a12007-09-24 14:43:56 +00003357 Py_buffer* data_buf_view = NULL;
3358 Py_buffer* key_buf_view = NULL;
Gregory P. Smith19699a92004-06-28 04:06:49 +00003359 int dlen = -1;
3360 int doff = -1;
3361 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003362 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3363 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003364
3365 CLEAR_DBT(key);
3366 CLEAR_DBT(data);
3367 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3368 &flags, &dlen, &doff))
3369 {
3370 PyErr_Clear();
3371 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003372 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003373 &keyobj, &flags, &dlen, &doff))
3374 {
3375 PyErr_Clear();
3376 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3377 kwnames, &keyobj, &dataobj,
3378 &flags, &dlen, &doff))
3379 {
3380 return NULL;
3381 }
3382 }
3383 }
3384
3385 CHECK_CURSOR_NOT_CLOSED(self);
3386
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003387 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003388 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003389 if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003390 (!add_partial_dbt(&data, dlen, doff)) ) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003391 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3392 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003393 return NULL;
3394 }
3395
3396 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3397 data.flags = DB_DBT_MALLOC;
3398 if (!(key.flags & DB_DBT_REALLOC)) {
3399 key.flags |= DB_DBT_MALLOC;
3400 }
3401 }
3402
3403 CLEAR_DBT(pkey);
3404 pkey.flags = DB_DBT_MALLOC;
3405
3406 MYDB_BEGIN_ALLOW_THREADS;
3407 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3408 MYDB_END_ALLOW_THREADS;
3409
Gregory P. Smithe9477062005-06-04 06:46:59 +00003410 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3411 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003412 Py_INCREF(Py_None);
3413 retval = Py_None;
3414 }
3415 else if (makeDBError(err)) {
3416 retval = NULL;
3417 }
3418 else {
3419 PyObject *pkeyObj;
3420 PyObject *dataObj;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003421 dataObj = PyBytes_FromStringAndSize(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003422
3423 if (self->mydb->primaryDBType == DB_RECNO ||
3424 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003425 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003426 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003427 pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003428
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003429 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003430 {
3431 PyObject *keyObj;
3432 int type = _DB_get_type(self->mydb);
3433 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003434 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003435 else
Martin v. Löwis64ce5052007-08-05 15:39:16 +00003436 keyObj = PyBytes_FromStringAndSize(key.data, key.size);
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003437 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Thomas Woutersb3153832006-03-08 01:47:19 +00003438 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003439 }
3440 else /* return just the pkey and data */
3441 {
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003442 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003443 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003444 Py_DECREF(dataObj);
3445 Py_DECREF(pkeyObj);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003446 free_dbt(&pkey);
3447 free_dbt(&data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003448 }
3449 /* the only time REALLOC should be set is if we used an integer
3450 * key that make_key_dbt malloc'd for us. always free these. */
3451 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003452 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003453 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003454 free_buf_view(keyobj, key_buf_view);
3455 free_buf_view(dataobj, data_buf_view);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003456 return retval;
3457}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003458#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461static PyObject*
3462DBC_get_recno(DBCursorObject* self, PyObject* args)
3463{
3464 int err;
3465 db_recno_t recno;
3466 DBT key;
3467 DBT data;
3468
3469 if (!PyArg_ParseTuple(args, ":get_recno"))
3470 return NULL;
3471
3472 CHECK_CURSOR_NOT_CLOSED(self);
3473
3474 CLEAR_DBT(key);
3475 CLEAR_DBT(data);
3476 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3477 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3478 data.flags = DB_DBT_MALLOC;
3479 key.flags = DB_DBT_MALLOC;
3480 }
3481
3482 MYDB_BEGIN_ALLOW_THREADS;
3483 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3484 MYDB_END_ALLOW_THREADS;
3485 RETURN_IF_ERR();
3486
3487 recno = *((db_recno_t*)data.data);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003488 free_dbt(&key);
3489 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003490 return PyInt_FromLong(recno);
3491}
3492
3493
3494static PyObject*
3495DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3496{
3497 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3498}
3499
3500
3501static PyObject*
3502DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3503{
3504 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3505}
3506
3507
3508static PyObject*
3509DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3510{
3511 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3512}
3513
3514
3515static PyObject*
3516DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3517{
3518 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003519 PyObject *keyobj, *dataobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003520 Py_buffer *data_buf_view = NULL;
3521 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003522 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003523 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003524 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003525 int dlen = -1;
3526 int doff = -1;
3527
3528 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3529 &keyobj, &dataobj, &flags, &dlen, &doff))
3530 return NULL;
3531
3532 CHECK_CURSOR_NOT_CLOSED(self);
3533
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003534 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003536 if (!make_dbt(dataobj, &data, &data_buf_view) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003537 !add_partial_dbt(&data, dlen, doff) )
3538 {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003539 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3540 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003541 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003542 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543
3544 MYDB_BEGIN_ALLOW_THREADS;
3545 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3546 MYDB_END_ALLOW_THREADS;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003547 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3548 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549 RETURN_IF_ERR();
3550 self->mydb->haveStat = 0;
3551 RETURN_NONE();
3552}
3553
3554
3555static PyObject*
3556DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3557{
3558 int err, flags = 0;
3559 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003560 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003561 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003562 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003563 int dlen = -1;
3564 int doff = -1;
3565
3566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3567 &keyobj, &flags, &dlen, &doff))
3568 return NULL;
3569
3570 CHECK_CURSOR_NOT_CLOSED(self);
3571
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003572 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573 return NULL;
3574
3575 CLEAR_DBT(data);
3576 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3577 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3578 data.flags = DB_DBT_MALLOC;
3579 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003580 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003581 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003583 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584
3585 MYDB_BEGIN_ALLOW_THREADS;
3586 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3587 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3589 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003590 Py_INCREF(Py_None);
3591 retval = Py_None;
3592 }
3593 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 retval = NULL;
3595 }
3596 else {
3597 switch (_DB_get_type(self->mydb)) {
3598 case -1:
3599 retval = NULL;
3600 break;
3601 case DB_BTREE:
3602 case DB_HASH:
3603 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003604 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003605 data.data, data.size);
3606 break;
3607 case DB_RECNO:
3608 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003609 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003610 data.data, data.size);
3611 break;
3612 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003613 free_dbt(&data);
3614 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003615 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003616 /* the only time REALLOC should be set is if we used an integer
3617 * key that make_key_dbt malloc'd for us. always free these. */
3618 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003619 free_dbt(&key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003620 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003621 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003622
3623 return retval;
3624}
3625
3626
3627static PyObject*
3628DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3629{
3630 int err, flags = 0;
3631 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003632 PyObject *retval, *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00003633 Py_buffer *key_buf_view = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003634 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003635 int dlen = -1;
3636 int doff = -1;
3637
3638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3639 &keyobj, &flags, &dlen, &doff))
3640 return NULL;
3641
3642 CHECK_CURSOR_NOT_CLOSED(self);
3643
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003644 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003645 return NULL;
3646
3647 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003648 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003649 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003650 return NULL;
3651 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003652 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3653 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003654 data.flags |= DB_DBT_MALLOC;
3655 /* only BTREE databases will return anything in the key */
3656 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3657 key.flags |= DB_DBT_MALLOC;
3658 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003659 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003660 MYDB_BEGIN_ALLOW_THREADS;
3661 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3662 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003663 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3664 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003665 Py_INCREF(Py_None);
3666 retval = Py_None;
3667 }
3668 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003669 retval = NULL;
3670 }
3671 else {
3672 switch (_DB_get_type(self->mydb)) {
3673 case -1:
3674 retval = NULL;
3675 break;
3676 case DB_BTREE:
3677 case DB_HASH:
3678 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003679 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003680 data.data, data.size);
3681 break;
3682 case DB_RECNO:
3683 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003684 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 data.data, data.size);
3686 break;
3687 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003688 free_dbt(&key);
3689 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003691 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003692 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003693 if (key.flags & DB_DBT_REALLOC) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003694 free_dbt(&key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003695 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003696 free_buf_view(keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697
3698 return retval;
3699}
3700
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003702_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3703 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003705 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003706 DBT key, data;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003707 PyObject *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00003708 Py_buffer *data_buf_view = NULL;
3709 Py_buffer *key_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003710
Gregory P. Smith7441e652003-11-03 21:35:31 +00003711 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003712 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003713 return NULL;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003714 if (!make_dbt(dataobj, &data, &data_buf_view)) {
3715 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003717 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003718
3719 MYDB_BEGIN_ALLOW_THREADS;
3720 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3721 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003722 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003723 Py_INCREF(Py_None);
3724 retval = Py_None;
3725 }
3726 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003727 retval = NULL;
3728 }
3729 else {
3730 switch (_DB_get_type(self->mydb)) {
3731 case -1:
3732 retval = NULL;
3733 break;
3734 case DB_BTREE:
3735 case DB_HASH:
3736 default:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003737 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003738 data.data, data.size);
3739 break;
3740 case DB_RECNO:
3741 case DB_QUEUE:
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003742 retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003743 data.data, data.size);
3744 break;
3745 }
3746 }
3747
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003748 FREE_DBT_VIEW(key, keyobj, key_buf_view);
3749 free_buf_view(dataobj, data_buf_view);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 return retval;
3751}
3752
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003753static PyObject*
3754DBC_get_both(DBCursorObject* self, PyObject* args)
3755{
3756 int flags=0;
3757 PyObject *keyobj, *dataobj;
3758
3759 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3760 return NULL;
3761
Gregory P. Smith7441e652003-11-03 21:35:31 +00003762 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003763 CHECK_CURSOR_NOT_CLOSED(self);
3764
3765 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3766 self->mydb->moduleFlags.getReturnsNone);
3767}
3768
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003769/* Return size of entry */
3770static PyObject*
3771DBC_get_current_size(DBCursorObject* self, PyObject* args)
3772{
3773 int err, flags=DB_CURRENT;
3774 PyObject* retval = NULL;
3775 DBT key, data;
3776
3777 if (!PyArg_ParseTuple(args, ":get_current_size"))
3778 return NULL;
3779 CHECK_CURSOR_NOT_CLOSED(self);
3780 CLEAR_DBT(key);
3781 CLEAR_DBT(data);
3782
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003783 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003784 getting the record size. */
3785 data.flags = DB_DBT_USERMEM;
3786 data.ulen = 0;
3787 MYDB_BEGIN_ALLOW_THREADS;
3788 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3789 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003790 if (err == DB_BUFFER_SMALL || !err) {
3791 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003792 retval = PyInt_FromLong((long)data.size);
3793 err = 0;
3794 }
3795
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003796 free_dbt(&key);
3797 free_dbt(&data);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003798 RETURN_IF_ERR();
3799 return retval;
3800}
3801
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003802static PyObject*
3803DBC_set_both(DBCursorObject* self, PyObject* args)
3804{
3805 int flags=0;
3806 PyObject *keyobj, *dataobj;
3807
3808 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3809 return NULL;
3810
Gregory P. Smith7441e652003-11-03 21:35:31 +00003811 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003812 CHECK_CURSOR_NOT_CLOSED(self);
3813
3814 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3815 self->mydb->moduleFlags.cursorSetReturnsNone);
3816}
3817
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818
3819static PyObject*
3820DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3821{
3822 int err, irecno, flags=0;
3823 db_recno_t recno;
3824 DBT key, data;
3825 PyObject* retval;
3826 int dlen = -1;
3827 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003828 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003829
3830 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3831 &irecno, &flags, &dlen, &doff))
3832 return NULL;
3833
3834 CHECK_CURSOR_NOT_CLOSED(self);
3835
3836 CLEAR_DBT(key);
3837 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003838 /* use allocated space so DB will be able to realloc room for the real
3839 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003840 key.data = malloc(sizeof(db_recno_t));
3841 if (key.data == NULL) {
3842 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3843 return NULL;
3844 }
3845 key.size = sizeof(db_recno_t);
3846 key.ulen = key.size;
3847 memcpy(key.data, &recno, sizeof(db_recno_t));
3848 key.flags = DB_DBT_REALLOC;
3849
3850 CLEAR_DBT(data);
3851 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3852 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3853 data.flags = DB_DBT_MALLOC;
3854 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003855 if (!add_partial_dbt(&data, dlen, doff)) {
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003856 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003857 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003858 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003859
3860 MYDB_BEGIN_ALLOW_THREADS;
3861 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3862 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003863 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3864 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003865 Py_INCREF(Py_None);
3866 retval = Py_None;
3867 }
3868 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003869 retval = NULL;
3870 }
3871 else { /* Can only be used for BTrees, so no need to return int key */
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003872 retval = Py_BuildValue("y#y#", key.data, key.size,
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003873 data.data, data.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003874 free_dbt(&data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003875 }
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003876 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003877
3878 return retval;
3879}
3880
3881
3882static PyObject*
3883DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3884{
3885 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3886}
3887
3888
3889static PyObject*
3890DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3891{
3892 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3893}
3894
3895
3896static PyObject*
3897DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3898{
3899 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3900}
3901
3902
3903static PyObject*
3904DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3905{
3906 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3907}
3908
3909
3910static PyObject*
3911DBC_join_item(DBCursorObject* self, PyObject* args)
3912{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003913 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003914 DBT key, data;
3915 PyObject* retval;
3916
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003917 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003918 return NULL;
3919
3920 CHECK_CURSOR_NOT_CLOSED(self);
3921
3922 CLEAR_DBT(key);
3923 CLEAR_DBT(data);
3924 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3925 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3926 key.flags = DB_DBT_MALLOC;
3927 }
3928
3929 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003930 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003931 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003932 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3933 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003934 Py_INCREF(Py_None);
3935 retval = Py_None;
3936 }
3937 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003938 retval = NULL;
3939 }
3940 else {
Martin v. Löwis918f49e2007-08-08 22:08:30 +00003941 retval = Py_BuildValue("y#", key.data, key.size);
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00003942 free_dbt(&key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003943 }
3944
3945 return retval;
3946}
3947
3948
3949
3950/* --------------------------------------------------------------------- */
3951/* DBEnv methods */
3952
3953
3954static PyObject*
3955DBEnv_close(DBEnvObject* self, PyObject* args)
3956{
3957 int err, flags = 0;
3958
3959 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3960 return NULL;
3961 if (!self->closed) { /* Don't close more than once */
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = self->db_env->close(self->db_env, flags);
3964 MYDB_END_ALLOW_THREADS;
3965 /* after calling DBEnv->close, regardless of error, this DBEnv
3966 * may not be accessed again (BerkeleyDB docs). */
3967 self->closed = 1;
3968 self->db_env = NULL;
3969 RETURN_IF_ERR();
3970 }
3971 RETURN_NONE();
3972}
3973
3974
3975static PyObject*
3976DBEnv_open(DBEnvObject* self, PyObject* args)
3977{
3978 int err, flags=0, mode=0660;
3979 char *db_home;
3980
3981 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3982 return NULL;
3983
3984 CHECK_ENV_NOT_CLOSED(self);
3985
3986 MYDB_BEGIN_ALLOW_THREADS;
3987 err = self->db_env->open(self->db_env, db_home, flags, mode);
3988 MYDB_END_ALLOW_THREADS;
3989 RETURN_IF_ERR();
3990 self->closed = 0;
3991 self->flags = flags;
3992 RETURN_NONE();
3993}
3994
3995
3996static PyObject*
3997DBEnv_remove(DBEnvObject* self, PyObject* args)
3998{
3999 int err, flags=0;
4000 char *db_home;
4001
4002 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4003 return NULL;
4004 CHECK_ENV_NOT_CLOSED(self);
4005 MYDB_BEGIN_ALLOW_THREADS;
4006 err = self->db_env->remove(self->db_env, db_home, flags);
4007 MYDB_END_ALLOW_THREADS;
4008 RETURN_IF_ERR();
4009 RETURN_NONE();
4010}
4011
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004012#if (DBVER >= 41)
4013static PyObject*
4014DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4015{
4016 int err;
4017 u_int32_t flags=0;
4018 char *file = NULL;
4019 char *database = NULL;
4020 PyObject *txnobj = NULL;
4021 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004022 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004023 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004024
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004025 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004026 &file, &database, &txnobj, &flags)) {
4027 return NULL;
4028 }
4029 if (!checkTxnObj(txnobj, &txn)) {
4030 return NULL;
4031 }
4032 CHECK_ENV_NOT_CLOSED(self);
4033 MYDB_BEGIN_ALLOW_THREADS;
4034 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4035 MYDB_END_ALLOW_THREADS;
4036 RETURN_IF_ERR();
4037 RETURN_NONE();
4038}
4039
4040static PyObject*
4041DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4042{
4043 int err;
4044 u_int32_t flags=0;
4045 char *file = NULL;
4046 char *database = NULL;
4047 char *newname = NULL;
4048 PyObject *txnobj = NULL;
4049 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004050 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004051 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004052
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004053 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004054 &file, &database, &newname, &txnobj, &flags)) {
4055 return NULL;
4056 }
4057 if (!checkTxnObj(txnobj, &txn)) {
4058 return NULL;
4059 }
4060 CHECK_ENV_NOT_CLOSED(self);
4061 MYDB_BEGIN_ALLOW_THREADS;
4062 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4063 flags);
4064 MYDB_END_ALLOW_THREADS;
4065 RETURN_IF_ERR();
4066 RETURN_NONE();
4067}
4068
4069static PyObject*
4070DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4071{
4072 int err;
4073 u_int32_t flags=0;
4074 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004075 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004076
4077 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4078 &passwd, &flags)) {
4079 return NULL;
4080 }
4081
4082 MYDB_BEGIN_ALLOW_THREADS;
4083 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4084 MYDB_END_ALLOW_THREADS;
4085
4086 RETURN_IF_ERR();
4087 RETURN_NONE();
4088}
4089#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004090
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004091#if (DBVER >= 40)
4092static PyObject*
4093DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4094{
4095 int err;
4096 u_int32_t flags=0;
4097 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004098 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004099
4100 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4101 &timeout, &flags)) {
4102 return NULL;
4103 }
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4107 MYDB_END_ALLOW_THREADS;
4108
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112#endif /* DBVER >= 40 */
4113
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004115DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4116{
4117 int err;
4118 long shm_key = 0;
4119
4120 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 err = self->db_env->set_shm_key(self->db_env, shm_key);
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4127}
4128
4129static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004130DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4131{
4132 int err, gbytes=0, bytes=0, ncache=0;
4133
4134 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4135 &gbytes, &bytes, &ncache))
4136 return NULL;
4137 CHECK_ENV_NOT_CLOSED(self);
4138
4139 MYDB_BEGIN_ALLOW_THREADS;
4140 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4141 MYDB_END_ALLOW_THREADS;
4142 RETURN_IF_ERR();
4143 RETURN_NONE();
4144}
4145
4146
4147#if (DBVER >= 32)
4148static PyObject*
4149DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4150{
4151 int err, flags=0, onoff=0;
4152
4153 if (!PyArg_ParseTuple(args, "ii:set_flags",
4154 &flags, &onoff))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4157
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_flags(self->db_env, flags, onoff);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4163}
4164#endif
4165
4166
4167static PyObject*
4168DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4169{
4170 int err;
4171 char *dir;
4172
4173 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_data_dir(self->db_env, dir);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184
4185static PyObject*
4186DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4187{
4188 int err, lg_bsize;
4189
4190 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4191 return NULL;
4192 CHECK_ENV_NOT_CLOSED(self);
4193
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4196 MYDB_END_ALLOW_THREADS;
4197 RETURN_IF_ERR();
4198 RETURN_NONE();
4199}
4200
4201
4202static PyObject*
4203DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4204{
4205 int err;
4206 char *dir;
4207
4208 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4209 return NULL;
4210 CHECK_ENV_NOT_CLOSED(self);
4211
4212 MYDB_BEGIN_ALLOW_THREADS;
4213 err = self->db_env->set_lg_dir(self->db_env, dir);
4214 MYDB_END_ALLOW_THREADS;
4215 RETURN_IF_ERR();
4216 RETURN_NONE();
4217}
4218
4219static PyObject*
4220DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4221{
4222 int err, lg_max;
4223
4224 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4225 return NULL;
4226 CHECK_ENV_NOT_CLOSED(self);
4227
4228 MYDB_BEGIN_ALLOW_THREADS;
4229 err = self->db_env->set_lg_max(self->db_env, lg_max);
4230 MYDB_END_ALLOW_THREADS;
4231 RETURN_IF_ERR();
4232 RETURN_NONE();
4233}
4234
4235
Neal Norwitz84562352005-10-20 04:30:15 +00004236#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004237static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004238DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4239{
4240 int err, lg_max;
4241
4242 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4243 return NULL;
4244 CHECK_ENV_NOT_CLOSED(self);
4245
4246 MYDB_BEGIN_ALLOW_THREADS;
4247 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4248 MYDB_END_ALLOW_THREADS;
4249 RETURN_IF_ERR();
4250 RETURN_NONE();
4251}
Neal Norwitz84562352005-10-20 04:30:15 +00004252#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004253
4254
4255static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004256DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4257{
4258 int err, lk_detect;
4259
4260 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4261 return NULL;
4262 CHECK_ENV_NOT_CLOSED(self);
4263
4264 MYDB_BEGIN_ALLOW_THREADS;
4265 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4266 MYDB_END_ALLOW_THREADS;
4267 RETURN_IF_ERR();
4268 RETURN_NONE();
4269}
4270
4271
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004272#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004273static PyObject*
4274DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4275{
4276 int err, max;
4277
4278 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4279 return NULL;
4280 CHECK_ENV_NOT_CLOSED(self);
4281
4282 MYDB_BEGIN_ALLOW_THREADS;
4283 err = self->db_env->set_lk_max(self->db_env, max);
4284 MYDB_END_ALLOW_THREADS;
4285 RETURN_IF_ERR();
4286 RETURN_NONE();
4287}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004289
4290
4291#if (DBVER >= 32)
4292
4293static PyObject*
4294DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4295{
4296 int err, max;
4297
4298 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4299 return NULL;
4300 CHECK_ENV_NOT_CLOSED(self);
4301
4302 MYDB_BEGIN_ALLOW_THREADS;
4303 err = self->db_env->set_lk_max_locks(self->db_env, max);
4304 MYDB_END_ALLOW_THREADS;
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307}
4308
4309
4310static PyObject*
4311DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4312{
4313 int err, max;
4314
4315 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4316 return NULL;
4317 CHECK_ENV_NOT_CLOSED(self);
4318
4319 MYDB_BEGIN_ALLOW_THREADS;
4320 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4321 MYDB_END_ALLOW_THREADS;
4322 RETURN_IF_ERR();
4323 RETURN_NONE();
4324}
4325
4326
4327static PyObject*
4328DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4329{
4330 int err, max;
4331
4332 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4333 return NULL;
4334 CHECK_ENV_NOT_CLOSED(self);
4335
4336 MYDB_BEGIN_ALLOW_THREADS;
4337 err = self->db_env->set_lk_max_objects(self->db_env, max);
4338 MYDB_END_ALLOW_THREADS;
4339 RETURN_IF_ERR();
4340 RETURN_NONE();
4341}
4342
4343#endif
4344
4345
4346static PyObject*
4347DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4348{
4349 int err, mp_mmapsize;
4350
4351 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4352 return NULL;
4353 CHECK_ENV_NOT_CLOSED(self);
4354
4355 MYDB_BEGIN_ALLOW_THREADS;
4356 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4357 MYDB_END_ALLOW_THREADS;
4358 RETURN_IF_ERR();
4359 RETURN_NONE();
4360}
4361
4362
4363static PyObject*
4364DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4365{
4366 int err;
4367 char *dir;
4368
4369 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4370 return NULL;
4371 CHECK_ENV_NOT_CLOSED(self);
4372
4373 MYDB_BEGIN_ALLOW_THREADS;
4374 err = self->db_env->set_tmp_dir(self->db_env, dir);
4375 MYDB_END_ALLOW_THREADS;
4376 RETURN_IF_ERR();
4377 RETURN_NONE();
4378}
4379
4380
4381static PyObject*
4382DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4383{
4384 int flags = 0;
4385 PyObject* txnobj = NULL;
4386 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004387 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004388
4389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4390 &txnobj, &flags))
4391 return NULL;
4392
4393 if (!checkTxnObj(txnobj, &txn))
4394 return NULL;
4395 CHECK_ENV_NOT_CLOSED(self);
4396
4397 return (PyObject*)newDBTxnObject(self, txn, flags);
4398}
4399
4400
4401static PyObject*
4402DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4403{
4404 int err, kbyte=0, min=0, flags=0;
4405
4406 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4407 return NULL;
4408 CHECK_ENV_NOT_CLOSED(self);
4409
4410 MYDB_BEGIN_ALLOW_THREADS;
4411#if (DBVER >= 40)
4412 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4413#else
4414 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4415#endif
4416 MYDB_END_ALLOW_THREADS;
4417 RETURN_IF_ERR();
4418 RETURN_NONE();
4419}
4420
4421
4422static PyObject*
4423DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4424{
4425 int err, max;
4426
4427 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4428 return NULL;
4429 CHECK_ENV_NOT_CLOSED(self);
4430
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004431 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004432 RETURN_IF_ERR();
4433 RETURN_NONE();
4434}
4435
4436
4437static PyObject*
4438DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4439{
4440 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004441 long stamp;
4442 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004443
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004444 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004445 return NULL;
4446 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004447 timestamp = (time_t)stamp;
4448 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004449 RETURN_IF_ERR();
4450 RETURN_NONE();
4451}
4452
4453
4454static PyObject*
4455DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4456{
4457 int err, atype, flags=0;
4458 int aborted = 0;
4459
4460 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4461 return NULL;
4462 CHECK_ENV_NOT_CLOSED(self);
4463
4464 MYDB_BEGIN_ALLOW_THREADS;
4465#if (DBVER >= 40)
4466 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4467#else
4468 err = lock_detect(self->db_env, flags, atype, &aborted);
4469#endif
4470 MYDB_END_ALLOW_THREADS;
4471 RETURN_IF_ERR();
4472 return PyInt_FromLong(aborted);
4473}
4474
4475
4476static PyObject*
4477DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4478{
4479 int flags=0;
4480 int locker, lock_mode;
4481 DBT obj;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004482 PyObject *objobj, *retval;
Thomas Heller39763a12007-09-24 14:43:56 +00004483 Py_buffer *obj_buf_view = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004484
4485 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4486 return NULL;
4487
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004488 if (!make_dbt(objobj, &obj, &obj_buf_view))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004489 return NULL;
4490
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00004491 retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4492 free_buf_view(objobj, obj_buf_view);
4493 return retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004494}
4495
4496
4497static PyObject*
4498DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4499{
4500 int err;
4501 u_int32_t theID;
4502
4503 if (!PyArg_ParseTuple(args, ":lock_id"))
4504 return NULL;
4505
4506 CHECK_ENV_NOT_CLOSED(self);
4507 MYDB_BEGIN_ALLOW_THREADS;
4508#if (DBVER >= 40)
4509 err = self->db_env->lock_id(self->db_env, &theID);
4510#else
4511 err = lock_id(self->db_env, &theID);
4512#endif
4513 MYDB_END_ALLOW_THREADS;
4514 RETURN_IF_ERR();
4515
4516 return PyInt_FromLong((long)theID);
4517}
4518
4519
4520static PyObject*
4521DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4522{
4523 int err;
4524 DBLockObject* dblockobj;
4525
4526 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4527 return NULL;
4528
4529 CHECK_ENV_NOT_CLOSED(self);
4530 MYDB_BEGIN_ALLOW_THREADS;
4531#if (DBVER >= 40)
4532 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4533#else
4534 err = lock_put(self->db_env, &dblockobj->lock);
4535#endif
4536 MYDB_END_ALLOW_THREADS;
4537 RETURN_IF_ERR();
4538 RETURN_NONE();
4539}
4540
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004541#if (DBVER >= 44)
4542static PyObject*
4543DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4544{
4545 int err;
4546 char *file;
4547 u_int32_t flags = 0;
4548 static char* kwnames[] = { "file", "flags", NULL};
4549
4550 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4551 &file, &flags))
4552 return NULL;
4553 CHECK_ENV_NOT_CLOSED(self);
4554
4555 MYDB_BEGIN_ALLOW_THREADS;
4556 err = self->db_env->lsn_reset(self->db_env, file, flags);
4557 MYDB_END_ALLOW_THREADS;
4558 RETURN_IF_ERR();
4559 RETURN_NONE();
4560}
4561#endif /* DBVER >= 4.4 */
4562
4563#if (DBVER >= 40)
4564static PyObject*
4565DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4566{
4567 int err;
4568 DB_LOG_STAT* statp = NULL;
4569 PyObject* d = NULL;
4570 u_int32_t flags = 0;
4571
4572 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4573 return NULL;
4574 CHECK_ENV_NOT_CLOSED(self);
4575
4576 MYDB_BEGIN_ALLOW_THREADS;
4577 err = self->db_env->log_stat(self->db_env, &statp, flags);
4578 MYDB_END_ALLOW_THREADS;
4579 RETURN_IF_ERR();
4580
4581 /* Turn the stat structure into a dictionary */
4582 d = PyDict_New();
4583 if (d == NULL) {
4584 if (statp)
4585 free(statp);
4586 return NULL;
4587 }
4588
4589#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4590
4591 MAKE_ENTRY(magic);
4592 MAKE_ENTRY(version);
4593 MAKE_ENTRY(mode);
4594 MAKE_ENTRY(lg_bsize);
4595#if (DBVER >= 44)
4596 MAKE_ENTRY(lg_size);
4597 MAKE_ENTRY(record);
4598#endif
4599#if (DBVER <= 40)
4600 MAKE_ENTRY(lg_max);
4601#endif
4602 MAKE_ENTRY(w_mbytes);
4603 MAKE_ENTRY(w_bytes);
4604 MAKE_ENTRY(wc_mbytes);
4605 MAKE_ENTRY(wc_bytes);
4606 MAKE_ENTRY(wcount);
4607 MAKE_ENTRY(wcount_fill);
4608#if (DBVER >= 44)
4609 MAKE_ENTRY(rcount);
4610#endif
4611 MAKE_ENTRY(scount);
4612 MAKE_ENTRY(cur_file);
4613 MAKE_ENTRY(cur_offset);
4614 MAKE_ENTRY(disk_file);
4615 MAKE_ENTRY(disk_offset);
4616 MAKE_ENTRY(maxcommitperflush);
4617 MAKE_ENTRY(mincommitperflush);
4618 MAKE_ENTRY(regsize);
4619 MAKE_ENTRY(region_wait);
4620 MAKE_ENTRY(region_nowait);
4621
4622#undef MAKE_ENTRY
4623 free(statp);
4624 return d;
4625} /* DBEnv_log_stat */
4626#endif /* DBVER >= 4.0 for log_stat method */
4627
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004628
4629static PyObject*
4630DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4631{
4632 int err;
4633 DB_LOCK_STAT* sp;
4634 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004635 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004636
4637 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4638 return NULL;
4639 CHECK_ENV_NOT_CLOSED(self);
4640
4641 MYDB_BEGIN_ALLOW_THREADS;
4642#if (DBVER >= 40)
4643 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4644#else
4645#if (DBVER >= 33)
4646 err = lock_stat(self->db_env, &sp);
4647#else
4648 err = lock_stat(self->db_env, &sp, NULL);
4649#endif
4650#endif
4651 MYDB_END_ALLOW_THREADS;
4652 RETURN_IF_ERR();
4653
4654 /* Turn the stat structure into a dictionary */
4655 d = PyDict_New();
4656 if (d == NULL) {
4657 free(sp);
4658 return NULL;
4659 }
4660
4661#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4662
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004663#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004665#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004666 MAKE_ENTRY(nmodes);
4667#if (DBVER >= 32)
4668 MAKE_ENTRY(maxlocks);
4669 MAKE_ENTRY(maxlockers);
4670 MAKE_ENTRY(maxobjects);
4671 MAKE_ENTRY(nlocks);
4672 MAKE_ENTRY(maxnlocks);
4673#endif
4674 MAKE_ENTRY(nlockers);
4675 MAKE_ENTRY(maxnlockers);
4676#if (DBVER >= 32)
4677 MAKE_ENTRY(nobjects);
4678 MAKE_ENTRY(maxnobjects);
4679#endif
4680 MAKE_ENTRY(nrequests);
4681 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004682#if (DBVER < 44)
4683 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004685#else
4686 MAKE_ENTRY(lock_nowait);
4687 MAKE_ENTRY(lock_wait);
4688#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004689 MAKE_ENTRY(ndeadlocks);
4690 MAKE_ENTRY(regsize);
4691 MAKE_ENTRY(region_wait);
4692 MAKE_ENTRY(region_nowait);
4693
4694#undef MAKE_ENTRY
4695 free(sp);
4696 return d;
4697}
4698
4699
4700static PyObject*
4701DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4702{
4703 int flags=0;
4704 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004705 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004706 PyObject* list;
4707 PyObject* item = NULL;
4708
4709 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4710 return NULL;
4711
4712 CHECK_ENV_NOT_CLOSED(self);
4713 MYDB_BEGIN_ALLOW_THREADS;
4714#if (DBVER >= 40)
4715 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4716#elif (DBVER == 33)
4717 err = log_archive(self->db_env, &log_list, flags);
4718#else
4719 err = log_archive(self->db_env, &log_list, flags, NULL);
4720#endif
4721 MYDB_END_ALLOW_THREADS;
4722 RETURN_IF_ERR();
4723
4724 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004725 if (list == NULL) {
4726 if (log_list)
4727 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004728 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004729 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730
4731 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004732 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004733 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Martin v. Löwis64ce5052007-08-05 15:39:16 +00004734 item = PyUnicode_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004735 if (item == NULL) {
4736 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004737 list = NULL;
4738 break;
4739 }
4740 PyList_Append(list, item);
4741 Py_DECREF(item);
4742 }
4743 free(log_list_start);
4744 }
4745 return list;
4746}
4747
4748
4749static PyObject*
4750DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4751{
4752 int err;
4753 DB_TXN_STAT* sp;
4754 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004755 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004756
4757 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4758 return NULL;
4759 CHECK_ENV_NOT_CLOSED(self);
4760
4761 MYDB_BEGIN_ALLOW_THREADS;
4762#if (DBVER >= 40)
4763 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4764#elif (DBVER == 33)
4765 err = txn_stat(self->db_env, &sp);
4766#else
4767 err = txn_stat(self->db_env, &sp, NULL);
4768#endif
4769 MYDB_END_ALLOW_THREADS;
4770 RETURN_IF_ERR();
4771
4772 /* Turn the stat structure into a dictionary */
4773 d = PyDict_New();
4774 if (d == NULL) {
4775 free(sp);
4776 return NULL;
4777 }
4778
4779#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00004780#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004781
Guido van Rossumd8faa362007-04-27 19:54:29 +00004782 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004783 MAKE_ENTRY(last_txnid);
4784 MAKE_ENTRY(maxtxns);
4785 MAKE_ENTRY(nactive);
4786 MAKE_ENTRY(maxnactive);
4787 MAKE_ENTRY(nbegins);
4788 MAKE_ENTRY(naborts);
4789 MAKE_ENTRY(ncommits);
4790 MAKE_ENTRY(regsize);
4791 MAKE_ENTRY(region_wait);
4792 MAKE_ENTRY(region_nowait);
4793
4794#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004795#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004796 free(sp);
4797 return d;
4798}
4799
4800
4801static PyObject*
4802DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4803{
4804 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004805 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004806
4807 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4808 return NULL;
4809 CHECK_ENV_NOT_CLOSED(self);
4810
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004811 if (self->moduleFlags.getReturnsNone)
4812 ++oldValue;
4813 if (self->moduleFlags.cursorSetReturnsNone)
4814 ++oldValue;
4815 self->moduleFlags.getReturnsNone = (flags >= 1);
4816 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004817 return PyInt_FromLong(oldValue);
4818}
4819
4820
4821/* --------------------------------------------------------------------- */
4822/* DBTxn methods */
4823
4824
4825static PyObject*
4826DBTxn_commit(DBTxnObject* self, PyObject* args)
4827{
4828 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004829 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004830
4831 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4832 return NULL;
4833
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004834 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004835 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4836 "after txn_commit or txn_abort");
4837 PyErr_SetObject(DBError, t);
4838 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004839 return NULL;
4840 }
4841 txn = self->txn;
4842 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004843 MYDB_BEGIN_ALLOW_THREADS;
4844#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004845 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004846#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004847 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004848#endif
4849 MYDB_END_ALLOW_THREADS;
4850 RETURN_IF_ERR();
4851 RETURN_NONE();
4852}
4853
4854static PyObject*
4855DBTxn_prepare(DBTxnObject* self, PyObject* args)
4856{
4857#if (DBVER >= 33)
4858 int err;
4859 char* gid=NULL;
4860 int gid_size=0;
4861
Gregory P. Smith361ed152007-08-23 07:32:27 +00004862 if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004863 return NULL;
4864
4865 if (gid_size != DB_XIDDATASIZE) {
4866 PyErr_SetString(PyExc_TypeError,
4867 "gid must be DB_XIDDATASIZE bytes long");
4868 return NULL;
4869 }
4870
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004871 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004872 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4873 "after txn_commit or txn_abort");
4874 PyErr_SetObject(DBError, t);
4875 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004876 return NULL;
4877 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004878 MYDB_BEGIN_ALLOW_THREADS;
4879#if (DBVER >= 40)
4880 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4881#else
4882 err = txn_prepare(self->txn, (u_int8_t*)gid);
4883#endif
4884 MYDB_END_ALLOW_THREADS;
4885 RETURN_IF_ERR();
4886 RETURN_NONE();
4887#else
4888 int err;
4889
4890 if (!PyArg_ParseTuple(args, ":prepare"))
4891 return NULL;
4892
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004893 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004894 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4895 "after txn_commit or txn_abort");
4896 PyErr_SetObject(DBError, t);
4897 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004898 return NULL;
4899 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004900 MYDB_BEGIN_ALLOW_THREADS;
4901 err = txn_prepare(self->txn);
4902 MYDB_END_ALLOW_THREADS;
4903 RETURN_IF_ERR();
4904 RETURN_NONE();
4905#endif
4906}
4907
4908
4909static PyObject*
4910DBTxn_abort(DBTxnObject* self, PyObject* args)
4911{
4912 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004913 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004914
4915 if (!PyArg_ParseTuple(args, ":abort"))
4916 return NULL;
4917
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004918 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004919 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4920 "after txn_commit or txn_abort");
4921 PyErr_SetObject(DBError, t);
4922 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004923 return NULL;
4924 }
4925 txn = self->txn;
4926 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004927 MYDB_BEGIN_ALLOW_THREADS;
4928#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004929 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004930#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004931 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004932#endif
4933 MYDB_END_ALLOW_THREADS;
4934 RETURN_IF_ERR();
4935 RETURN_NONE();
4936}
4937
4938
4939static PyObject*
4940DBTxn_id(DBTxnObject* self, PyObject* args)
4941{
4942 int id;
4943
4944 if (!PyArg_ParseTuple(args, ":id"))
4945 return NULL;
4946
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004947 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004948 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4949 "after txn_commit or txn_abort");
4950 PyErr_SetObject(DBError, t);
4951 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004952 return NULL;
4953 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004954 MYDB_BEGIN_ALLOW_THREADS;
4955#if (DBVER >= 40)
4956 id = self->txn->id(self->txn);
4957#else
4958 id = txn_id(self->txn);
4959#endif
4960 MYDB_END_ALLOW_THREADS;
4961 return PyInt_FromLong(id);
4962}
4963
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004964#if (DBVER >= 43)
4965/* --------------------------------------------------------------------- */
4966/* DBSequence methods */
4967
4968
4969static PyObject*
4970DBSequence_close(DBSequenceObject* self, PyObject* args)
4971{
4972 int err, flags=0;
4973 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4974 return NULL;
4975 CHECK_SEQUENCE_NOT_CLOSED(self)
4976
4977 MYDB_BEGIN_ALLOW_THREADS
4978 err = self->sequence->close(self->sequence, flags);
4979 self->sequence = NULL;
4980 MYDB_END_ALLOW_THREADS
4981
4982 RETURN_IF_ERR();
4983
4984 RETURN_NONE();
4985}
4986
4987static PyObject*
4988DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4989{
4990 int err, flags = 0;
4991 int delta = 1;
4992 db_seq_t value;
4993 PyObject *txnobj = NULL;
4994 DB_TXN *txn = NULL;
4995 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4996 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4997 return NULL;
4998 CHECK_SEQUENCE_NOT_CLOSED(self)
4999
5000 if (!checkTxnObj(txnobj, &txn))
5001 return NULL;
5002
5003 MYDB_BEGIN_ALLOW_THREADS
5004 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5005 MYDB_END_ALLOW_THREADS
5006
5007 RETURN_IF_ERR();
5008 return PyLong_FromLongLong(value);
5009
5010}
5011
5012static PyObject*
5013DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5014{
5015 if (!PyArg_ParseTuple(args,":get_dbp"))
5016 return NULL;
5017 CHECK_SEQUENCE_NOT_CLOSED(self)
5018 Py_INCREF(self->mydb);
5019 return (PyObject* )self->mydb;
5020}
5021
5022static PyObject*
5023DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5024{
5025 int err;
5026 DBT key;
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00005027 PyObject *retval;
5028 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005029 CHECK_SEQUENCE_NOT_CLOSED(self)
5030 MYDB_BEGIN_ALLOW_THREADS
5031 err = self->sequence->get_key(self->sequence, &key);
5032 MYDB_END_ALLOW_THREADS
5033
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00005034 if (!err)
5035 retval = PyBytes_FromStringAndSize(key.data, key.size);
5036
5037 free_dbt(&key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005038 RETURN_IF_ERR();
5039
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00005040 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005041}
5042
5043static PyObject*
5044DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5045{
5046 int err;
5047 db_seq_t value;
5048 if (!PyArg_ParseTuple(args,"L:init_value", &value))
5049 return NULL;
5050 CHECK_SEQUENCE_NOT_CLOSED(self)
5051
5052 MYDB_BEGIN_ALLOW_THREADS
5053 err = self->sequence->initial_value(self->sequence, value);
5054 MYDB_END_ALLOW_THREADS
5055
5056 RETURN_IF_ERR();
5057
5058 RETURN_NONE();
5059}
5060
5061static PyObject*
5062DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5063{
5064 int err, flags = 0;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00005065 PyObject *keyobj;
Thomas Heller39763a12007-09-24 14:43:56 +00005066 Py_buffer *key_buf_view = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005067 PyObject *txnobj = NULL;
5068 DB_TXN *txn = NULL;
5069 DBT key;
5070
5071 static char* kwnames[] = {"key", "txn", "flags", NULL };
5072 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
5073 return NULL;
5074
5075 if (!checkTxnObj(txnobj, &txn))
5076 return NULL;
5077
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00005078 if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005079 return NULL;
5080
5081 MYDB_BEGIN_ALLOW_THREADS
5082 err = self->sequence->open(self->sequence, txn, &key, flags);
5083 MYDB_END_ALLOW_THREADS
5084
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00005085 FREE_DBT_VIEW(key, keyobj, key_buf_view);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005086 RETURN_IF_ERR();
5087
5088 RETURN_NONE();
5089}
5090
5091static PyObject*
5092DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5093{
5094 int err, flags = 0;
5095 PyObject *txnobj = NULL;
5096 DB_TXN *txn = NULL;
5097
5098 static char* kwnames[] = {"txn", "flags", NULL };
5099 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
5100 return NULL;
5101
5102 if (!checkTxnObj(txnobj, &txn))
5103 return NULL;
5104
5105 CHECK_SEQUENCE_NOT_CLOSED(self)
5106
5107 MYDB_BEGIN_ALLOW_THREADS
5108 err = self->sequence->remove(self->sequence, txn, flags);
5109 MYDB_END_ALLOW_THREADS
5110
5111 RETURN_IF_ERR();
5112 RETURN_NONE();
5113}
5114
5115static PyObject*
5116DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5117{
5118 int err, size;
5119 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5120 return NULL;
5121 CHECK_SEQUENCE_NOT_CLOSED(self)
5122
5123 MYDB_BEGIN_ALLOW_THREADS
5124 err = self->sequence->set_cachesize(self->sequence, size);
5125 MYDB_END_ALLOW_THREADS
5126
5127 RETURN_IF_ERR();
5128 RETURN_NONE();
5129}
5130
5131static PyObject*
5132DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5133{
5134 int err, size;
5135 if (!PyArg_ParseTuple(args,":get_cachesize"))
5136 return NULL;
5137 CHECK_SEQUENCE_NOT_CLOSED(self)
5138
5139 MYDB_BEGIN_ALLOW_THREADS
5140 err = self->sequence->get_cachesize(self->sequence, &size);
5141 MYDB_END_ALLOW_THREADS
5142
5143 RETURN_IF_ERR();
5144 return PyInt_FromLong(size);
5145}
5146
5147static PyObject*
5148DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5149{
5150 int err, flags = 0;
5151 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5152 return NULL;
5153 CHECK_SEQUENCE_NOT_CLOSED(self)
5154
5155 MYDB_BEGIN_ALLOW_THREADS
5156 err = self->sequence->set_flags(self->sequence, flags);
5157 MYDB_END_ALLOW_THREADS
5158
5159 RETURN_IF_ERR();
5160 RETURN_NONE();
5161
5162}
5163
5164static PyObject*
5165DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5166{
5167 unsigned int flags;
5168 int err;
5169 if (!PyArg_ParseTuple(args,":get_flags"))
5170 return NULL;
5171 CHECK_SEQUENCE_NOT_CLOSED(self)
5172
5173 MYDB_BEGIN_ALLOW_THREADS
5174 err = self->sequence->get_flags(self->sequence, &flags);
5175 MYDB_END_ALLOW_THREADS
5176
5177 RETURN_IF_ERR();
5178 return PyInt_FromLong((int)flags);
5179}
5180
5181static PyObject*
5182DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5183{
5184 int err;
5185 db_seq_t min, max;
5186 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5187 return NULL;
5188 CHECK_SEQUENCE_NOT_CLOSED(self)
5189
5190 MYDB_BEGIN_ALLOW_THREADS
5191 err = self->sequence->set_range(self->sequence, min, max);
5192 MYDB_END_ALLOW_THREADS
5193
5194 RETURN_IF_ERR();
5195 RETURN_NONE();
5196}
5197
5198static PyObject*
5199DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5200{
5201 int err;
5202 db_seq_t min, max;
5203 if (!PyArg_ParseTuple(args,":get_range"))
5204 return NULL;
5205 CHECK_SEQUENCE_NOT_CLOSED(self)
5206
5207 MYDB_BEGIN_ALLOW_THREADS
5208 err = self->sequence->get_range(self->sequence, &min, &max);
5209 MYDB_END_ALLOW_THREADS
5210
5211 RETURN_IF_ERR();
5212 return Py_BuildValue("(LL)", min, max);
5213}
5214
5215static PyObject*
5216DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5217{
5218 int err, flags = 0;
5219 DB_SEQUENCE_STAT* sp = NULL;
5220 PyObject* dict_stat;
5221 static char* kwnames[] = {"flags", NULL };
5222 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5223 return NULL;
5224 CHECK_SEQUENCE_NOT_CLOSED(self);
5225
5226 MYDB_BEGIN_ALLOW_THREADS;
5227 err = self->sequence->stat(self->sequence, &sp, flags);
5228 MYDB_END_ALLOW_THREADS;
5229 RETURN_IF_ERR();
5230
5231 if ((dict_stat = PyDict_New()) == NULL) {
5232 free(sp);
5233 return NULL;
5234 }
5235
5236
5237#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5238#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5239
5240 MAKE_INT_ENTRY(wait);
5241 MAKE_INT_ENTRY(nowait);
5242 MAKE_LONG_LONG_ENTRY(current);
5243 MAKE_LONG_LONG_ENTRY(value);
5244 MAKE_LONG_LONG_ENTRY(last_value);
5245 MAKE_LONG_LONG_ENTRY(min);
5246 MAKE_LONG_LONG_ENTRY(max);
5247 MAKE_INT_ENTRY(cache_size);
5248 MAKE_INT_ENTRY(flags);
5249
5250#undef MAKE_INT_ENTRY
5251#undef MAKE_LONG_LONG_ENTRY
5252
5253 free(sp);
5254 return dict_stat;
5255}
5256#endif
5257
5258
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005259/* --------------------------------------------------------------------- */
5260/* Method definition tables and type objects */
5261
5262static PyMethodDef DB_methods[] = {
5263 {"append", (PyCFunction)DB_append, METH_VARARGS},
5264#if (DBVER >= 33)
5265 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5266#endif
5267 {"close", (PyCFunction)DB_close, METH_VARARGS},
5268#if (DBVER >= 32)
5269 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5270 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5271#endif
5272 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5273 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5274 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5275 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005276#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005277 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005278#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005279 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5280 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5281 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5282 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5283 {"join", (PyCFunction)DB_join, METH_VARARGS},
5284 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5285 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5286 {"items", (PyCFunction)DB_items, METH_VARARGS},
5287 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5288 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5289 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5290 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5291 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5292 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005293#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005294 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005295#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005296 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005297#if (DBVER >= 41)
5298 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005300 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5301 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5302 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5303 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5304 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5305 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5306 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5307 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5308 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5309#if (DBVER >= 32)
5310 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5311#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005312 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005313 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5314#if (DBVER >= 33)
5315 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5316#endif
5317 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5318 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5319 {"values", (PyCFunction)DB_values, METH_VARARGS},
5320 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5321 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5322 {NULL, NULL} /* sentinel */
5323};
5324
5325
5326static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005327 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005328 (binaryfunc)DB_subscript, /*mp_subscript*/
5329 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5330};
5331
5332
5333static PyMethodDef DBCursor_methods[] = {
5334 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5335 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5336 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5337 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5338 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5339 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5340 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005341#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005342 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005343#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005344 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5345 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5346 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5347 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5348 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5349 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5350 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5351 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005352 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005353 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005354 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5355 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5356 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5357 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5358 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5359 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5360 {NULL, NULL} /* sentinel */
5361};
5362
5363
5364static PyMethodDef DBEnv_methods[] = {
5365 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5366 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5367 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005368#if (DBVER >= 41)
5369 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5370 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5371 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5372#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005373#if (DBVER >= 40)
5374 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5375#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005376 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005377 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5378 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5379#if (DBVER >= 32)
5380 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5381#endif
5382 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5383 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5384 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005385#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005386 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005387#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005388 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005389#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005390 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005391#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005392#if (DBVER >= 32)
5393 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5394 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5395 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5396#endif
5397 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5398 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5399 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5400 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5401 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5402 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005403 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005404 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5405 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5406 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5407 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5408 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5409 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005410#if (DBVER >= 40)
5411 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5412#endif
5413#if (DBVER >= 44)
5414 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5415#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005416 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5417 {NULL, NULL} /* sentinel */
5418};
5419
5420
5421static PyMethodDef DBTxn_methods[] = {
5422 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5423 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5424 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5425 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5426 {NULL, NULL} /* sentinel */
5427};
5428
5429
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005430#if (DBVER >= 43)
5431static PyMethodDef DBSequence_methods[] = {
5432 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5433 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5434 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5435 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5436 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5437 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5438 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5439 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5440 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5441 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5442 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5443 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5444 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5445 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5446 {NULL, NULL} /* sentinel */
5447};
5448#endif
5449
5450
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005451static PyObject*
5452DB_getattr(DBObject* self, char *name)
5453{
5454 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5455}
5456
5457
5458static PyObject*
5459DBEnv_getattr(DBEnvObject* self, char *name)
5460{
5461 if (!strcmp(name, "db_home")) {
5462 CHECK_ENV_NOT_CLOSED(self);
5463 if (self->db_env->db_home == NULL) {
5464 RETURN_NONE();
5465 }
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005466 return PyUnicode_FromString(self->db_env->db_home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005467 }
5468
5469 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5470}
5471
5472
5473static PyObject*
5474DBCursor_getattr(DBCursorObject* self, char *name)
5475{
5476 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5477}
5478
5479static PyObject*
5480DBTxn_getattr(DBTxnObject* self, char *name)
5481{
5482 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5483}
5484
5485static PyObject*
5486DBLock_getattr(DBLockObject* self, char *name)
5487{
5488 return NULL;
5489}
5490
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005491#if (DBVER >= 43)
5492static PyObject*
5493DBSequence_getattr(DBSequenceObject* self, char *name)
5494{
5495 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5496}
5497#endif
5498
Neal Norwitz227b5332006-03-22 09:28:35 +00005499static PyTypeObject DB_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005500 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005501 "DB", /*tp_name*/
5502 sizeof(DBObject), /*tp_basicsize*/
5503 0, /*tp_itemsize*/
5504 /* methods */
5505 (destructor)DB_dealloc, /*tp_dealloc*/
5506 0, /*tp_print*/
5507 (getattrfunc)DB_getattr, /*tp_getattr*/
5508 0, /*tp_setattr*/
5509 0, /*tp_compare*/
5510 0, /*tp_repr*/
5511 0, /*tp_as_number*/
5512 0, /*tp_as_sequence*/
5513 &DB_mapping,/*tp_as_mapping*/
5514 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005515#ifdef HAVE_WEAKREF
5516 0, /* tp_call */
5517 0, /* tp_str */
5518 0, /* tp_getattro */
5519 0, /* tp_setattro */
5520 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005521 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005522 0, /* tp_doc */
5523 0, /* tp_traverse */
5524 0, /* tp_clear */
5525 0, /* tp_richcompare */
5526 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5527#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005528};
5529
5530
Neal Norwitz227b5332006-03-22 09:28:35 +00005531static PyTypeObject DBCursor_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005532 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005533 "DBCursor", /*tp_name*/
5534 sizeof(DBCursorObject), /*tp_basicsize*/
5535 0, /*tp_itemsize*/
5536 /* methods */
5537 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5538 0, /*tp_print*/
5539 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5540 0, /*tp_setattr*/
5541 0, /*tp_compare*/
5542 0, /*tp_repr*/
5543 0, /*tp_as_number*/
5544 0, /*tp_as_sequence*/
5545 0, /*tp_as_mapping*/
5546 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005547#ifdef HAVE_WEAKREF
5548 0, /* tp_call */
5549 0, /* tp_str */
5550 0, /* tp_getattro */
5551 0, /* tp_setattro */
5552 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005553 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smitha703a212003-11-03 01:04:41 +00005554 0, /* tp_doc */
5555 0, /* tp_traverse */
5556 0, /* tp_clear */
5557 0, /* tp_richcompare */
5558 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5559#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005560};
5561
5562
Neal Norwitz227b5332006-03-22 09:28:35 +00005563static PyTypeObject DBEnv_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005564 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005565 "DBEnv", /*tp_name*/
5566 sizeof(DBEnvObject), /*tp_basicsize*/
5567 0, /*tp_itemsize*/
5568 /* methods */
5569 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5570 0, /*tp_print*/
5571 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5572 0, /*tp_setattr*/
5573 0, /*tp_compare*/
5574 0, /*tp_repr*/
5575 0, /*tp_as_number*/
5576 0, /*tp_as_sequence*/
5577 0, /*tp_as_mapping*/
5578 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005579#ifdef HAVE_WEAKREF
5580 0, /* tp_call */
5581 0, /* tp_str */
5582 0, /* tp_getattro */
5583 0, /* tp_setattro */
5584 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005585 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005586 0, /* tp_doc */
5587 0, /* tp_traverse */
5588 0, /* tp_clear */
5589 0, /* tp_richcompare */
5590 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5591#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005592};
5593
Neal Norwitz227b5332006-03-22 09:28:35 +00005594static PyTypeObject DBTxn_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005595 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005596 "DBTxn", /*tp_name*/
5597 sizeof(DBTxnObject), /*tp_basicsize*/
5598 0, /*tp_itemsize*/
5599 /* methods */
5600 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5601 0, /*tp_print*/
5602 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5603 0, /*tp_setattr*/
5604 0, /*tp_compare*/
5605 0, /*tp_repr*/
5606 0, /*tp_as_number*/
5607 0, /*tp_as_sequence*/
5608 0, /*tp_as_mapping*/
5609 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005610#ifdef HAVE_WEAKREF
5611 0, /* tp_call */
5612 0, /* tp_str */
5613 0, /* tp_getattro */
5614 0, /* tp_setattro */
5615 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005616 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005617 0, /* tp_doc */
5618 0, /* tp_traverse */
5619 0, /* tp_clear */
5620 0, /* tp_richcompare */
5621 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5622#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005623};
5624
5625
Neal Norwitz227b5332006-03-22 09:28:35 +00005626static PyTypeObject DBLock_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005627 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005628 "DBLock", /*tp_name*/
5629 sizeof(DBLockObject), /*tp_basicsize*/
5630 0, /*tp_itemsize*/
5631 /* methods */
5632 (destructor)DBLock_dealloc, /*tp_dealloc*/
5633 0, /*tp_print*/
5634 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5635 0, /*tp_setattr*/
5636 0, /*tp_compare*/
5637 0, /*tp_repr*/
5638 0, /*tp_as_number*/
5639 0, /*tp_as_sequence*/
5640 0, /*tp_as_mapping*/
5641 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005642#ifdef HAVE_WEAKREF
5643 0, /* tp_call */
5644 0, /* tp_str */
5645 0, /* tp_getattro */
5646 0, /* tp_setattro */
5647 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005648 Py_TPFLAGS_DEFAULT, /* tp_flags */
Gregory P. Smith31c50652004-06-28 01:20:40 +00005649 0, /* tp_doc */
5650 0, /* tp_traverse */
5651 0, /* tp_clear */
5652 0, /* tp_richcompare */
5653 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5654#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005655};
5656
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005657#if (DBVER >= 43)
5658static PyTypeObject DBSequence_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005659 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005660 "DBSequence", /*tp_name*/
5661 sizeof(DBSequenceObject), /*tp_basicsize*/
5662 0, /*tp_itemsize*/
5663 /* methods */
5664 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5665 0, /*tp_print*/
5666 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5667 0, /*tp_setattr*/
5668 0, /*tp_compare*/
5669 0, /*tp_repr*/
5670 0, /*tp_as_number*/
5671 0, /*tp_as_sequence*/
5672 0, /*tp_as_mapping*/
5673 0, /*tp_hash*/
5674#ifdef HAVE_WEAKREF
5675 0, /* tp_call */
5676 0, /* tp_str */
5677 0, /* tp_getattro */
5678 0, /* tp_setattro */
5679 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +00005680 Py_TPFLAGS_DEFAULT, /* tp_flags */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005681 0, /* tp_doc */
5682 0, /* tp_traverse */
5683 0, /* tp_clear */
5684 0, /* tp_richcompare */
5685 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5686#endif
5687};
5688#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005689
5690/* --------------------------------------------------------------------- */
5691/* Module-level functions */
5692
5693static PyObject*
5694DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5695{
5696 PyObject* dbenvobj = NULL;
5697 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005698 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005699
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005700 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5701 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005702 return NULL;
5703 if (dbenvobj == Py_None)
5704 dbenvobj = NULL;
5705 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5706 makeTypeError("DBEnv", dbenvobj);
5707 return NULL;
5708 }
5709
5710 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5711}
5712
5713
5714static PyObject*
5715DBEnv_construct(PyObject* self, PyObject* args)
5716{
5717 int flags = 0;
5718 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5719 return (PyObject* )newDBEnvObject(flags);
5720}
5721
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005722#if (DBVER >= 43)
5723static PyObject*
5724DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5725{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005726 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005727 int flags = 0;
5728 static char* kwnames[] = { "db", "flags", NULL};
5729
5730 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5731 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00005732 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005733 makeTypeError("DB", dbobj);
5734 return NULL;
5735 }
5736 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5737}
5738#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005739
5740static char bsddb_version_doc[] =
5741"Returns a tuple of major, minor, and patch release numbers of the\n\
5742underlying DB library.";
5743
5744static PyObject*
5745bsddb_version(PyObject* self, PyObject* args)
5746{
5747 int major, minor, patch;
5748
5749 if (!PyArg_ParseTuple(args, ":version"))
5750 return NULL;
5751 db_version(&major, &minor, &patch);
5752 return Py_BuildValue("(iii)", major, minor, patch);
5753}
5754
5755
5756/* List of functions defined in the module */
5757
5758static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005759 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5760 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5761#if (DBVER >= 43)
5762 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5763#endif
5764 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005765 {NULL, NULL} /* sentinel */
5766};
5767
5768
5769/* --------------------------------------------------------------------- */
5770/* Module initialization */
5771
5772
5773/* Convenience routine to export an integer value.
5774 * Errors are silently ignored, for better or for worse...
5775 */
5776#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5777
Gregory P. Smith41631e82003-09-21 00:08:14 +00005778#define MODULE_NAME_MAX_LEN 11
5779static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005780
Neal Norwitzf6657e62006-12-28 04:47:50 +00005781PyMODINIT_FUNC init_bsddb(void)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005782{
5783 PyObject* m;
5784 PyObject* d;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005785 PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
5786 PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
5787 PyObject* svnid_s = PyUnicode_FromString(svn_id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005788
5789 /* Initialize the type of the new type objects here; doing it here
5790 is required for portability to Windows without requiring C++. */
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005791 Py_Type(&DB_Type) = &PyType_Type;
5792 Py_Type(&DBCursor_Type) = &PyType_Type;
5793 Py_Type(&DBEnv_Type) = &PyType_Type;
5794 Py_Type(&DBTxn_Type) = &PyType_Type;
5795 Py_Type(&DBLock_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005796#if (DBVER >= 43)
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00005797 Py_Type(&DBSequence_Type) = &PyType_Type;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799
5800
Mark Hammonda69d4092003-04-22 23:13:27 +00005801#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005803 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005804#endif
5805
5806 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005807 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005808 if (m == NULL)
5809 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005810
5811 /* Add some symbolic constants to the module */
5812 d = PyModule_GetDict(m);
5813 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005814 PyDict_SetItemString(d, "cvsid", svnid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005815 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5816 Py_DECREF(pybsddb_version_s);
5817 pybsddb_version_s = NULL;
Martin v. Löwis64ce5052007-08-05 15:39:16 +00005818 Py_DECREF(svnid_s);
5819 svnid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005820 Py_DECREF(db_version_s);
5821 db_version_s = NULL;
5822
5823 ADD_INT(d, DB_VERSION_MAJOR);
5824 ADD_INT(d, DB_VERSION_MINOR);
5825 ADD_INT(d, DB_VERSION_PATCH);
5826
5827 ADD_INT(d, DB_MAX_PAGES);
5828 ADD_INT(d, DB_MAX_RECORDS);
5829
Gregory P. Smith41631e82003-09-21 00:08:14 +00005830#if (DBVER >= 42)
5831 ADD_INT(d, DB_RPCCLIENT);
5832#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005833 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005834 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5835 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5836#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005837 ADD_INT(d, DB_XA_CREATE);
5838
5839 ADD_INT(d, DB_CREATE);
5840 ADD_INT(d, DB_NOMMAP);
5841 ADD_INT(d, DB_THREAD);
5842
5843 ADD_INT(d, DB_FORCE);
5844 ADD_INT(d, DB_INIT_CDB);
5845 ADD_INT(d, DB_INIT_LOCK);
5846 ADD_INT(d, DB_INIT_LOG);
5847 ADD_INT(d, DB_INIT_MPOOL);
5848 ADD_INT(d, DB_INIT_TXN);
5849#if (DBVER >= 32)
5850 ADD_INT(d, DB_JOINENV);
5851#endif
5852
5853 ADD_INT(d, DB_RECOVER);
5854 ADD_INT(d, DB_RECOVER_FATAL);
5855 ADD_INT(d, DB_TXN_NOSYNC);
5856 ADD_INT(d, DB_USE_ENVIRON);
5857 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5858
5859 ADD_INT(d, DB_LOCKDOWN);
5860 ADD_INT(d, DB_PRIVATE);
5861 ADD_INT(d, DB_SYSTEM_MEM);
5862
5863 ADD_INT(d, DB_TXN_SYNC);
5864 ADD_INT(d, DB_TXN_NOWAIT);
5865
5866 ADD_INT(d, DB_EXCL);
5867 ADD_INT(d, DB_FCNTL_LOCKING);
5868 ADD_INT(d, DB_ODDFILESIZE);
5869 ADD_INT(d, DB_RDWRMASTER);
5870 ADD_INT(d, DB_RDONLY);
5871 ADD_INT(d, DB_TRUNCATE);
5872#if (DBVER >= 32)
5873 ADD_INT(d, DB_EXTENT);
5874 ADD_INT(d, DB_CDB_ALLDB);
5875 ADD_INT(d, DB_VERIFY);
5876#endif
5877 ADD_INT(d, DB_UPGRADE);
5878
5879 ADD_INT(d, DB_AGGRESSIVE);
5880 ADD_INT(d, DB_NOORDERCHK);
5881 ADD_INT(d, DB_ORDERCHKONLY);
5882 ADD_INT(d, DB_PR_PAGE);
5883#if ! (DBVER >= 33)
5884 ADD_INT(d, DB_VRFY_FLAGMASK);
5885 ADD_INT(d, DB_PR_HEADERS);
5886#endif
5887 ADD_INT(d, DB_PR_RECOVERYTEST);
5888 ADD_INT(d, DB_SALVAGE);
5889
5890 ADD_INT(d, DB_LOCK_NORUN);
5891 ADD_INT(d, DB_LOCK_DEFAULT);
5892 ADD_INT(d, DB_LOCK_OLDEST);
5893 ADD_INT(d, DB_LOCK_RANDOM);
5894 ADD_INT(d, DB_LOCK_YOUNGEST);
5895#if (DBVER >= 33)
5896 ADD_INT(d, DB_LOCK_MAXLOCKS);
5897 ADD_INT(d, DB_LOCK_MINLOCKS);
5898 ADD_INT(d, DB_LOCK_MINWRITE);
5899#endif
5900
5901
5902#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005903 /* docs say to use zero instead */
5904 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005905#else
5906 ADD_INT(d, DB_LOCK_CONFLICT);
5907#endif
5908
5909 ADD_INT(d, DB_LOCK_DUMP);
5910 ADD_INT(d, DB_LOCK_GET);
5911 ADD_INT(d, DB_LOCK_INHERIT);
5912 ADD_INT(d, DB_LOCK_PUT);
5913 ADD_INT(d, DB_LOCK_PUT_ALL);
5914 ADD_INT(d, DB_LOCK_PUT_OBJ);
5915
5916 ADD_INT(d, DB_LOCK_NG);
5917 ADD_INT(d, DB_LOCK_READ);
5918 ADD_INT(d, DB_LOCK_WRITE);
5919 ADD_INT(d, DB_LOCK_NOWAIT);
5920#if (DBVER >= 32)
5921 ADD_INT(d, DB_LOCK_WAIT);
5922#endif
5923 ADD_INT(d, DB_LOCK_IWRITE);
5924 ADD_INT(d, DB_LOCK_IREAD);
5925 ADD_INT(d, DB_LOCK_IWR);
5926#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005927#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005928 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005929#else
5930 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5931#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005932 ADD_INT(d, DB_LOCK_WWRITE);
5933#endif
5934
5935 ADD_INT(d, DB_LOCK_RECORD);
5936 ADD_INT(d, DB_LOCK_UPGRADE);
5937#if (DBVER >= 32)
5938 ADD_INT(d, DB_LOCK_SWITCH);
5939#endif
5940#if (DBVER >= 33)
5941 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5942#endif
5943
5944 ADD_INT(d, DB_LOCK_NOWAIT);
5945 ADD_INT(d, DB_LOCK_RECORD);
5946 ADD_INT(d, DB_LOCK_UPGRADE);
5947
5948#if (DBVER >= 33)
5949 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005950#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005951 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005953 ADD_INT(d, DB_LSTAT_FREE);
5954 ADD_INT(d, DB_LSTAT_HELD);
5955#if (DBVER == 33)
5956 ADD_INT(d, DB_LSTAT_NOGRANT);
5957#endif
5958 ADD_INT(d, DB_LSTAT_PENDING);
5959 ADD_INT(d, DB_LSTAT_WAITING);
5960#endif
5961
5962 ADD_INT(d, DB_ARCH_ABS);
5963 ADD_INT(d, DB_ARCH_DATA);
5964 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00005965#if (DBVER >= 42)
5966 ADD_INT(d, DB_ARCH_REMOVE);
5967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005968
5969 ADD_INT(d, DB_BTREE);
5970 ADD_INT(d, DB_HASH);
5971 ADD_INT(d, DB_RECNO);
5972 ADD_INT(d, DB_QUEUE);
5973 ADD_INT(d, DB_UNKNOWN);
5974
5975 ADD_INT(d, DB_DUP);
5976 ADD_INT(d, DB_DUPSORT);
5977 ADD_INT(d, DB_RECNUM);
5978 ADD_INT(d, DB_RENUMBER);
5979 ADD_INT(d, DB_REVSPLITOFF);
5980 ADD_INT(d, DB_SNAPSHOT);
5981
5982 ADD_INT(d, DB_JOIN_NOSORT);
5983
5984 ADD_INT(d, DB_AFTER);
5985 ADD_INT(d, DB_APPEND);
5986 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005987#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00005989#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005990#if (DBVER >= 41)
5991 _addIntToDict(d, "DB_CHECKPOINT", 0);
5992#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005993 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005994 ADD_INT(d, DB_CURLSN);
5995#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005996#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005997 ADD_INT(d, DB_COMMIT);
5998#endif
5999 ADD_INT(d, DB_CONSUME);
6000#if (DBVER >= 32)
6001 ADD_INT(d, DB_CONSUME_WAIT);
6002#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006003 ADD_INT(d, DB_CURRENT);
6004#if (DBVER >= 33)
6005 ADD_INT(d, DB_FAST_STAT);
6006#endif
6007 ADD_INT(d, DB_FIRST);
6008 ADD_INT(d, DB_FLUSH);
6009 ADD_INT(d, DB_GET_BOTH);
6010 ADD_INT(d, DB_GET_RECNO);
6011 ADD_INT(d, DB_JOIN_ITEM);
6012 ADD_INT(d, DB_KEYFIRST);
6013 ADD_INT(d, DB_KEYLAST);
6014 ADD_INT(d, DB_LAST);
6015 ADD_INT(d, DB_NEXT);
6016 ADD_INT(d, DB_NEXT_DUP);
6017 ADD_INT(d, DB_NEXT_NODUP);
6018 ADD_INT(d, DB_NODUPDATA);
6019 ADD_INT(d, DB_NOOVERWRITE);
6020 ADD_INT(d, DB_NOSYNC);
6021 ADD_INT(d, DB_POSITION);
6022 ADD_INT(d, DB_PREV);
6023 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00006024#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006025 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00006026#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006027 ADD_INT(d, DB_SET);
6028 ADD_INT(d, DB_SET_RANGE);
6029 ADD_INT(d, DB_SET_RECNO);
6030 ADD_INT(d, DB_WRITECURSOR);
6031
6032 ADD_INT(d, DB_OPFLAGS_MASK);
6033 ADD_INT(d, DB_RMW);
6034#if (DBVER >= 33)
6035 ADD_INT(d, DB_DIRTY_READ);
6036 ADD_INT(d, DB_MULTIPLE);
6037 ADD_INT(d, DB_MULTIPLE_KEY);
6038#endif
6039
Gregory P. Smith29602d22006-01-24 09:46:48 +00006040#if (DBVER >= 44)
6041 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6042 ADD_INT(d, DB_READ_COMMITTED);
6043#endif
6044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006045#if (DBVER >= 33)
6046 ADD_INT(d, DB_DONOTINDEX);
Gregory P. Smith361ed152007-08-23 07:32:27 +00006047 ADD_INT(d, DB_XIDDATASIZE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048#endif
6049
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006050#if (DBVER >= 41)
6051 _addIntToDict(d, "DB_INCOMPLETE", 0);
6052#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006053 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006054#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006055 ADD_INT(d, DB_KEYEMPTY);
6056 ADD_INT(d, DB_KEYEXIST);
6057 ADD_INT(d, DB_LOCK_DEADLOCK);
6058 ADD_INT(d, DB_LOCK_NOTGRANTED);
6059 ADD_INT(d, DB_NOSERVER);
6060 ADD_INT(d, DB_NOSERVER_HOME);
6061 ADD_INT(d, DB_NOSERVER_ID);
6062 ADD_INT(d, DB_NOTFOUND);
6063 ADD_INT(d, DB_OLD_VERSION);
6064 ADD_INT(d, DB_RUNRECOVERY);
6065 ADD_INT(d, DB_VERIFY_BAD);
6066#if (DBVER >= 33)
6067 ADD_INT(d, DB_PAGE_NOTFOUND);
6068 ADD_INT(d, DB_SECONDARY_BAD);
6069#endif
6070#if (DBVER >= 40)
6071 ADD_INT(d, DB_STAT_CLEAR);
6072 ADD_INT(d, DB_REGION_INIT);
6073 ADD_INT(d, DB_NOLOCKING);
6074 ADD_INT(d, DB_YIELDCPU);
6075 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6076 ADD_INT(d, DB_NOPANIC);
6077#endif
6078
Gregory P. Smith41631e82003-09-21 00:08:14 +00006079#if (DBVER >= 42)
6080 ADD_INT(d, DB_TIME_NOTGRANTED);
6081 ADD_INT(d, DB_TXN_NOT_DURABLE);
6082 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
6083 ADD_INT(d, DB_LOG_AUTOREMOVE);
6084 ADD_INT(d, DB_DIRECT_LOG);
6085 ADD_INT(d, DB_DIRECT_DB);
6086 ADD_INT(d, DB_INIT_REP);
6087 ADD_INT(d, DB_ENCRYPT);
6088 ADD_INT(d, DB_CHKSUM);
6089#endif
6090
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006091#if (DBVER >= 43)
6092 ADD_INT(d, DB_LOG_INMEMORY);
6093 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006094 ADD_INT(d, DB_SEQ_DEC);
6095 ADD_INT(d, DB_SEQ_INC);
6096 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006097#endif
6098
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006099#if (DBVER >= 41)
6100 ADD_INT(d, DB_ENCRYPT_AES);
6101 ADD_INT(d, DB_AUTO_COMMIT);
6102#else
6103 /* allow berkeleydb 4.1 aware apps to run on older versions */
6104 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
6105#endif
6106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006107 ADD_INT(d, EINVAL);
6108 ADD_INT(d, EACCES);
6109 ADD_INT(d, ENOSPC);
6110 ADD_INT(d, ENOMEM);
6111 ADD_INT(d, EAGAIN);
6112 ADD_INT(d, EBUSY);
6113 ADD_INT(d, EEXIST);
6114 ADD_INT(d, ENOENT);
6115 ADD_INT(d, EPERM);
6116
Barry Warsaw1baa9822003-03-31 19:51:29 +00006117#if (DBVER >= 40)
6118 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
6119 ADD_INT(d, DB_SET_TXN_TIMEOUT);
6120#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006121
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006122 /* The exception name must be correct for pickled exception *
6123 * objects to unpickle properly. */
6124#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6125#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6126#else
6127#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6128#endif
6129
6130 /* All the rest of the exceptions derive only from DBError */
6131#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6132 PyDict_SetItemString(d, #name, name)
6133
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006134 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006135 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6136 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006137
Gregory P. Smithe9477062005-06-04 06:46:59 +00006138 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6139 * from both DBError and KeyError, since the API only supports
6140 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006141 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Guido van Rossum52cc1d82007-03-18 15:41:51 +00006142 {
6143 PyObject *builtin_mod = PyImport_ImportModule("__builtin__");
6144 PyDict_SetItemString(d, "__builtins__", builtin_mod);
6145 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00006146 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6147 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006148 Py_file_input, d, d);
6149 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006150 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006151 PyDict_DelItemString(d, "KeyError");
6152
6153
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006154#if !INCOMPLETE_IS_WARNING
6155 MAKE_EX(DBIncompleteError);
6156#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006157 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006158 MAKE_EX(DBKeyEmptyError);
6159 MAKE_EX(DBKeyExistError);
6160 MAKE_EX(DBLockDeadlockError);
6161 MAKE_EX(DBLockNotGrantedError);
6162 MAKE_EX(DBOldVersionError);
6163 MAKE_EX(DBRunRecoveryError);
6164 MAKE_EX(DBVerifyBadError);
6165 MAKE_EX(DBNoServerError);
6166 MAKE_EX(DBNoServerHomeError);
6167 MAKE_EX(DBNoServerIDError);
6168#if (DBVER >= 33)
6169 MAKE_EX(DBPageNotFoundError);
6170 MAKE_EX(DBSecondaryBadError);
6171#endif
6172
6173 MAKE_EX(DBInvalidArgError);
6174 MAKE_EX(DBAccessError);
6175 MAKE_EX(DBNoSpaceError);
6176 MAKE_EX(DBNoMemoryError);
6177 MAKE_EX(DBAgainError);
6178 MAKE_EX(DBBusyError);
6179 MAKE_EX(DBFileExistsError);
6180 MAKE_EX(DBNoSuchFileError);
6181 MAKE_EX(DBPermissionsError);
6182
6183#undef MAKE_EX
6184
6185 /* Check for errors */
6186 if (PyErr_Occurred()) {
6187 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006188 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006189 }
6190}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006191
6192/* allow this module to be named _pybsddb so that it can be installed
6193 * and imported on top of python >= 2.3 that includes its own older
6194 * copy of the library named _bsddb without importing the old version. */
Neal Norwitzf6657e62006-12-28 04:47:50 +00006195PyMODINIT_FUNC init_pybsddb(void)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006196{
6197 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6198 init_bsddb();
6199}