blob: d43d4aa6e8dafd84d302c98856b7f8f0783294e1 [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
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
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 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
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 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +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)
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
Gregory P. Smith372b5832006-06-05 18:48:21 +0000101#define PY_BSDDB_VERSION "4.4.4"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +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
Gregory P. Smithf0547d02006-06-05 17:38:04 +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;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#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
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
531
532 switch (err) {
533 case 0: /* successful, no error */ break;
534
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000535#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000536 case DB_INCOMPLETE:
537#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000538 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000539 if (_db_errmsg[0]) {
540 strcat(errTxt, " -- ");
541 strcat(errTxt, _db_errmsg);
542 _db_errmsg[0] = 0;
543 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000544#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000545 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
546#else
547 fprintf(stderr, errTxt);
548 fprintf(stderr, "\n");
549#endif
550
551#else /* do an exception instead */
552 errObj = DBIncompleteError;
553#endif
554 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000555#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556
557 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
558 case DB_KEYEXIST: errObj = DBKeyExistError; break;
559 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
560 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
561 case DB_NOTFOUND: errObj = DBNotFoundError; break;
562 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
563 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
564 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
565 case DB_NOSERVER: errObj = DBNoServerError; break;
566 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
567 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
568#if (DBVER >= 33)
569 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
570 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
571#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000572 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000573
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000574#if (DBVER >= 43)
575 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
576 case ENOMEM: errObj = PyExc_MemoryError; break;
577#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000578 case EINVAL: errObj = DBInvalidArgError; break;
579 case EACCES: errObj = DBAccessError; break;
580 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000581 case EAGAIN: errObj = DBAgainError; break;
582 case EBUSY : errObj = DBBusyError; break;
583 case EEXIST: errObj = DBFileExistsError; break;
584 case ENOENT: errObj = DBNoSuchFileError; break;
585 case EPERM : errObj = DBPermissionsError; break;
586
587 default: errObj = DBError; break;
588 }
589
590 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000591 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000592 if (_db_errmsg[0]) {
593 strcat(errTxt, " -- ");
594 strcat(errTxt, _db_errmsg);
595 _db_errmsg[0] = 0;
596 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000597
598 errTuple = Py_BuildValue("(is)", err, errTxt);
599 PyErr_SetObject(errObj, errTuple);
600 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000601 }
602
603 return ((errObj != NULL) || exceptionRaised);
604}
605
606
607
608/* set a type exception */
609static void makeTypeError(char* expected, PyObject* found)
610{
611 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
612 expected, found->ob_type->tp_name);
613}
614
615
616/* verify that an obj is either None or a DBTxn, and set the txn pointer */
617static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
618{
619 if (txnobj == Py_None || txnobj == NULL) {
620 *txn = NULL;
621 return 1;
622 }
623 if (DBTxnObject_Check(txnobj)) {
624 *txn = ((DBTxnObject*)txnobj)->txn;
625 return 1;
626 }
627 else
628 makeTypeError("DBTxn", txnobj);
629 return 0;
630}
631
632
633/* Delete a key from a database
634 Returns 0 on success, -1 on an error. */
635static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
636{
637 int err;
638
639 MYDB_BEGIN_ALLOW_THREADS;
640 err = self->db->del(self->db, txn, key, 0);
641 MYDB_END_ALLOW_THREADS;
642 if (makeDBError(err)) {
643 return -1;
644 }
645 self->haveStat = 0;
646 return 0;
647}
648
649
650/* Store a key into a database
651 Returns 0 on success, -1 on an error. */
652static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
653{
654 int err;
655
656 MYDB_BEGIN_ALLOW_THREADS;
657 err = self->db->put(self->db, txn, key, data, flags);
658 MYDB_END_ALLOW_THREADS;
659 if (makeDBError(err)) {
660 return -1;
661 }
662 self->haveStat = 0;
663 return 0;
664}
665
666/* Get a key/data pair from a cursor */
667static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
668 PyObject *args, PyObject *kwargs, char *format)
669{
670 int err;
671 PyObject* retval = NULL;
672 DBT key, data;
673 int dlen = -1;
674 int doff = -1;
675 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000676 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000677
678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
679 &flags, &dlen, &doff))
680 return NULL;
681
682 CHECK_CURSOR_NOT_CLOSED(self);
683
684 flags |= extra_flags;
685 CLEAR_DBT(key);
686 CLEAR_DBT(data);
687 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
688 /* Tell BerkeleyDB to malloc the return value (thread safe) */
689 data.flags = DB_DBT_MALLOC;
690 key.flags = DB_DBT_MALLOC;
691 }
692 if (!add_partial_dbt(&data, dlen, doff))
693 return NULL;
694
695 MYDB_BEGIN_ALLOW_THREADS;
696 err = self->dbc->c_get(self->dbc, &key, &data, flags);
697 MYDB_END_ALLOW_THREADS;
698
Gregory P. Smithe9477062005-06-04 06:46:59 +0000699 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
700 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000701 Py_INCREF(Py_None);
702 retval = Py_None;
703 }
704 else if (makeDBError(err)) {
705 retval = NULL;
706 }
707 else { /* otherwise, success! */
708
709 /* if Recno or Queue, return the key as an Int */
710 switch (_DB_get_type(self->mydb)) {
711 case -1:
712 retval = NULL;
713 break;
714
715 case DB_RECNO:
716 case DB_QUEUE:
717 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
718 data.data, data.size);
719 break;
720 case DB_HASH:
721 case DB_BTREE:
722 default:
723 retval = Py_BuildValue("s#s#", key.data, key.size,
724 data.data, data.size);
725 break;
726 }
727 }
728 if (!err) {
729 FREE_DBT(key);
730 FREE_DBT(data);
731 }
732 return retval;
733}
734
735
736/* add an integer to a dictionary using the given name as a key */
737static void _addIntToDict(PyObject* dict, char *name, int value)
738{
739 PyObject* v = PyInt_FromLong((long) value);
740 if (!v || PyDict_SetItemString(dict, name, v))
741 PyErr_Clear();
742
743 Py_XDECREF(v);
744}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000745#if (DBVER >= 43)
746/* add an db_seq_t to a dictionary using the given name as a key */
747static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
748{
749 PyObject* v = PyLong_FromLongLong(value);
750 if (!v || PyDict_SetItemString(dict, name, v))
751 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000753 Py_XDECREF(v);
754}
755#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000756
757
758
759/* --------------------------------------------------------------------- */
760/* Allocators and deallocators */
761
762static DBObject*
763newDBObject(DBEnvObject* arg, int flags)
764{
765 DBObject* self;
766 DB_ENV* db_env = NULL;
767 int err;
768
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770 if (self == NULL)
771 return NULL;
772
773 self->haveStat = 0;
774 self->flags = 0;
775 self->setflags = 0;
776 self->myenvobj = NULL;
777#if (DBVER >= 33)
778 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000779 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000780 self->primaryDBType = 0;
781#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000782#ifdef HAVE_WEAKREF
783 self->in_weakreflist = NULL;
784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000785
786 /* keep a reference to our python DBEnv object */
787 if (arg) {
788 Py_INCREF(arg);
789 self->myenvobj = arg;
790 db_env = arg->db_env;
791 }
792
793 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000794 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000796 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
797 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000798
799 MYDB_BEGIN_ALLOW_THREADS;
800 err = db_create(&self->db, db_env, flags);
801 self->db->set_errcall(self->db, _db_errorCallback);
802#if (DBVER >= 33)
803 self->db->app_private = (void*)self;
804#endif
805 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000806 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
807 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000808 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809 if (makeDBError(err)) {
810 if (self->myenvobj) {
811 Py_DECREF(self->myenvobj);
812 self->myenvobj = NULL;
813 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000814 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000815 self = NULL;
816 }
817 return self;
818}
819
820
821static void
822DB_dealloc(DBObject* self)
823{
824 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000825 /* avoid closing a DB when its DBEnv has been closed out from under
826 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000828 (self->myenvobj && self->myenvobj->db_env))
829 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830 MYDB_BEGIN_ALLOW_THREADS;
831 self->db->close(self->db, 0);
832 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000833#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 } else {
835 PyErr_Warn(PyExc_RuntimeWarning,
836 "DB could not be closed in destructor: DBEnv already closed");
837#endif
838 }
839 self->db = NULL;
840 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000841#ifdef HAVE_WEAKREF
842 if (self->in_weakreflist != NULL) {
843 PyObject_ClearWeakRefs((PyObject *) self);
844 }
845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846 if (self->myenvobj) {
847 Py_DECREF(self->myenvobj);
848 self->myenvobj = NULL;
849 }
850#if (DBVER >= 33)
851 if (self->associateCallback != NULL) {
852 Py_DECREF(self->associateCallback);
853 self->associateCallback = NULL;
854 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000855 if (self->btCompareCallback != NULL) {
856 Py_DECREF(self->btCompareCallback);
857 self->btCompareCallback = NULL;
858 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861}
862
863
864static DBCursorObject*
865newDBCursorObject(DBC* dbc, DBObject* db)
866{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000867 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868 if (self == NULL)
869 return NULL;
870
871 self->dbc = dbc;
872 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000873#ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876 Py_INCREF(self->mydb);
877 return self;
878}
879
880
881static void
882DBCursor_dealloc(DBCursorObject* self)
883{
884 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000885
886#ifdef HAVE_WEAKREF
887 if (self->in_weakreflist != NULL) {
888 PyObject_ClearWeakRefs((PyObject *) self);
889 }
890#endif
891
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 if (self->dbc != NULL) {
893 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000894 /* If the underlying database has been closed, we don't
895 need to do anything. If the environment has been closed
896 we need to leak, as BerkeleyDB will crash trying to access
897 the environment. There was an exception when the
898 user closed the environment even though there still was
899 a database open. */
900 if (self->mydb->db && self->mydb->myenvobj &&
901 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000902 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 self->dbc = NULL;
904 MYDB_END_ALLOW_THREADS;
905 }
906 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908}
909
910
911static DBEnvObject*
912newDBEnvObject(int flags)
913{
914 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000915 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 if (self == NULL)
917 return NULL;
918
919 self->closed = 1;
920 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000921 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
922 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000923#ifdef HAVE_WEAKREF
924 self->in_weakreflist = NULL;
925#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000926
927 MYDB_BEGIN_ALLOW_THREADS;
928 err = db_env_create(&self->db_env, flags);
929 MYDB_END_ALLOW_THREADS;
930 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000931 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 self = NULL;
933 }
934 else {
935 self->db_env->set_errcall(self->db_env, _db_errorCallback);
936 }
937 return self;
938}
939
940
941static void
942DBEnv_dealloc(DBEnvObject* self)
943{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000944#ifdef HAVE_WEAKREF
945 if (self->in_weakreflist != NULL) {
946 PyObject_ClearWeakRefs((PyObject *) self);
947 }
948#endif
949
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000950 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 MYDB_BEGIN_ALLOW_THREADS;
952 self->db_env->close(self->db_env, 0);
953 MYDB_END_ALLOW_THREADS;
954 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000955 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956}
957
958
959static DBTxnObject*
960newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
961{
962 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000963 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 if (self == NULL)
965 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000966 Py_INCREF(myenv);
967 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000968#ifdef HAVE_WEAKREF
969 self->in_weakreflist = NULL;
970#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971
972 MYDB_BEGIN_ALLOW_THREADS;
973#if (DBVER >= 40)
974 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
975#else
976 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
977#endif
978 MYDB_END_ALLOW_THREADS;
979 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000980 Py_DECREF(self->env);
981 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982 self = NULL;
983 }
984 return self;
985}
986
987
988static void
989DBTxn_dealloc(DBTxnObject* self)
990{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000991#ifdef HAVE_WEAKREF
992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
994 }
995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996
Gregory P. Smith31c50652004-06-28 01:20:40 +0000997#ifdef HAVE_WARNINGS
998 if (self->txn) {
999 /* it hasn't been finalized, abort it! */
1000 MYDB_BEGIN_ALLOW_THREADS;
1001#if (DBVER >= 40)
1002 self->txn->abort(self->txn);
1003#else
1004 txn_abort(self->txn);
1005#endif
1006 MYDB_END_ALLOW_THREADS;
1007 PyErr_Warn(PyExc_RuntimeWarning,
1008 "DBTxn aborted in destructor. No prior commit() or abort().");
1009 }
1010#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011
Neal Norwitz62a21122006-01-25 05:21:55 +00001012 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014}
1015
1016
1017static DBLockObject*
1018newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1019 db_lockmode_t lock_mode, int flags)
1020{
1021 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001022 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023 if (self == NULL)
1024 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001025#ifdef HAVE_WEAKREF
1026 self->in_weakreflist = NULL;
1027#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001028
1029 MYDB_BEGIN_ALLOW_THREADS;
1030#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001031 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1032 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033#else
1034 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1035#endif
1036 MYDB_END_ALLOW_THREADS;
1037 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001038 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001039 self = NULL;
1040 }
1041
1042 return self;
1043}
1044
1045
1046static void
1047DBLock_dealloc(DBLockObject* self)
1048{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001049#ifdef HAVE_WEAKREF
1050 if (self->in_weakreflist != NULL) {
1051 PyObject_ClearWeakRefs((PyObject *) self);
1052 }
1053#endif
1054 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057}
1058
1059
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001060#if (DBVER >= 43)
1061static DBSequenceObject*
1062newDBSequenceObject(DBObject* mydb, int flags)
1063{
1064 int err;
1065 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1066 if (self == NULL)
1067 return NULL;
1068 Py_INCREF(mydb);
1069 self->mydb = mydb;
1070#ifdef HAVE_WEAKREF
1071 self->in_weakreflist = NULL;
1072#endif
1073
1074
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1082 }
1083
1084 return self;
1085}
1086
1087
1088static void
1089DBSequence_dealloc(DBSequenceObject* self)
1090{
1091#ifdef HAVE_WEAKREF
1092 if (self->in_weakreflist != NULL) {
1093 PyObject_ClearWeakRefs((PyObject *) self);
1094 }
1095#endif
1096
1097 Py_DECREF(self->mydb);
1098 PyObject_Del(self);
1099}
1100#endif
1101
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001102/* --------------------------------------------------------------------- */
1103/* DB methods */
1104
1105static PyObject*
1106DB_append(DBObject* self, PyObject* args)
1107{
1108 PyObject* txnobj = NULL;
1109 PyObject* dataobj;
1110 db_recno_t recno;
1111 DBT key, data;
1112 DB_TXN *txn = NULL;
1113
Georg Brandl96a8c392006-05-29 21:04:52 +00001114 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001115 return NULL;
1116
1117 CHECK_DB_NOT_CLOSED(self);
1118
1119 /* make a dummy key out of a recno */
1120 recno = 0;
1121 CLEAR_DBT(key);
1122 key.data = &recno;
1123 key.size = sizeof(recno);
1124 key.ulen = key.size;
1125 key.flags = DB_DBT_USERMEM;
1126
1127 if (!make_dbt(dataobj, &data)) return NULL;
1128 if (!checkTxnObj(txnobj, &txn)) return NULL;
1129
1130 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1131 return NULL;
1132
1133 return PyInt_FromLong(recno);
1134}
1135
1136
1137#if (DBVER >= 33)
1138
1139static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001140_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1141 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001142{
1143 int retval = DB_DONOTINDEX;
1144 DBObject* secondaryDB = (DBObject*)db->app_private;
1145 PyObject* callback = secondaryDB->associateCallback;
1146 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001148 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149
1150
1151 if (callback != NULL) {
1152 MYDB_BEGIN_BLOCK_THREADS;
1153
Thomas Woutersb3153832006-03-08 01:47:19 +00001154 if (type == DB_RECNO || type == DB_QUEUE)
1155 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1156 priData->data, priData->size);
1157 else
1158 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1159 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001160 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001161 result = PyEval_CallObject(callback, args);
1162 }
1163 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001164 PyErr_Print();
1165 }
1166 else if (result == Py_None) {
1167 retval = DB_DONOTINDEX;
1168 }
1169 else if (PyInt_Check(result)) {
1170 retval = PyInt_AsLong(result);
1171 }
1172 else if (PyString_Check(result)) {
1173 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001174 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175
1176 CLEAR_DBT(*secKey);
1177#if PYTHON_API_VERSION <= 1007
1178 /* 1.5 compatibility */
1179 size = PyString_Size(result);
1180 data = PyString_AsString(result);
1181#else
1182 PyString_AsStringAndSize(result, &data, &size);
1183#endif
1184 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1185 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001186 if (secKey->data) {
1187 memcpy(secKey->data, data, size);
1188 secKey->size = size;
1189 retval = 0;
1190 }
1191 else {
1192 PyErr_SetString(PyExc_MemoryError,
1193 "malloc failed in _db_associateCallback");
1194 PyErr_Print();
1195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001196 }
1197 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001198 PyErr_SetString(
1199 PyExc_TypeError,
1200 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001201 PyErr_Print();
1202 }
1203
Thomas Woutersb3153832006-03-08 01:47:19 +00001204 Py_XDECREF(args);
1205 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206
1207 MYDB_END_BLOCK_THREADS;
1208 }
1209 return retval;
1210}
1211
1212
1213static PyObject*
1214DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1215{
1216 int err, flags=0;
1217 DBObject* secondaryDB;
1218 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001219#if (DBVER >= 41)
1220 PyObject *txnobj = NULL;
1221 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001222 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001223 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001224#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001225 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001226#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1230 &secondaryDB, &callback, &flags,
1231 &txnobj)) {
1232#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001234 &secondaryDB, &callback, &flags)) {
1235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237 }
1238
1239#if (DBVER >= 41)
1240 if (!checkTxnObj(txnobj, &txn)) return NULL;
1241#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242
1243 CHECK_DB_NOT_CLOSED(self);
1244 if (!DBObject_Check(secondaryDB)) {
1245 makeTypeError("DB", (PyObject*)secondaryDB);
1246 return NULL;
1247 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001248 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001249 if (callback == Py_None) {
1250 callback = NULL;
1251 }
1252 else if (!PyCallable_Check(callback)) {
1253 makeTypeError("Callable", callback);
1254 return NULL;
1255 }
1256
1257 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001258 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001259 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 secondaryDB->associateCallback = callback;
1261 secondaryDB->primaryDBType = _DB_get_type(self);
1262
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001263 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1264 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1265 * The global interepreter lock is not initialized until the first
1266 * thread is created using thread.start_new_thread() or fork() is
1267 * called. that would cause the ALLOW_THREADS here to segfault due
1268 * to a null pointer reference if no threads or child processes
1269 * have been created. This works around that and is a no-op if
1270 * threads have already been initialized.
1271 * (see pybsddb-users mailing list post on 2002-08-07)
1272 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001273#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001274 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001275#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001277#if (DBVER >= 41)
1278 err = self->db->associate(self->db,
1279 txn,
1280 secondaryDB->db,
1281 _db_associateCallback,
1282 flags);
1283#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001284 err = self->db->associate(self->db,
1285 secondaryDB->db,
1286 _db_associateCallback,
1287 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289 MYDB_END_ALLOW_THREADS;
1290
1291 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001292 Py_XDECREF(secondaryDB->associateCallback);
1293 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294 secondaryDB->primaryDBType = 0;
1295 }
1296
1297 RETURN_IF_ERR();
1298 RETURN_NONE();
1299}
1300
1301
1302#endif
1303
1304
1305static PyObject*
1306DB_close(DBObject* self, PyObject* args)
1307{
1308 int err, flags=0;
1309 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1310 return NULL;
1311 if (self->db != NULL) {
1312 if (self->myenvobj)
1313 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 self->db = NULL;
1316 RETURN_IF_ERR();
1317 }
1318 RETURN_NONE();
1319}
1320
1321
1322#if (DBVER >= 32)
1323static PyObject*
1324_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1325{
1326 int err, flags=0, type;
1327 PyObject* txnobj = NULL;
1328 PyObject* retval = NULL;
1329 DBT key, data;
1330 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001331 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1336
1337 CHECK_DB_NOT_CLOSED(self);
1338 type = _DB_get_type(self);
1339 if (type == -1)
1340 return NULL;
1341 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342 PyErr_SetString(PyExc_TypeError,
1343 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001344 return NULL;
1345 }
1346 if (!checkTxnObj(txnobj, &txn))
1347 return NULL;
1348
1349 CLEAR_DBT(key);
1350 CLEAR_DBT(data);
1351 if (CHECK_DBFLAG(self, DB_THREAD)) {
1352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1353 data.flags = DB_DBT_MALLOC;
1354 key.flags = DB_DBT_MALLOC;
1355 }
1356
1357 MYDB_BEGIN_ALLOW_THREADS;
1358 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1359 MYDB_END_ALLOW_THREADS;
1360
Gregory P. Smithe9477062005-06-04 06:46:59 +00001361 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1362 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1366 }
1367 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001368 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1369 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001370 FREE_DBT(key);
1371 FREE_DBT(data);
1372 }
1373
1374 RETURN_IF_ERR();
1375 return retval;
1376}
1377
1378static PyObject*
1379DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1380{
1381 return _DB_consume(self, args, kwargs, DB_CONSUME);
1382}
1383
1384static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001385DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1386 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001387{
1388 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1389}
1390#endif
1391
1392
1393
1394static PyObject*
1395DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1396{
1397 int err, flags=0;
1398 DBC* dbc;
1399 PyObject* txnobj = NULL;
1400 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001401 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402
1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1404 &txnobj, &flags))
1405 return NULL;
1406 CHECK_DB_NOT_CLOSED(self);
1407 if (!checkTxnObj(txnobj, &txn))
1408 return NULL;
1409
1410 MYDB_BEGIN_ALLOW_THREADS;
1411 err = self->db->cursor(self->db, txn, &dbc, flags);
1412 MYDB_END_ALLOW_THREADS;
1413 RETURN_IF_ERR();
1414 return (PyObject*) newDBCursorObject(dbc, self);
1415}
1416
1417
1418static PyObject*
1419DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1420{
1421 PyObject* txnobj = NULL;
1422 int flags = 0;
1423 PyObject* keyobj;
1424 DBT key;
1425 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001426 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1429 &keyobj, &txnobj, &flags))
1430 return NULL;
1431 CHECK_DB_NOT_CLOSED(self);
1432 if (!make_key_dbt(self, keyobj, &key, NULL))
1433 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001434 if (!checkTxnObj(txnobj, &txn)) {
1435 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001437 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001439 if (-1 == _DB_delete(self, txn, &key, 0)) {
1440 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001442 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443
1444 FREE_DBT(key);
1445 RETURN_NONE();
1446}
1447
1448
1449static PyObject*
1450DB_fd(DBObject* self, PyObject* args)
1451{
1452 int err, the_fd;
1453
1454 if (!PyArg_ParseTuple(args,":fd"))
1455 return NULL;
1456 CHECK_DB_NOT_CLOSED(self);
1457
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->fd(self->db, &the_fd);
1460 MYDB_END_ALLOW_THREADS;
1461 RETURN_IF_ERR();
1462 return PyInt_FromLong(the_fd);
1463}
1464
1465
1466static PyObject*
1467DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1468{
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, data;
1477 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001478 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001479 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001480
1481 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001482 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1483 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 return NULL;
1485
1486 CHECK_DB_NOT_CLOSED(self);
1487 if (!make_key_dbt(self, keyobj, &key, &flags))
1488 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001489 if (!checkTxnObj(txnobj, &txn)) {
1490 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001492 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493
1494 CLEAR_DBT(data);
1495 if (CHECK_DBFLAG(self, DB_THREAD)) {
1496 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1497 data.flags = DB_DBT_MALLOC;
1498 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001499 if (!add_partial_dbt(&data, dlen, doff)) {
1500 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001501 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001502 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503
1504 MYDB_BEGIN_ALLOW_THREADS;
1505 err = self->db->get(self->db, txn, &key, &data, flags);
1506 MYDB_END_ALLOW_THREADS;
1507
Gregory P. Smithe9477062005-06-04 06:46:59 +00001508 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001509 err = 0;
1510 Py_INCREF(dfltobj);
1511 retval = dfltobj;
1512 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001513 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1514 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515 err = 0;
1516 Py_INCREF(Py_None);
1517 retval = Py_None;
1518 }
1519 else if (!err) {
1520 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001521 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1522 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001523 else /* return just the data */
1524 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525 FREE_DBT(data);
1526 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001527 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528
1529 RETURN_IF_ERR();
1530 return retval;
1531}
1532
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001533#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001534static PyObject*
1535DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1536{
1537 int err, flags=0;
1538 PyObject* txnobj = NULL;
1539 PyObject* keyobj;
1540 PyObject* dfltobj = NULL;
1541 PyObject* retval = NULL;
1542 int dlen = -1;
1543 int doff = -1;
1544 DBT key, pkey, data;
1545 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001546 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001547 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001548
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1550 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1551 &doff))
1552 return NULL;
1553
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
1557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
1559 return NULL;
1560 }
1561
1562 CLEAR_DBT(data);
1563 if (CHECK_DBFLAG(self, DB_THREAD)) {
1564 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1565 data.flags = DB_DBT_MALLOC;
1566 }
1567 if (!add_partial_dbt(&data, dlen, doff)) {
1568 FREE_DBT(key);
1569 return NULL;
1570 }
1571
1572 CLEAR_DBT(pkey);
1573 pkey.flags = DB_DBT_MALLOC;
1574
1575 MYDB_BEGIN_ALLOW_THREADS;
1576 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1577 MYDB_END_ALLOW_THREADS;
1578
Gregory P. Smithe9477062005-06-04 06:46:59 +00001579 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001580 err = 0;
1581 Py_INCREF(dfltobj);
1582 retval = dfltobj;
1583 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001584 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1585 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001586 err = 0;
1587 Py_INCREF(Py_None);
1588 retval = Py_None;
1589 }
1590 else if (!err) {
1591 PyObject *pkeyObj;
1592 PyObject *dataObj;
1593 dataObj = PyString_FromStringAndSize(data.data, data.size);
1594
1595 if (self->primaryDBType == DB_RECNO ||
1596 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001597 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001598 else
1599 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1600
1601 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1602 {
1603 PyObject *keyObj;
1604 int type = _DB_get_type(self);
1605 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001606 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
1608 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001609#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001610 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001611#else
1612 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1613#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001614 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001615 }
1616 else /* return just the pkey and data */
1617 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1622#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001623 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001624 Py_DECREF(dataObj);
1625 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001626 FREE_DBT(pkey);
1627 FREE_DBT(data);
1628 }
1629 FREE_DBT(key);
1630
1631 RETURN_IF_ERR();
1632 return retval;
1633}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001634#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636
1637/* Return size of entry */
1638static PyObject*
1639DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1640{
1641 int err, flags=0;
1642 PyObject* txnobj = NULL;
1643 PyObject* keyobj;
1644 PyObject* retval = NULL;
1645 DBT key, data;
1646 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001647 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648
1649 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1650 &keyobj, &txnobj))
1651 return NULL;
1652 CHECK_DB_NOT_CLOSED(self);
1653 if (!make_key_dbt(self, keyobj, &key, &flags))
1654 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001655 if (!checkTxnObj(txnobj, &txn)) {
1656 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001658 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 CLEAR_DBT(data);
1660
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001661 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1662 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663 data.flags = DB_DBT_USERMEM;
1664 data.ulen = 0;
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->get(self->db, txn, &key, &data, flags);
1667 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001668 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001669 retval = PyInt_FromLong((long)data.size);
1670 err = 0;
1671 }
1672
1673 FREE_DBT(key);
1674 FREE_DBT(data);
1675 RETURN_IF_ERR();
1676 return retval;
1677}
1678
1679
1680static PyObject*
1681DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1682{
1683 int err, flags=0;
1684 PyObject* txnobj = NULL;
1685 PyObject* keyobj;
1686 PyObject* dataobj;
1687 PyObject* retval = NULL;
1688 DBT key, data;
1689 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001690 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691
1692
1693 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1694 &keyobj, &dataobj, &txnobj, &flags))
1695 return NULL;
1696
1697 CHECK_DB_NOT_CLOSED(self);
1698 if (!make_key_dbt(self, keyobj, &key, NULL))
1699 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001700 if ( !make_dbt(dataobj, &data) ||
1701 !checkTxnObj(txnobj, &txn) )
1702 {
1703 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001705 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706
1707 flags |= DB_GET_BOTH;
1708
1709 if (CHECK_DBFLAG(self, DB_THREAD)) {
1710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1711 data.flags = DB_DBT_MALLOC;
1712 /* TODO: Is this flag needed? We're passing a data object that should
1713 match what's in the DB, so there should be no need to malloc.
1714 We run the risk of freeing something twice! Check this. */
1715 }
1716
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1720
Gregory P. Smithe9477062005-06-04 06:46:59 +00001721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1722 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 err = 0;
1724 Py_INCREF(Py_None);
1725 retval = Py_None;
1726 }
1727 else if (!err) {
1728 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1729 FREE_DBT(data); /* Only if retrieval was successful */
1730 }
1731
1732 FREE_DBT(key);
1733 RETURN_IF_ERR();
1734 return retval;
1735}
1736
1737
1738static PyObject*
1739DB_get_byteswapped(DBObject* self, PyObject* args)
1740{
1741#if (DBVER >= 33)
1742 int err = 0;
1743#endif
1744 int retval = -1;
1745
1746 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1747 return NULL;
1748 CHECK_DB_NOT_CLOSED(self);
1749
1750#if (DBVER >= 33)
1751 MYDB_BEGIN_ALLOW_THREADS;
1752 err = self->db->get_byteswapped(self->db, &retval);
1753 MYDB_END_ALLOW_THREADS;
1754 RETURN_IF_ERR();
1755#else
1756 MYDB_BEGIN_ALLOW_THREADS;
1757 retval = self->db->get_byteswapped(self->db);
1758 MYDB_END_ALLOW_THREADS;
1759#endif
1760 return PyInt_FromLong(retval);
1761}
1762
1763
1764static PyObject*
1765DB_get_type(DBObject* self, PyObject* args)
1766{
1767 int type;
1768
1769 if (!PyArg_ParseTuple(args,":get_type"))
1770 return NULL;
1771 CHECK_DB_NOT_CLOSED(self);
1772
1773 MYDB_BEGIN_ALLOW_THREADS;
1774 type = _DB_get_type(self);
1775 MYDB_END_ALLOW_THREADS;
1776 if (type == -1)
1777 return NULL;
1778 return PyInt_FromLong(type);
1779}
1780
1781
1782static PyObject*
1783DB_join(DBObject* self, PyObject* args)
1784{
1785 int err, flags=0;
1786 int length, x;
1787 PyObject* cursorsObj;
1788 DBC** cursors;
1789 DBC* dbc;
1790
1791
1792 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1793 return NULL;
1794
1795 CHECK_DB_NOT_CLOSED(self);
1796
1797 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001798 PyErr_SetString(PyExc_TypeError,
1799 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001800 return NULL;
1801 }
1802
1803 length = PyObject_Length(cursorsObj);
1804 cursors = malloc((length+1) * sizeof(DBC*));
1805 cursors[length] = NULL;
1806 for (x=0; x<length; x++) {
1807 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001808 if (item == NULL) {
1809 free(cursors);
1810 return NULL;
1811 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001812 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001813 PyErr_SetString(PyExc_TypeError,
1814 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001815 free(cursors);
1816 return NULL;
1817 }
1818 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001819 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001820 }
1821
1822 MYDB_BEGIN_ALLOW_THREADS;
1823 err = self->db->join(self->db, cursors, &dbc, flags);
1824 MYDB_END_ALLOW_THREADS;
1825 free(cursors);
1826 RETURN_IF_ERR();
1827
Gregory P. Smith7441e652003-11-03 21:35:31 +00001828 /* FIXME: this is a buggy interface. The returned cursor
1829 contains internal references to the passed in cursors
1830 but does not hold python references to them or prevent
1831 them from being closed prematurely. This can cause
1832 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 return (PyObject*) newDBCursorObject(dbc, self);
1834}
1835
1836
1837static PyObject*
1838DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1839{
1840 int err, flags=0;
1841 PyObject* txnobj = NULL;
1842 PyObject* keyobj;
1843 DBT key;
1844 DB_TXN *txn = NULL;
1845 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001846 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001847
1848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1849 &keyobj, &txnobj, &flags))
1850 return NULL;
1851 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001852 if (!make_dbt(keyobj, &key))
1853 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 return NULL;
1855 if (!checkTxnObj(txnobj, &txn))
1856 return NULL;
1857
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->key_range(self->db, txn, &key, &range, flags);
1860 MYDB_END_ALLOW_THREADS;
1861
1862 RETURN_IF_ERR();
1863 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1864}
1865
1866
1867static PyObject*
1868DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1869{
1870 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1871 char* filename = NULL;
1872 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001873#if (DBVER >= 41)
1874 PyObject *txnobj = NULL;
1875 DB_TXN *txn = NULL;
1876 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001877 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001878 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1879 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001880 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001881 "filename", "dbtype", "flags", "mode", "txn", NULL};
1882#else
1883 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001884 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001885 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1886 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001887 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001888 "filename", "dbtype", "flags", "mode", NULL};
1889#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001890
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001891#if (DBVER >= 41)
1892 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1893 &filename, &dbname, &type, &flags, &mode,
1894 &txnobj))
1895#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001897 &filename, &dbname, &type, &flags,
1898 &mode))
1899#endif
1900 {
1901 PyErr_Clear();
1902 type = DB_UNKNOWN; flags = 0; mode = 0660;
1903 filename = NULL; dbname = NULL;
1904#if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1906 kwnames_basic,
1907 &filename, &type, &flags, &mode,
1908 &txnobj))
1909 return NULL;
1910#else
1911 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1912 kwnames_basic,
1913 &filename, &type, &flags, &mode))
1914 return NULL;
1915#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 }
1917
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918#if (DBVER >= 41)
1919 if (!checkTxnObj(txnobj, &txn)) return NULL;
1920#endif
1921
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001922 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001923 PyObject *t = Py_BuildValue("(is)", 0,
1924 "Cannot call open() twice for DB object");
1925 PyErr_SetObject(DBError, t);
1926 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001927 return NULL;
1928 }
1929
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001930#if 0 && (DBVER >= 41)
1931 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1932 && (self->myenvobj->flags & DB_INIT_TXN))
1933 {
1934 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1935 * explicitly passed) but we are in a transaction ready environment:
1936 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1937 * to work on BerkeleyDB 4.1 without needing to modify their
1938 * DBEnv or DB open calls.
1939 * TODO make this behaviour of the library configurable.
1940 */
1941 flags |= DB_AUTO_COMMIT;
1942 }
1943#endif
1944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946#if (DBVER >= 41)
1947 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1948#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001950#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 MYDB_END_ALLOW_THREADS;
1952 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001953 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 self->db = NULL;
1955 return NULL;
1956 }
1957
1958 self->flags = flags;
1959 RETURN_NONE();
1960}
1961
1962
1963static PyObject*
1964DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1965{
1966 int flags=0;
1967 PyObject* txnobj = NULL;
1968 int dlen = -1;
1969 int doff = -1;
1970 PyObject* keyobj, *dataobj, *retval;
1971 DBT key, data;
1972 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001973 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001974 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001975
1976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1977 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1978 return NULL;
1979
1980 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001981 if (!make_key_dbt(self, keyobj, &key, NULL))
1982 return NULL;
1983 if ( !make_dbt(dataobj, &data) ||
1984 !add_partial_dbt(&data, dlen, doff) ||
1985 !checkTxnObj(txnobj, &txn) )
1986 {
1987 FREE_DBT(key);
1988 return NULL;
1989 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001990
1991 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1992 FREE_DBT(key);
1993 return NULL;
1994 }
1995
1996 if (flags & DB_APPEND)
1997 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1998 else {
1999 retval = Py_None;
2000 Py_INCREF(retval);
2001 }
2002 FREE_DBT(key);
2003 return retval;
2004}
2005
2006
2007
2008static PyObject*
2009DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2010{
2011 char* filename;
2012 char* database = NULL;
2013 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002014 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002015
2016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2017 &filename, &database, &flags))
2018 return NULL;
2019 CHECK_DB_NOT_CLOSED(self);
2020
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002021 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002022 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002023 RETURN_IF_ERR();
2024 RETURN_NONE();
2025}
2026
2027
2028
2029static PyObject*
2030DB_rename(DBObject* self, PyObject* args)
2031{
2032 char* filename;
2033 char* database;
2034 char* newname;
2035 int err, flags=0;
2036
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2038 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002039 return NULL;
2040 CHECK_DB_NOT_CLOSED(self);
2041
2042 MYDB_BEGIN_ALLOW_THREADS;
2043 err = self->db->rename(self->db, filename, database, newname, flags);
2044 MYDB_END_ALLOW_THREADS;
2045 RETURN_IF_ERR();
2046 RETURN_NONE();
2047}
2048
2049
2050static PyObject*
2051DB_set_bt_minkey(DBObject* self, PyObject* args)
2052{
2053 int err, minkey;
2054
2055 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2056 return NULL;
2057 CHECK_DB_NOT_CLOSED(self);
2058
2059 MYDB_BEGIN_ALLOW_THREADS;
2060 err = self->db->set_bt_minkey(self->db, minkey);
2061 MYDB_END_ALLOW_THREADS;
2062 RETURN_IF_ERR();
2063 RETURN_NONE();
2064}
2065
Neal Norwitz84562352005-10-20 04:30:15 +00002066#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002067static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002068_default_cmp(const DBT *leftKey,
2069 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002070{
2071 int res;
2072 int lsize = leftKey->size, rsize = rightKey->size;
2073
Georg Brandlef1701f2006-03-07 14:57:48 +00002074 res = memcmp(leftKey->data, rightKey->data,
2075 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002076
2077 if (res == 0) {
2078 if (lsize < rsize) {
2079 res = -1;
2080 }
2081 else if (lsize > rsize) {
2082 res = 1;
2083 }
2084 }
2085 return res;
2086}
2087
2088static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002089_db_compareCallback(DB* db,
2090 const DBT *leftKey,
2091 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002092{
2093 int res = 0;
2094 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002095 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002096 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002097
2098 if (self == NULL || self->btCompareCallback == NULL) {
2099 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002100 PyErr_SetString(PyExc_TypeError,
2101 (self == 0
2102 ? "DB_bt_compare db is NULL."
2103 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002105 PyErr_Print();
2106 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109 MYDB_BEGIN_BLOCK_THREADS;
2110
Thomas Woutersb3153832006-03-08 01:47:19 +00002111 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2112 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002113 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002114 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002115 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002117 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002118 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002119 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 PyErr_Print();
2121 res = _default_cmp(leftKey, rightKey);
2122 } else if (PyInt_Check(result)) {
2123 res = PyInt_AsLong(result);
2124 } else {
2125 PyErr_SetString(PyExc_TypeError,
2126 "DB_bt_compare callback MUST return an int.");
2127 /* we're in a callback within the DB code, we can't raise */
2128 PyErr_Print();
2129 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 }
2131
Thomas Woutersb3153832006-03-08 01:47:19 +00002132 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134
2135 MYDB_END_BLOCK_THREADS;
2136 }
2137 return res;
2138}
2139
2140static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002141DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142{
2143 int err;
2144 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002145 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002148 return NULL;
2149
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002151
Georg Brandlef1701f2006-03-07 14:57:48 +00002152 if (!PyCallable_Check(comparator)) {
2153 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002154 return NULL;
2155 }
2156
2157 /*
2158 * Perform a test call of the comparator function with two empty
2159 * string objects here. verify that it returns an int (0).
2160 * err if not.
2161 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002162 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 result = PyEval_CallObject(comparator, tuple);
2164 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002165 if (result == NULL)
2166 return NULL;
2167 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002168 PyErr_SetString(PyExc_TypeError,
2169 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002170 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002171 } else if (PyInt_AsLong(result) != 0) {
2172 PyErr_SetString(PyExc_TypeError,
2173 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002174 return NULL;
2175 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002176 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002177
2178 /* We don't accept multiple set_bt_compare operations, in order to
2179 * simplify the code. This would have no real use, as one cannot
2180 * change the function once the db is opened anyway */
2181 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183 return NULL;
2184 }
2185
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187 self->btCompareCallback = comparator;
2188
2189 /* This is to workaround a problem with un-initialized threads (see
2190 comment in DB_associate) */
2191#ifdef WITH_THREAD
2192 PyEval_InitThreads();
2193#endif
2194
Thomas Woutersb3153832006-03-08 01:47:19 +00002195 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002196
2197 if (err) {
2198 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002199 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200 self->btCompareCallback = NULL;
2201 }
2202
Georg Brandlef1701f2006-03-07 14:57:48 +00002203 RETURN_IF_ERR();
2204 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002205}
Neal Norwitz84562352005-10-20 04:30:15 +00002206#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002208
2209static PyObject*
2210DB_set_cachesize(DBObject* self, PyObject* args)
2211{
2212 int err;
2213 int gbytes = 0, bytes = 0, ncache = 0;
2214
2215 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2216 &gbytes,&bytes,&ncache))
2217 return NULL;
2218 CHECK_DB_NOT_CLOSED(self);
2219
2220 MYDB_BEGIN_ALLOW_THREADS;
2221 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2222 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2225}
2226
2227
2228static PyObject*
2229DB_set_flags(DBObject* self, PyObject* args)
2230{
2231 int err, flags;
2232
2233 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2234 return NULL;
2235 CHECK_DB_NOT_CLOSED(self);
2236
2237 MYDB_BEGIN_ALLOW_THREADS;
2238 err = self->db->set_flags(self->db, flags);
2239 MYDB_END_ALLOW_THREADS;
2240 RETURN_IF_ERR();
2241
2242 self->setflags |= flags;
2243 RETURN_NONE();
2244}
2245
2246
2247static PyObject*
2248DB_set_h_ffactor(DBObject* self, PyObject* args)
2249{
2250 int err, ffactor;
2251
2252 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2253 return NULL;
2254 CHECK_DB_NOT_CLOSED(self);
2255
2256 MYDB_BEGIN_ALLOW_THREADS;
2257 err = self->db->set_h_ffactor(self->db, ffactor);
2258 MYDB_END_ALLOW_THREADS;
2259 RETURN_IF_ERR();
2260 RETURN_NONE();
2261}
2262
2263
2264static PyObject*
2265DB_set_h_nelem(DBObject* self, PyObject* args)
2266{
2267 int err, nelem;
2268
2269 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2270 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2272
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_h_nelem(self->db, nelem);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2278}
2279
2280
2281static PyObject*
2282DB_set_lorder(DBObject* self, PyObject* args)
2283{
2284 int err, lorder;
2285
2286 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2287 return NULL;
2288 CHECK_DB_NOT_CLOSED(self);
2289
2290 MYDB_BEGIN_ALLOW_THREADS;
2291 err = self->db->set_lorder(self->db, lorder);
2292 MYDB_END_ALLOW_THREADS;
2293 RETURN_IF_ERR();
2294 RETURN_NONE();
2295}
2296
2297
2298static PyObject*
2299DB_set_pagesize(DBObject* self, PyObject* args)
2300{
2301 int err, pagesize;
2302
2303 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2304 return NULL;
2305 CHECK_DB_NOT_CLOSED(self);
2306
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->set_pagesize(self->db, pagesize);
2309 MYDB_END_ALLOW_THREADS;
2310 RETURN_IF_ERR();
2311 RETURN_NONE();
2312}
2313
2314
2315static PyObject*
2316DB_set_re_delim(DBObject* self, PyObject* args)
2317{
2318 int err;
2319 char delim;
2320
2321 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2322 PyErr_Clear();
2323 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2324 return NULL;
2325 }
2326
2327 CHECK_DB_NOT_CLOSED(self);
2328
2329 MYDB_BEGIN_ALLOW_THREADS;
2330 err = self->db->set_re_delim(self->db, delim);
2331 MYDB_END_ALLOW_THREADS;
2332 RETURN_IF_ERR();
2333 RETURN_NONE();
2334}
2335
2336static PyObject*
2337DB_set_re_len(DBObject* self, PyObject* args)
2338{
2339 int err, len;
2340
2341 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2342 return NULL;
2343 CHECK_DB_NOT_CLOSED(self);
2344
2345 MYDB_BEGIN_ALLOW_THREADS;
2346 err = self->db->set_re_len(self->db, len);
2347 MYDB_END_ALLOW_THREADS;
2348 RETURN_IF_ERR();
2349 RETURN_NONE();
2350}
2351
2352
2353static PyObject*
2354DB_set_re_pad(DBObject* self, PyObject* args)
2355{
2356 int err;
2357 char pad;
2358
2359 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2360 PyErr_Clear();
2361 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2362 return NULL;
2363 }
2364 CHECK_DB_NOT_CLOSED(self);
2365
2366 MYDB_BEGIN_ALLOW_THREADS;
2367 err = self->db->set_re_pad(self->db, pad);
2368 MYDB_END_ALLOW_THREADS;
2369 RETURN_IF_ERR();
2370 RETURN_NONE();
2371}
2372
2373
2374static PyObject*
2375DB_set_re_source(DBObject* self, PyObject* args)
2376{
2377 int err;
2378 char *re_source;
2379
2380 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2381 return NULL;
2382 CHECK_DB_NOT_CLOSED(self);
2383
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_re_source(self->db, re_source);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388 RETURN_NONE();
2389}
2390
2391
2392#if (DBVER >= 32)
2393static PyObject*
2394DB_set_q_extentsize(DBObject* self, PyObject* args)
2395{
2396 int err;
2397 int extentsize;
2398
2399 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2400 return NULL;
2401 CHECK_DB_NOT_CLOSED(self);
2402
2403 MYDB_BEGIN_ALLOW_THREADS;
2404 err = self->db->set_q_extentsize(self->db, extentsize);
2405 MYDB_END_ALLOW_THREADS;
2406 RETURN_IF_ERR();
2407 RETURN_NONE();
2408}
2409#endif
2410
2411static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002412DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002413{
2414 int err, flags = 0, type;
2415 void* sp;
2416 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002417#if (DBVER >= 43)
2418 PyObject* txnobj = NULL;
2419 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002420 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002421#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002422 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002423#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002424
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002425#if (DBVER >= 43)
2426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2427 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002428 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002429 if (!checkTxnObj(txnobj, &txn))
2430 return NULL;
2431#else
2432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2433 return NULL;
2434#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002435 CHECK_DB_NOT_CLOSED(self);
2436
2437 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438#if (DBVER >= 43)
2439 err = self->db->stat(self->db, txn, &sp, flags);
2440#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441 err = self->db->stat(self->db, &sp, flags);
2442#else
2443 err = self->db->stat(self->db, &sp, NULL, flags);
2444#endif
2445 MYDB_END_ALLOW_THREADS;
2446 RETURN_IF_ERR();
2447
2448 self->haveStat = 1;
2449
2450 /* Turn the stat structure into a dictionary */
2451 type = _DB_get_type(self);
2452 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2453 free(sp);
2454 return NULL;
2455 }
2456
2457#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2458#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2459#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2460
2461 switch (type) {
2462 case DB_HASH:
2463 MAKE_HASH_ENTRY(magic);
2464 MAKE_HASH_ENTRY(version);
2465 MAKE_HASH_ENTRY(nkeys);
2466 MAKE_HASH_ENTRY(ndata);
2467 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002468#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002469 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002470#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 MAKE_HASH_ENTRY(ffactor);
2472 MAKE_HASH_ENTRY(buckets);
2473 MAKE_HASH_ENTRY(free);
2474 MAKE_HASH_ENTRY(bfree);
2475 MAKE_HASH_ENTRY(bigpages);
2476 MAKE_HASH_ENTRY(big_bfree);
2477 MAKE_HASH_ENTRY(overflows);
2478 MAKE_HASH_ENTRY(ovfl_free);
2479 MAKE_HASH_ENTRY(dup);
2480 MAKE_HASH_ENTRY(dup_free);
2481 break;
2482
2483 case DB_BTREE:
2484 case DB_RECNO:
2485 MAKE_BT_ENTRY(magic);
2486 MAKE_BT_ENTRY(version);
2487 MAKE_BT_ENTRY(nkeys);
2488 MAKE_BT_ENTRY(ndata);
2489 MAKE_BT_ENTRY(pagesize);
2490 MAKE_BT_ENTRY(minkey);
2491 MAKE_BT_ENTRY(re_len);
2492 MAKE_BT_ENTRY(re_pad);
2493 MAKE_BT_ENTRY(levels);
2494 MAKE_BT_ENTRY(int_pg);
2495 MAKE_BT_ENTRY(leaf_pg);
2496 MAKE_BT_ENTRY(dup_pg);
2497 MAKE_BT_ENTRY(over_pg);
2498 MAKE_BT_ENTRY(free);
2499 MAKE_BT_ENTRY(int_pgfree);
2500 MAKE_BT_ENTRY(leaf_pgfree);
2501 MAKE_BT_ENTRY(dup_pgfree);
2502 MAKE_BT_ENTRY(over_pgfree);
2503 break;
2504
2505 case DB_QUEUE:
2506 MAKE_QUEUE_ENTRY(magic);
2507 MAKE_QUEUE_ENTRY(version);
2508 MAKE_QUEUE_ENTRY(nkeys);
2509 MAKE_QUEUE_ENTRY(ndata);
2510 MAKE_QUEUE_ENTRY(pagesize);
2511 MAKE_QUEUE_ENTRY(pages);
2512 MAKE_QUEUE_ENTRY(re_len);
2513 MAKE_QUEUE_ENTRY(re_pad);
2514 MAKE_QUEUE_ENTRY(pgfree);
2515#if (DBVER == 31)
2516 MAKE_QUEUE_ENTRY(start);
2517#endif
2518 MAKE_QUEUE_ENTRY(first_recno);
2519 MAKE_QUEUE_ENTRY(cur_recno);
2520 break;
2521
2522 default:
2523 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2524 Py_DECREF(d);
2525 d = NULL;
2526 }
2527
2528#undef MAKE_HASH_ENTRY
2529#undef MAKE_BT_ENTRY
2530#undef MAKE_QUEUE_ENTRY
2531
2532 free(sp);
2533 return d;
2534}
2535
2536static PyObject*
2537DB_sync(DBObject* self, PyObject* args)
2538{
2539 int err;
2540 int flags = 0;
2541
2542 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2543 return NULL;
2544 CHECK_DB_NOT_CLOSED(self);
2545
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->db->sync(self->db, flags);
2548 MYDB_END_ALLOW_THREADS;
2549 RETURN_IF_ERR();
2550 RETURN_NONE();
2551}
2552
2553
2554#if (DBVER >= 33)
2555static PyObject*
2556DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2557{
2558 int err, flags=0;
2559 u_int32_t count=0;
2560 PyObject* txnobj = NULL;
2561 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002562 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002563
2564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2565 &txnobj, &flags))
2566 return NULL;
2567 CHECK_DB_NOT_CLOSED(self);
2568 if (!checkTxnObj(txnobj, &txn))
2569 return NULL;
2570
2571 MYDB_BEGIN_ALLOW_THREADS;
2572 err = self->db->truncate(self->db, txn, &count, flags);
2573 MYDB_END_ALLOW_THREADS;
2574 RETURN_IF_ERR();
2575 return PyInt_FromLong(count);
2576}
2577#endif
2578
2579
2580static PyObject*
2581DB_upgrade(DBObject* self, PyObject* args)
2582{
2583 int err, flags=0;
2584 char *filename;
2585
2586 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2587 return NULL;
2588 CHECK_DB_NOT_CLOSED(self);
2589
2590 MYDB_BEGIN_ALLOW_THREADS;
2591 err = self->db->upgrade(self->db, filename, flags);
2592 MYDB_END_ALLOW_THREADS;
2593 RETURN_IF_ERR();
2594 RETURN_NONE();
2595}
2596
2597
2598static PyObject*
2599DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2600{
2601 int err, flags=0;
2602 char* fileName;
2603 char* dbName=NULL;
2604 char* outFileName=NULL;
2605 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002606 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002607 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002608
2609 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2610 &fileName, &dbName, &outFileName, &flags))
2611 return NULL;
2612
2613 CHECK_DB_NOT_CLOSED(self);
2614 if (outFileName)
2615 outFile = fopen(outFileName, "w");
2616
2617 MYDB_BEGIN_ALLOW_THREADS;
2618 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2619 MYDB_END_ALLOW_THREADS;
2620 if (outFileName)
2621 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002622
2623 /* DB.verify acts as a DB handle destructor (like close); this was
2624 * documented in BerkeleyDB 4.2 but had the undocumented effect
2625 * of not being safe in prior versions while still requiring an explicit
2626 * DB.close call afterwards. Lets call close for the user to emulate
2627 * the safe 4.2 behaviour. */
2628#if (DBVER <= 41)
2629 self->db->close(self->db, 0);
2630#endif
2631 self->db = NULL;
2632
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002633 RETURN_IF_ERR();
2634 RETURN_NONE();
2635}
2636
2637
2638static PyObject*
2639DB_set_get_returns_none(DBObject* self, PyObject* args)
2640{
2641 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002642 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002643
2644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2645 return NULL;
2646 CHECK_DB_NOT_CLOSED(self);
2647
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002648 if (self->moduleFlags.getReturnsNone)
2649 ++oldValue;
2650 if (self->moduleFlags.cursorSetReturnsNone)
2651 ++oldValue;
2652 self->moduleFlags.getReturnsNone = (flags >= 1);
2653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654 return PyInt_FromLong(oldValue);
2655}
2656
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002657#if (DBVER >= 41)
2658static PyObject*
2659DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2660{
2661 int err;
2662 u_int32_t flags=0;
2663 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002664 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002665
2666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2667 &passwd, &flags)) {
2668 return NULL;
2669 }
2670
2671 MYDB_BEGIN_ALLOW_THREADS;
2672 err = self->db->set_encrypt(self->db, passwd, flags);
2673 MYDB_END_ALLOW_THREADS;
2674
2675 RETURN_IF_ERR();
2676 RETURN_NONE();
2677}
2678#endif /* DBVER >= 41 */
2679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002680
2681/*-------------------------------------------------------------- */
2682/* Mapping and Dictionary-like access routines */
2683
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002684Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002685{
2686 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002687 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 int flags = 0;
2689 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002690 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002691
2692 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002693 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2694 PyErr_SetObject(DBError, t);
2695 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 return -1;
2697 }
2698
2699 if (self->haveStat) { /* Has the stat function been called recently? If
2700 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002701 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 }
2703
2704 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002705redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002706#if (DBVER >= 43)
2707 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2708#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 err = self->db->stat(self->db, &sp, flags);
2710#else
2711 err = self->db->stat(self->db, &sp, NULL, flags);
2712#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002713
2714 /* All the stat structures have matching fields upto the ndata field,
2715 so we can use any of them for the type cast */
2716 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2717
2718 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2719 * redo a full stat to make sure.
2720 * Fixes SF python bug 1493322, pybsddb bug 1184012
2721 */
2722 if (size == 0 && (flags & DB_FAST_STAT)) {
2723 flags = 0;
2724 goto redo_stat_for_length;
2725 }
2726
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 MYDB_END_ALLOW_THREADS;
2728
2729 if (err)
2730 return -1;
2731
2732 self->haveStat = 1;
2733
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 free(sp);
2735 return size;
2736}
2737
2738
2739PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2740{
2741 int err;
2742 PyObject* retval;
2743 DBT key;
2744 DBT data;
2745
2746 CHECK_DB_NOT_CLOSED(self);
2747 if (!make_key_dbt(self, keyobj, &key, NULL))
2748 return NULL;
2749
2750 CLEAR_DBT(data);
2751 if (CHECK_DBFLAG(self, DB_THREAD)) {
2752 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2753 data.flags = DB_DBT_MALLOC;
2754 }
2755 MYDB_BEGIN_ALLOW_THREADS;
2756 err = self->db->get(self->db, NULL, &key, &data, 0);
2757 MYDB_END_ALLOW_THREADS;
2758 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2759 PyErr_SetObject(PyExc_KeyError, keyobj);
2760 retval = NULL;
2761 }
2762 else if (makeDBError(err)) {
2763 retval = NULL;
2764 }
2765 else {
2766 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2767 FREE_DBT(data);
2768 }
2769
2770 FREE_DBT(key);
2771 return retval;
2772}
2773
2774
2775static int
2776DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2777{
2778 DBT key, data;
2779 int retval;
2780 int flags = 0;
2781
2782 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002783 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2784 PyErr_SetObject(DBError, t);
2785 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 return -1;
2787 }
2788
2789 if (!make_key_dbt(self, keyobj, &key, NULL))
2790 return -1;
2791
2792 if (dataobj != NULL) {
2793 if (!make_dbt(dataobj, &data))
2794 retval = -1;
2795 else {
2796 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002797 /* dictionaries shouldn't have duplicate keys */
2798 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 retval = _DB_put(self, NULL, &key, &data, flags);
2800
2801 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002802 /* try deleting any old record that matches and then PUT it
2803 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804 _DB_delete(self, NULL, &key, 0);
2805 PyErr_Clear();
2806 retval = _DB_put(self, NULL, &key, &data, flags);
2807 }
2808 }
2809 }
2810 else {
2811 /* dataobj == NULL, so delete the key */
2812 retval = _DB_delete(self, NULL, &key, 0);
2813 }
2814 FREE_DBT(key);
2815 return retval;
2816}
2817
2818
2819static PyObject*
2820DB_has_key(DBObject* self, PyObject* args)
2821{
2822 int err;
2823 PyObject* keyobj;
2824 DBT key, data;
2825 PyObject* txnobj = NULL;
2826 DB_TXN *txn = NULL;
2827
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002828 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002829 return NULL;
2830 CHECK_DB_NOT_CLOSED(self);
2831 if (!make_key_dbt(self, keyobj, &key, NULL))
2832 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002833 if (!checkTxnObj(txnobj, &txn)) {
2834 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002836 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002837
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002838 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 it has a record but can't allocate a buffer for the data. This saves
2840 having to deal with data we won't be using.
2841 */
2842 CLEAR_DBT(data);
2843 data.flags = DB_DBT_USERMEM;
2844
2845 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002846 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 MYDB_END_ALLOW_THREADS;
2848 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002849
2850 if (err == DB_BUFFER_SMALL || err == 0) {
2851 return PyInt_FromLong(1);
2852 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2853 return PyInt_FromLong(0);
2854 }
2855
2856 makeDBError(err);
2857 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858}
2859
2860
2861#define _KEYS_LIST 1
2862#define _VALUES_LIST 2
2863#define _ITEMS_LIST 3
2864
2865static PyObject*
2866_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2867{
2868 int err, dbtype;
2869 DBT key;
2870 DBT data;
2871 DBC *cursor;
2872 PyObject* list;
2873 PyObject* item = NULL;
2874
2875 CHECK_DB_NOT_CLOSED(self);
2876 CLEAR_DBT(key);
2877 CLEAR_DBT(data);
2878
2879 dbtype = _DB_get_type(self);
2880 if (dbtype == -1)
2881 return NULL;
2882
2883 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002884 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002885 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002886
2887 /* get a cursor */
2888 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002889 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002890 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002891 if (makeDBError(err)) {
2892 Py_DECREF(list);
2893 return NULL;
2894 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002895
2896 if (CHECK_DBFLAG(self, DB_THREAD)) {
2897 key.flags = DB_DBT_REALLOC;
2898 data.flags = DB_DBT_REALLOC;
2899 }
2900
2901 while (1) { /* use the cursor to traverse the DB, collecting items */
2902 MYDB_BEGIN_ALLOW_THREADS;
2903 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2904 MYDB_END_ALLOW_THREADS;
2905
2906 if (err) {
2907 /* for any error, break out of the loop */
2908 break;
2909 }
2910
2911 switch (type) {
2912 case _KEYS_LIST:
2913 switch(dbtype) {
2914 case DB_BTREE:
2915 case DB_HASH:
2916 default:
2917 item = PyString_FromStringAndSize((char*)key.data, key.size);
2918 break;
2919 case DB_RECNO:
2920 case DB_QUEUE:
2921 item = PyInt_FromLong(*((db_recno_t*)key.data));
2922 break;
2923 }
2924 break;
2925
2926 case _VALUES_LIST:
2927 item = PyString_FromStringAndSize((char*)data.data, data.size);
2928 break;
2929
2930 case _ITEMS_LIST:
2931 switch(dbtype) {
2932 case DB_BTREE:
2933 case DB_HASH:
2934 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002935 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2936 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 break;
2938 case DB_RECNO:
2939 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002940 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2941 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002942 break;
2943 }
2944 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002945 default:
2946 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2947 item = NULL;
2948 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002949 }
2950 if (item == NULL) {
2951 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002952 list = NULL;
2953 goto done;
2954 }
2955 PyList_Append(list, item);
2956 Py_DECREF(item);
2957 }
2958
Gregory P. Smithe9477062005-06-04 06:46:59 +00002959 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2960 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 Py_DECREF(list);
2962 list = NULL;
2963 }
2964
2965 done:
2966 FREE_DBT(key);
2967 FREE_DBT(data);
2968 MYDB_BEGIN_ALLOW_THREADS;
2969 cursor->c_close(cursor);
2970 MYDB_END_ALLOW_THREADS;
2971 return list;
2972}
2973
2974
2975static PyObject*
2976DB_keys(DBObject* self, PyObject* args)
2977{
2978 PyObject* txnobj = NULL;
2979 DB_TXN *txn = NULL;
2980
Georg Brandl96a8c392006-05-29 21:04:52 +00002981 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 return NULL;
2983 if (!checkTxnObj(txnobj, &txn))
2984 return NULL;
2985 return _DB_make_list(self, txn, _KEYS_LIST);
2986}
2987
2988
2989static PyObject*
2990DB_items(DBObject* self, PyObject* args)
2991{
2992 PyObject* txnobj = NULL;
2993 DB_TXN *txn = NULL;
2994
Georg Brandl96a8c392006-05-29 21:04:52 +00002995 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 return NULL;
2997 if (!checkTxnObj(txnobj, &txn))
2998 return NULL;
2999 return _DB_make_list(self, txn, _ITEMS_LIST);
3000}
3001
3002
3003static PyObject*
3004DB_values(DBObject* self, PyObject* args)
3005{
3006 PyObject* txnobj = NULL;
3007 DB_TXN *txn = NULL;
3008
Georg Brandl96a8c392006-05-29 21:04:52 +00003009 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003010 return NULL;
3011 if (!checkTxnObj(txnobj, &txn))
3012 return NULL;
3013 return _DB_make_list(self, txn, _VALUES_LIST);
3014}
3015
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016/* --------------------------------------------------------------------- */
3017/* DBCursor methods */
3018
3019
3020static PyObject*
3021DBC_close(DBCursorObject* self, PyObject* args)
3022{
3023 int err = 0;
3024
3025 if (!PyArg_ParseTuple(args, ":close"))
3026 return NULL;
3027
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 if (self->dbc != NULL) {
3029 MYDB_BEGIN_ALLOW_THREADS;
3030 err = self->dbc->c_close(self->dbc);
3031 self->dbc = NULL;
3032 MYDB_END_ALLOW_THREADS;
3033 }
3034 RETURN_IF_ERR();
3035 RETURN_NONE();
3036}
3037
3038
3039static PyObject*
3040DBC_count(DBCursorObject* self, PyObject* args)
3041{
3042 int err = 0;
3043 db_recno_t count;
3044 int flags = 0;
3045
3046 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3047 return NULL;
3048
3049 CHECK_CURSOR_NOT_CLOSED(self);
3050
3051 MYDB_BEGIN_ALLOW_THREADS;
3052 err = self->dbc->c_count(self->dbc, &count, flags);
3053 MYDB_END_ALLOW_THREADS;
3054 RETURN_IF_ERR();
3055
3056 return PyInt_FromLong(count);
3057}
3058
3059
3060static PyObject*
3061DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3062{
3063 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3064}
3065
3066
3067static PyObject*
3068DBC_delete(DBCursorObject* self, PyObject* args)
3069{
3070 int err, flags=0;
3071
3072 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3073 return NULL;
3074
3075 CHECK_CURSOR_NOT_CLOSED(self);
3076
3077 MYDB_BEGIN_ALLOW_THREADS;
3078 err = self->dbc->c_del(self->dbc, flags);
3079 MYDB_END_ALLOW_THREADS;
3080 RETURN_IF_ERR();
3081
3082 self->mydb->haveStat = 0;
3083 RETURN_NONE();
3084}
3085
3086
3087static PyObject*
3088DBC_dup(DBCursorObject* self, PyObject* args)
3089{
3090 int err, flags =0;
3091 DBC* dbc = NULL;
3092
3093 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3094 return NULL;
3095
3096 CHECK_CURSOR_NOT_CLOSED(self);
3097
3098 MYDB_BEGIN_ALLOW_THREADS;
3099 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3100 MYDB_END_ALLOW_THREADS;
3101 RETURN_IF_ERR();
3102
3103 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3104}
3105
3106static PyObject*
3107DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3108{
3109 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3110}
3111
3112
3113static PyObject*
3114DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3115{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003116 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 PyObject* keyobj = NULL;
3118 PyObject* dataobj = NULL;
3119 PyObject* retval = NULL;
3120 int dlen = -1;
3121 int doff = -1;
3122 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003123 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003124 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003125
3126 CLEAR_DBT(key);
3127 CLEAR_DBT(data);
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003129 &flags, &dlen, &doff))
3130 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3133 &kwnames[1],
3134 &keyobj, &flags, &dlen, &doff))
3135 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003137 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3138 kwnames, &keyobj, &dataobj,
3139 &flags, &dlen, &doff))
3140 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141 return NULL;
3142 }
3143 }
3144 }
3145
3146 CHECK_CURSOR_NOT_CLOSED(self);
3147
3148 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3149 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003150 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3151 (!add_partial_dbt(&data, dlen, doff)) )
3152 {
3153 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003154 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003155 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156
3157 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3158 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003159 if (!(key.flags & DB_DBT_REALLOC)) {
3160 key.flags |= DB_DBT_MALLOC;
3161 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 }
3163
3164 MYDB_BEGIN_ALLOW_THREADS;
3165 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3166 MYDB_END_ALLOW_THREADS;
3167
Gregory P. Smithe9477062005-06-04 06:46:59 +00003168 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3169 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 Py_INCREF(Py_None);
3171 retval = Py_None;
3172 }
3173 else if (makeDBError(err)) {
3174 retval = NULL;
3175 }
3176 else {
3177 switch (_DB_get_type(self->mydb)) {
3178 case -1:
3179 retval = NULL;
3180 break;
3181 case DB_BTREE:
3182 case DB_HASH:
3183 default:
3184 retval = Py_BuildValue("s#s#", key.data, key.size,
3185 data.data, data.size);
3186 break;
3187 case DB_RECNO:
3188 case DB_QUEUE:
3189 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3190 data.data, data.size);
3191 break;
3192 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003193 FREE_DBT(data);
3194 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003195 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 return retval;
3197}
3198
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003199#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003200static PyObject*
3201DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3202{
3203 int err, flags=0;
3204 PyObject* keyobj = NULL;
3205 PyObject* dataobj = NULL;
3206 PyObject* retval = NULL;
3207 int dlen = -1;
3208 int doff = -1;
3209 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003210 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3211 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003212
3213 CLEAR_DBT(key);
3214 CLEAR_DBT(data);
3215 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3216 &flags, &dlen, &doff))
3217 {
3218 PyErr_Clear();
3219 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003220 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003221 &keyobj, &flags, &dlen, &doff))
3222 {
3223 PyErr_Clear();
3224 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3225 kwnames, &keyobj, &dataobj,
3226 &flags, &dlen, &doff))
3227 {
3228 return NULL;
3229 }
3230 }
3231 }
3232
3233 CHECK_CURSOR_NOT_CLOSED(self);
3234
3235 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3236 return NULL;
3237 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3238 (!add_partial_dbt(&data, dlen, doff)) ) {
3239 FREE_DBT(key);
3240 return NULL;
3241 }
3242
3243 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3244 data.flags = DB_DBT_MALLOC;
3245 if (!(key.flags & DB_DBT_REALLOC)) {
3246 key.flags |= DB_DBT_MALLOC;
3247 }
3248 }
3249
3250 CLEAR_DBT(pkey);
3251 pkey.flags = DB_DBT_MALLOC;
3252
3253 MYDB_BEGIN_ALLOW_THREADS;
3254 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3255 MYDB_END_ALLOW_THREADS;
3256
Gregory P. Smithe9477062005-06-04 06:46:59 +00003257 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3258 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003259 Py_INCREF(Py_None);
3260 retval = Py_None;
3261 }
3262 else if (makeDBError(err)) {
3263 retval = NULL;
3264 }
3265 else {
3266 PyObject *pkeyObj;
3267 PyObject *dataObj;
3268 dataObj = PyString_FromStringAndSize(data.data, data.size);
3269
3270 if (self->mydb->primaryDBType == DB_RECNO ||
3271 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003272 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003273 else
3274 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3275
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003276 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003277 {
3278 PyObject *keyObj;
3279 int type = _DB_get_type(self->mydb);
3280 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003281 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003282 else
3283 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003284#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003285 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003286#else
3287 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3288#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003289 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003290 FREE_DBT(key);
3291 }
3292 else /* return just the pkey and data */
3293 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003294#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003295 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003296#else
3297 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3298#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003300 Py_DECREF(dataObj);
3301 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302 FREE_DBT(pkey);
3303 FREE_DBT(data);
3304 }
3305 /* the only time REALLOC should be set is if we used an integer
3306 * key that make_key_dbt malloc'd for us. always free these. */
3307 if (key.flags & DB_DBT_REALLOC) {
3308 FREE_DBT(key);
3309 }
3310 return retval;
3311}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003312#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003314
3315static PyObject*
3316DBC_get_recno(DBCursorObject* self, PyObject* args)
3317{
3318 int err;
3319 db_recno_t recno;
3320 DBT key;
3321 DBT data;
3322
3323 if (!PyArg_ParseTuple(args, ":get_recno"))
3324 return NULL;
3325
3326 CHECK_CURSOR_NOT_CLOSED(self);
3327
3328 CLEAR_DBT(key);
3329 CLEAR_DBT(data);
3330 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3331 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3332 data.flags = DB_DBT_MALLOC;
3333 key.flags = DB_DBT_MALLOC;
3334 }
3335
3336 MYDB_BEGIN_ALLOW_THREADS;
3337 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3338 MYDB_END_ALLOW_THREADS;
3339 RETURN_IF_ERR();
3340
3341 recno = *((db_recno_t*)data.data);
3342 FREE_DBT(key);
3343 FREE_DBT(data);
3344 return PyInt_FromLong(recno);
3345}
3346
3347
3348static PyObject*
3349DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3350{
3351 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3352}
3353
3354
3355static PyObject*
3356DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3357{
3358 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3359}
3360
3361
3362static PyObject*
3363DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3364{
3365 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3366}
3367
3368
3369static PyObject*
3370DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3371{
3372 int err, flags = 0;
3373 PyObject* keyobj, *dataobj;
3374 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003375 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003376 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003377 int dlen = -1;
3378 int doff = -1;
3379
3380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3381 &keyobj, &dataobj, &flags, &dlen, &doff))
3382 return NULL;
3383
3384 CHECK_CURSOR_NOT_CLOSED(self);
3385
3386 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3387 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003388 if (!make_dbt(dataobj, &data) ||
3389 !add_partial_dbt(&data, dlen, doff) )
3390 {
3391 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003392 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394
3395 MYDB_BEGIN_ALLOW_THREADS;
3396 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3397 MYDB_END_ALLOW_THREADS;
3398 FREE_DBT(key);
3399 RETURN_IF_ERR();
3400 self->mydb->haveStat = 0;
3401 RETURN_NONE();
3402}
3403
3404
3405static PyObject*
3406DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3407{
3408 int err, flags = 0;
3409 DBT key, data;
3410 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003411 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 int dlen = -1;
3413 int doff = -1;
3414
3415 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3416 &keyobj, &flags, &dlen, &doff))
3417 return NULL;
3418
3419 CHECK_CURSOR_NOT_CLOSED(self);
3420
3421 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3422 return NULL;
3423
3424 CLEAR_DBT(data);
3425 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3426 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3427 data.flags = DB_DBT_MALLOC;
3428 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003429 if (!add_partial_dbt(&data, dlen, doff)) {
3430 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003432 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433
3434 MYDB_BEGIN_ALLOW_THREADS;
3435 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3436 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003437 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3438 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003439 Py_INCREF(Py_None);
3440 retval = Py_None;
3441 }
3442 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003443 retval = NULL;
3444 }
3445 else {
3446 switch (_DB_get_type(self->mydb)) {
3447 case -1:
3448 retval = NULL;
3449 break;
3450 case DB_BTREE:
3451 case DB_HASH:
3452 default:
3453 retval = Py_BuildValue("s#s#", key.data, key.size,
3454 data.data, data.size);
3455 break;
3456 case DB_RECNO:
3457 case DB_QUEUE:
3458 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3459 data.data, data.size);
3460 break;
3461 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003462 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003463 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003465 /* the only time REALLOC should be set is if we used an integer
3466 * key that make_key_dbt malloc'd for us. always free these. */
3467 if (key.flags & DB_DBT_REALLOC) {
3468 FREE_DBT(key);
3469 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470
3471 return retval;
3472}
3473
3474
3475static PyObject*
3476DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3477{
3478 int err, flags = 0;
3479 DBT key, data;
3480 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003481 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 int dlen = -1;
3483 int doff = -1;
3484
3485 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3486 &keyobj, &flags, &dlen, &doff))
3487 return NULL;
3488
3489 CHECK_CURSOR_NOT_CLOSED(self);
3490
3491 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3492 return NULL;
3493
3494 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003495 if (!add_partial_dbt(&data, dlen, doff)) {
3496 FREE_DBT(key);
3497 return NULL;
3498 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003499 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3500 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003501 data.flags |= DB_DBT_MALLOC;
3502 /* only BTREE databases will return anything in the key */
3503 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3504 key.flags |= DB_DBT_MALLOC;
3505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003506 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003507 MYDB_BEGIN_ALLOW_THREADS;
3508 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3509 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003510 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3511 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003512 Py_INCREF(Py_None);
3513 retval = Py_None;
3514 }
3515 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 retval = NULL;
3517 }
3518 else {
3519 switch (_DB_get_type(self->mydb)) {
3520 case -1:
3521 retval = NULL;
3522 break;
3523 case DB_BTREE:
3524 case DB_HASH:
3525 default:
3526 retval = Py_BuildValue("s#s#", key.data, key.size,
3527 data.data, data.size);
3528 break;
3529 case DB_RECNO:
3530 case DB_QUEUE:
3531 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3532 data.data, data.size);
3533 break;
3534 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003535 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 FREE_DBT(data);
3537 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003538 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003539 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003540 if (key.flags & DB_DBT_REALLOC) {
3541 FREE_DBT(key);
3542 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543
3544 return retval;
3545}
3546
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003548_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3549 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003551 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003553 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554
Gregory P. Smith7441e652003-11-03 21:35:31 +00003555 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3557 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003558 if (!make_dbt(dataobj, &data)) {
3559 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003560 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003561 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562
3563 MYDB_BEGIN_ALLOW_THREADS;
3564 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3565 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003566 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003567 Py_INCREF(Py_None);
3568 retval = Py_None;
3569 }
3570 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 retval = NULL;
3572 }
3573 else {
3574 switch (_DB_get_type(self->mydb)) {
3575 case -1:
3576 retval = NULL;
3577 break;
3578 case DB_BTREE:
3579 case DB_HASH:
3580 default:
3581 retval = Py_BuildValue("s#s#", key.data, key.size,
3582 data.data, data.size);
3583 break;
3584 case DB_RECNO:
3585 case DB_QUEUE:
3586 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3587 data.data, data.size);
3588 break;
3589 }
3590 }
3591
3592 FREE_DBT(key);
3593 return retval;
3594}
3595
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003596static PyObject*
3597DBC_get_both(DBCursorObject* self, PyObject* args)
3598{
3599 int flags=0;
3600 PyObject *keyobj, *dataobj;
3601
3602 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3603 return NULL;
3604
Gregory P. Smith7441e652003-11-03 21:35:31 +00003605 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003606 CHECK_CURSOR_NOT_CLOSED(self);
3607
3608 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3609 self->mydb->moduleFlags.getReturnsNone);
3610}
3611
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003612/* Return size of entry */
3613static PyObject*
3614DBC_get_current_size(DBCursorObject* self, PyObject* args)
3615{
3616 int err, flags=DB_CURRENT;
3617 PyObject* retval = NULL;
3618 DBT key, data;
3619
3620 if (!PyArg_ParseTuple(args, ":get_current_size"))
3621 return NULL;
3622 CHECK_CURSOR_NOT_CLOSED(self);
3623 CLEAR_DBT(key);
3624 CLEAR_DBT(data);
3625
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003626 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003627 getting the record size. */
3628 data.flags = DB_DBT_USERMEM;
3629 data.ulen = 0;
3630 MYDB_BEGIN_ALLOW_THREADS;
3631 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3632 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003633 if (err == DB_BUFFER_SMALL || !err) {
3634 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003635 retval = PyInt_FromLong((long)data.size);
3636 err = 0;
3637 }
3638
3639 FREE_DBT(key);
3640 FREE_DBT(data);
3641 RETURN_IF_ERR();
3642 return retval;
3643}
3644
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003645static PyObject*
3646DBC_set_both(DBCursorObject* self, PyObject* args)
3647{
3648 int flags=0;
3649 PyObject *keyobj, *dataobj;
3650
3651 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3652 return NULL;
3653
Gregory P. Smith7441e652003-11-03 21:35:31 +00003654 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003655 CHECK_CURSOR_NOT_CLOSED(self);
3656
3657 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3658 self->mydb->moduleFlags.cursorSetReturnsNone);
3659}
3660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661
3662static PyObject*
3663DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3664{
3665 int err, irecno, flags=0;
3666 db_recno_t recno;
3667 DBT key, data;
3668 PyObject* retval;
3669 int dlen = -1;
3670 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003671 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3674 &irecno, &flags, &dlen, &doff))
3675 return NULL;
3676
3677 CHECK_CURSOR_NOT_CLOSED(self);
3678
3679 CLEAR_DBT(key);
3680 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003681 /* use allocated space so DB will be able to realloc room for the real
3682 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683 key.data = malloc(sizeof(db_recno_t));
3684 if (key.data == NULL) {
3685 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3686 return NULL;
3687 }
3688 key.size = sizeof(db_recno_t);
3689 key.ulen = key.size;
3690 memcpy(key.data, &recno, sizeof(db_recno_t));
3691 key.flags = DB_DBT_REALLOC;
3692
3693 CLEAR_DBT(data);
3694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3696 data.flags = DB_DBT_MALLOC;
3697 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003698 if (!add_partial_dbt(&data, dlen, doff)) {
3699 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003700 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003701 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702
3703 MYDB_BEGIN_ALLOW_THREADS;
3704 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3705 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3707 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003708 Py_INCREF(Py_None);
3709 retval = Py_None;
3710 }
3711 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 retval = NULL;
3713 }
3714 else { /* Can only be used for BTrees, so no need to return int key */
3715 retval = Py_BuildValue("s#s#", key.data, key.size,
3716 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717 FREE_DBT(data);
3718 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003719 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003720
3721 return retval;
3722}
3723
3724
3725static PyObject*
3726DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3727{
3728 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3729}
3730
3731
3732static PyObject*
3733DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3734{
3735 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3736}
3737
3738
3739static PyObject*
3740DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3741{
3742 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3743}
3744
3745
3746static PyObject*
3747DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3748{
3749 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3750}
3751
3752
3753static PyObject*
3754DBC_join_item(DBCursorObject* self, PyObject* args)
3755{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003756 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757 DBT key, data;
3758 PyObject* retval;
3759
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003760 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003761 return NULL;
3762
3763 CHECK_CURSOR_NOT_CLOSED(self);
3764
3765 CLEAR_DBT(key);
3766 CLEAR_DBT(data);
3767 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3768 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3769 key.flags = DB_DBT_MALLOC;
3770 }
3771
3772 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003773 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003774 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003775 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3776 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003777 Py_INCREF(Py_None);
3778 retval = Py_None;
3779 }
3780 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003781 retval = NULL;
3782 }
3783 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003784 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003785 FREE_DBT(key);
3786 }
3787
3788 return retval;
3789}
3790
3791
3792
3793/* --------------------------------------------------------------------- */
3794/* DBEnv methods */
3795
3796
3797static PyObject*
3798DBEnv_close(DBEnvObject* self, PyObject* args)
3799{
3800 int err, flags = 0;
3801
3802 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3803 return NULL;
3804 if (!self->closed) { /* Don't close more than once */
3805 MYDB_BEGIN_ALLOW_THREADS;
3806 err = self->db_env->close(self->db_env, flags);
3807 MYDB_END_ALLOW_THREADS;
3808 /* after calling DBEnv->close, regardless of error, this DBEnv
3809 * may not be accessed again (BerkeleyDB docs). */
3810 self->closed = 1;
3811 self->db_env = NULL;
3812 RETURN_IF_ERR();
3813 }
3814 RETURN_NONE();
3815}
3816
3817
3818static PyObject*
3819DBEnv_open(DBEnvObject* self, PyObject* args)
3820{
3821 int err, flags=0, mode=0660;
3822 char *db_home;
3823
3824 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3825 return NULL;
3826
3827 CHECK_ENV_NOT_CLOSED(self);
3828
3829 MYDB_BEGIN_ALLOW_THREADS;
3830 err = self->db_env->open(self->db_env, db_home, flags, mode);
3831 MYDB_END_ALLOW_THREADS;
3832 RETURN_IF_ERR();
3833 self->closed = 0;
3834 self->flags = flags;
3835 RETURN_NONE();
3836}
3837
3838
3839static PyObject*
3840DBEnv_remove(DBEnvObject* self, PyObject* args)
3841{
3842 int err, flags=0;
3843 char *db_home;
3844
3845 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3846 return NULL;
3847 CHECK_ENV_NOT_CLOSED(self);
3848 MYDB_BEGIN_ALLOW_THREADS;
3849 err = self->db_env->remove(self->db_env, db_home, flags);
3850 MYDB_END_ALLOW_THREADS;
3851 RETURN_IF_ERR();
3852 RETURN_NONE();
3853}
3854
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003855#if (DBVER >= 41)
3856static PyObject*
3857DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3858{
3859 int err;
3860 u_int32_t flags=0;
3861 char *file = NULL;
3862 char *database = NULL;
3863 PyObject *txnobj = NULL;
3864 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003865 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003866 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003867
3868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3869 &file, &database, &txnobj, &flags)) {
3870 return NULL;
3871 }
3872 if (!checkTxnObj(txnobj, &txn)) {
3873 return NULL;
3874 }
3875 CHECK_ENV_NOT_CLOSED(self);
3876 MYDB_BEGIN_ALLOW_THREADS;
3877 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3878 MYDB_END_ALLOW_THREADS;
3879 RETURN_IF_ERR();
3880 RETURN_NONE();
3881}
3882
3883static PyObject*
3884DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3885{
3886 int err;
3887 u_int32_t flags=0;
3888 char *file = NULL;
3889 char *database = NULL;
3890 char *newname = NULL;
3891 PyObject *txnobj = NULL;
3892 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003893 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003894 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003895
3896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3897 &file, &database, &newname, &txnobj, &flags)) {
3898 return NULL;
3899 }
3900 if (!checkTxnObj(txnobj, &txn)) {
3901 return NULL;
3902 }
3903 CHECK_ENV_NOT_CLOSED(self);
3904 MYDB_BEGIN_ALLOW_THREADS;
3905 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3906 flags);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3910}
3911
3912static PyObject*
3913DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3914{
3915 int err;
3916 u_int32_t flags=0;
3917 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003918 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003919
3920 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3921 &passwd, &flags)) {
3922 return NULL;
3923 }
3924
3925 MYDB_BEGIN_ALLOW_THREADS;
3926 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3927 MYDB_END_ALLOW_THREADS;
3928
3929 RETURN_IF_ERR();
3930 RETURN_NONE();
3931}
3932#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003933
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003934#if (DBVER >= 40)
3935static PyObject*
3936DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3937{
3938 int err;
3939 u_int32_t flags=0;
3940 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003941 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003942
3943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3944 &timeout, &flags)) {
3945 return NULL;
3946 }
3947
3948 MYDB_BEGIN_ALLOW_THREADS;
3949 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3950 MYDB_END_ALLOW_THREADS;
3951
3952 RETURN_IF_ERR();
3953 RETURN_NONE();
3954}
3955#endif /* DBVER >= 40 */
3956
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003957static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003958DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3959{
3960 int err;
3961 long shm_key = 0;
3962
3963 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3964 return NULL;
3965 CHECK_ENV_NOT_CLOSED(self);
3966
3967 err = self->db_env->set_shm_key(self->db_env, shm_key);
3968 RETURN_IF_ERR();
3969 RETURN_NONE();
3970}
3971
3972static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003973DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3974{
3975 int err, gbytes=0, bytes=0, ncache=0;
3976
3977 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3978 &gbytes, &bytes, &ncache))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3981
3982 MYDB_BEGIN_ALLOW_THREADS;
3983 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3984 MYDB_END_ALLOW_THREADS;
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988
3989
3990#if (DBVER >= 32)
3991static PyObject*
3992DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3993{
3994 int err, flags=0, onoff=0;
3995
3996 if (!PyArg_ParseTuple(args, "ii:set_flags",
3997 &flags, &onoff))
3998 return NULL;
3999 CHECK_ENV_NOT_CLOSED(self);
4000
4001 MYDB_BEGIN_ALLOW_THREADS;
4002 err = self->db_env->set_flags(self->db_env, flags, onoff);
4003 MYDB_END_ALLOW_THREADS;
4004 RETURN_IF_ERR();
4005 RETURN_NONE();
4006}
4007#endif
4008
4009
4010static PyObject*
4011DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4012{
4013 int err;
4014 char *dir;
4015
4016 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4017 return NULL;
4018 CHECK_ENV_NOT_CLOSED(self);
4019
4020 MYDB_BEGIN_ALLOW_THREADS;
4021 err = self->db_env->set_data_dir(self->db_env, dir);
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
4026
4027
4028static PyObject*
4029DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4030{
4031 int err, lg_bsize;
4032
4033 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045static PyObject*
4046DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4047{
4048 int err;
4049 char *dir;
4050
4051 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4052 return NULL;
4053 CHECK_ENV_NOT_CLOSED(self);
4054
4055 MYDB_BEGIN_ALLOW_THREADS;
4056 err = self->db_env->set_lg_dir(self->db_env, dir);
4057 MYDB_END_ALLOW_THREADS;
4058 RETURN_IF_ERR();
4059 RETURN_NONE();
4060}
4061
4062static PyObject*
4063DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4064{
4065 int err, lg_max;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_max(self->db_env, lg_max);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
Neal Norwitz84562352005-10-20 04:30:15 +00004079#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004080static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004081DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4082{
4083 int err, lg_max;
4084
4085 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4086 return NULL;
4087 CHECK_ENV_NOT_CLOSED(self);
4088
4089 MYDB_BEGIN_ALLOW_THREADS;
4090 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4091 MYDB_END_ALLOW_THREADS;
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
Neal Norwitz84562352005-10-20 04:30:15 +00004095#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004096
4097
4098static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004099DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4100{
4101 int err, lk_detect;
4102
4103 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4104 return NULL;
4105 CHECK_ENV_NOT_CLOSED(self);
4106
4107 MYDB_BEGIN_ALLOW_THREADS;
4108 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4109 MYDB_END_ALLOW_THREADS;
4110 RETURN_IF_ERR();
4111 RETURN_NONE();
4112}
4113
4114
4115static PyObject*
4116DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4117{
4118 int err, max;
4119
4120 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_lk_max(self->db_env, max);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
4130
4131
4132#if (DBVER >= 32)
4133
4134static PyObject*
4135DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4136{
4137 int err, max;
4138
4139 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4142
4143 MYDB_BEGIN_ALLOW_THREADS;
4144 err = self->db_env->set_lk_max_locks(self->db_env, max);
4145 MYDB_END_ALLOW_THREADS;
4146 RETURN_IF_ERR();
4147 RETURN_NONE();
4148}
4149
4150
4151static PyObject*
4152DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4153{
4154 int err, max;
4155
4156 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4157 return NULL;
4158 CHECK_ENV_NOT_CLOSED(self);
4159
4160 MYDB_BEGIN_ALLOW_THREADS;
4161 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4162 MYDB_END_ALLOW_THREADS;
4163 RETURN_IF_ERR();
4164 RETURN_NONE();
4165}
4166
4167
4168static PyObject*
4169DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4170{
4171 int err, max;
4172
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_objects(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184#endif
4185
4186
4187static PyObject*
4188DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4189{
4190 int err, mp_mmapsize;
4191
4192 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4193 return NULL;
4194 CHECK_ENV_NOT_CLOSED(self);
4195
4196 MYDB_BEGIN_ALLOW_THREADS;
4197 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4198 MYDB_END_ALLOW_THREADS;
4199 RETURN_IF_ERR();
4200 RETURN_NONE();
4201}
4202
4203
4204static PyObject*
4205DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4206{
4207 int err;
4208 char *dir;
4209
4210 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4211 return NULL;
4212 CHECK_ENV_NOT_CLOSED(self);
4213
4214 MYDB_BEGIN_ALLOW_THREADS;
4215 err = self->db_env->set_tmp_dir(self->db_env, dir);
4216 MYDB_END_ALLOW_THREADS;
4217 RETURN_IF_ERR();
4218 RETURN_NONE();
4219}
4220
4221
4222static PyObject*
4223DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4224{
4225 int flags = 0;
4226 PyObject* txnobj = NULL;
4227 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004228 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004229
4230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4231 &txnobj, &flags))
4232 return NULL;
4233
4234 if (!checkTxnObj(txnobj, &txn))
4235 return NULL;
4236 CHECK_ENV_NOT_CLOSED(self);
4237
4238 return (PyObject*)newDBTxnObject(self, txn, flags);
4239}
4240
4241
4242static PyObject*
4243DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4244{
4245 int err, kbyte=0, min=0, flags=0;
4246
4247 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4248 return NULL;
4249 CHECK_ENV_NOT_CLOSED(self);
4250
4251 MYDB_BEGIN_ALLOW_THREADS;
4252#if (DBVER >= 40)
4253 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4254#else
4255 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4256#endif
4257 MYDB_END_ALLOW_THREADS;
4258 RETURN_IF_ERR();
4259 RETURN_NONE();
4260}
4261
4262
4263static PyObject*
4264DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4265{
4266 int err, max;
4267
4268 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4269 return NULL;
4270 CHECK_ENV_NOT_CLOSED(self);
4271
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004272 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004273 RETURN_IF_ERR();
4274 RETURN_NONE();
4275}
4276
4277
4278static PyObject*
4279DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4280{
4281 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004282 long stamp;
4283 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004284
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004285 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004288 timestamp = (time_t)stamp;
4289 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004290 RETURN_IF_ERR();
4291 RETURN_NONE();
4292}
4293
4294
4295static PyObject*
4296DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4297{
4298 int err, atype, flags=0;
4299 int aborted = 0;
4300
4301 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4302 return NULL;
4303 CHECK_ENV_NOT_CLOSED(self);
4304
4305 MYDB_BEGIN_ALLOW_THREADS;
4306#if (DBVER >= 40)
4307 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4308#else
4309 err = lock_detect(self->db_env, flags, atype, &aborted);
4310#endif
4311 MYDB_END_ALLOW_THREADS;
4312 RETURN_IF_ERR();
4313 return PyInt_FromLong(aborted);
4314}
4315
4316
4317static PyObject*
4318DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4319{
4320 int flags=0;
4321 int locker, lock_mode;
4322 DBT obj;
4323 PyObject* objobj;
4324
4325 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4326 return NULL;
4327
4328
4329 if (!make_dbt(objobj, &obj))
4330 return NULL;
4331
4332 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4333}
4334
4335
4336static PyObject*
4337DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4338{
4339 int err;
4340 u_int32_t theID;
4341
4342 if (!PyArg_ParseTuple(args, ":lock_id"))
4343 return NULL;
4344
4345 CHECK_ENV_NOT_CLOSED(self);
4346 MYDB_BEGIN_ALLOW_THREADS;
4347#if (DBVER >= 40)
4348 err = self->db_env->lock_id(self->db_env, &theID);
4349#else
4350 err = lock_id(self->db_env, &theID);
4351#endif
4352 MYDB_END_ALLOW_THREADS;
4353 RETURN_IF_ERR();
4354
4355 return PyInt_FromLong((long)theID);
4356}
4357
4358
4359static PyObject*
4360DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4361{
4362 int err;
4363 DBLockObject* dblockobj;
4364
4365 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4366 return NULL;
4367
4368 CHECK_ENV_NOT_CLOSED(self);
4369 MYDB_BEGIN_ALLOW_THREADS;
4370#if (DBVER >= 40)
4371 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4372#else
4373 err = lock_put(self->db_env, &dblockobj->lock);
4374#endif
4375 MYDB_END_ALLOW_THREADS;
4376 RETURN_IF_ERR();
4377 RETURN_NONE();
4378}
4379
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004380#if (DBVER >= 44)
4381static PyObject*
4382DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4383{
4384 int err;
4385 char *file;
4386 u_int32_t flags = 0;
4387 static char* kwnames[] = { "file", "flags", NULL};
4388
4389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4390 &file, &flags))
4391 return NULL;
4392 CHECK_ENV_NOT_CLOSED(self);
4393
4394 MYDB_BEGIN_ALLOW_THREADS;
4395 err = self->db_env->lsn_reset(self->db_env, file, flags);
4396 MYDB_END_ALLOW_THREADS;
4397 RETURN_IF_ERR();
4398 RETURN_NONE();
4399}
4400#endif /* DBVER >= 4.4 */
4401
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004402#if (DBVER >= 40)
4403static PyObject*
4404DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4405{
4406 int err;
4407 DB_LOG_STAT* statp = NULL;
4408 PyObject* d = NULL;
4409 u_int32_t flags = 0;
4410
4411 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4412 return NULL;
4413 CHECK_ENV_NOT_CLOSED(self);
4414
4415 MYDB_BEGIN_ALLOW_THREADS;
4416 err = self->db_env->log_stat(self->db_env, &statp, flags);
4417 MYDB_END_ALLOW_THREADS;
4418 RETURN_IF_ERR();
4419
4420 /* Turn the stat structure into a dictionary */
4421 d = PyDict_New();
4422 if (d == NULL) {
4423 if (statp)
4424 free(statp);
4425 return NULL;
4426 }
4427
4428#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4429
4430 MAKE_ENTRY(magic);
4431 MAKE_ENTRY(version);
4432 MAKE_ENTRY(mode);
4433 MAKE_ENTRY(lg_bsize);
4434#if (DBVER >= 44)
4435 MAKE_ENTRY(lg_size);
4436 MAKE_ENTRY(record);
4437#endif
4438#if (DBVER <= 40)
4439 MAKE_ENTRY(lg_max);
4440#endif
4441 MAKE_ENTRY(w_mbytes);
4442 MAKE_ENTRY(w_bytes);
4443 MAKE_ENTRY(wc_mbytes);
4444 MAKE_ENTRY(wc_bytes);
4445 MAKE_ENTRY(wcount);
4446 MAKE_ENTRY(wcount_fill);
4447#if (DBVER >= 44)
4448 MAKE_ENTRY(rcount);
4449#endif
4450 MAKE_ENTRY(scount);
4451 MAKE_ENTRY(cur_file);
4452 MAKE_ENTRY(cur_offset);
4453 MAKE_ENTRY(disk_file);
4454 MAKE_ENTRY(disk_offset);
4455 MAKE_ENTRY(maxcommitperflush);
4456 MAKE_ENTRY(mincommitperflush);
4457 MAKE_ENTRY(regsize);
4458 MAKE_ENTRY(region_wait);
4459 MAKE_ENTRY(region_nowait);
4460
4461#undef MAKE_ENTRY
4462 free(statp);
4463 return d;
4464} /* DBEnv_log_stat */
4465#endif /* DBVER >= 4.0 for log_stat method */
4466
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004467
4468static PyObject*
4469DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4470{
4471 int err;
4472 DB_LOCK_STAT* sp;
4473 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004474 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004475
4476 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4477 return NULL;
4478 CHECK_ENV_NOT_CLOSED(self);
4479
4480 MYDB_BEGIN_ALLOW_THREADS;
4481#if (DBVER >= 40)
4482 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4483#else
4484#if (DBVER >= 33)
4485 err = lock_stat(self->db_env, &sp);
4486#else
4487 err = lock_stat(self->db_env, &sp, NULL);
4488#endif
4489#endif
4490 MYDB_END_ALLOW_THREADS;
4491 RETURN_IF_ERR();
4492
4493 /* Turn the stat structure into a dictionary */
4494 d = PyDict_New();
4495 if (d == NULL) {
4496 free(sp);
4497 return NULL;
4498 }
4499
4500#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4501
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004502#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004503 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004504#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004505 MAKE_ENTRY(nmodes);
4506#if (DBVER >= 32)
4507 MAKE_ENTRY(maxlocks);
4508 MAKE_ENTRY(maxlockers);
4509 MAKE_ENTRY(maxobjects);
4510 MAKE_ENTRY(nlocks);
4511 MAKE_ENTRY(maxnlocks);
4512#endif
4513 MAKE_ENTRY(nlockers);
4514 MAKE_ENTRY(maxnlockers);
4515#if (DBVER >= 32)
4516 MAKE_ENTRY(nobjects);
4517 MAKE_ENTRY(maxnobjects);
4518#endif
4519 MAKE_ENTRY(nrequests);
4520 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004521#if (DBVER < 44)
4522 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004523 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004524#else
4525 MAKE_ENTRY(lock_nowait);
4526 MAKE_ENTRY(lock_wait);
4527#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004528 MAKE_ENTRY(ndeadlocks);
4529 MAKE_ENTRY(regsize);
4530 MAKE_ENTRY(region_wait);
4531 MAKE_ENTRY(region_nowait);
4532
4533#undef MAKE_ENTRY
4534 free(sp);
4535 return d;
4536}
4537
4538
4539static PyObject*
4540DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4541{
4542 int flags=0;
4543 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004544 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 PyObject* list;
4546 PyObject* item = NULL;
4547
4548 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4549 return NULL;
4550
4551 CHECK_ENV_NOT_CLOSED(self);
4552 MYDB_BEGIN_ALLOW_THREADS;
4553#if (DBVER >= 40)
4554 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4555#elif (DBVER == 33)
4556 err = log_archive(self->db_env, &log_list, flags);
4557#else
4558 err = log_archive(self->db_env, &log_list, flags, NULL);
4559#endif
4560 MYDB_END_ALLOW_THREADS;
4561 RETURN_IF_ERR();
4562
Gregory P. Smithbad47452006-06-05 00:33:35 +00004563 list = PyList_New(0);
4564 if (list == NULL) {
4565 if (log_list)
4566 free(log_list);
4567 return NULL;
4568 }
4569
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004570 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004571 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004572 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4573 item = PyString_FromString (*log_list);
4574 if (item == NULL) {
4575 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576 list = NULL;
4577 break;
4578 }
4579 PyList_Append(list, item);
4580 Py_DECREF(item);
4581 }
4582 free(log_list_start);
4583 }
4584 return list;
4585}
4586
4587
4588static PyObject*
4589DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4590{
4591 int err;
4592 DB_TXN_STAT* sp;
4593 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004594 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004595
4596 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4597 return NULL;
4598 CHECK_ENV_NOT_CLOSED(self);
4599
4600 MYDB_BEGIN_ALLOW_THREADS;
4601#if (DBVER >= 40)
4602 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4603#elif (DBVER == 33)
4604 err = txn_stat(self->db_env, &sp);
4605#else
4606 err = txn_stat(self->db_env, &sp, NULL);
4607#endif
4608 MYDB_END_ALLOW_THREADS;
4609 RETURN_IF_ERR();
4610
4611 /* Turn the stat structure into a dictionary */
4612 d = PyDict_New();
4613 if (d == NULL) {
4614 free(sp);
4615 return NULL;
4616 }
4617
4618#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4619
4620 MAKE_ENTRY(time_ckp);
4621 MAKE_ENTRY(last_txnid);
4622 MAKE_ENTRY(maxtxns);
4623 MAKE_ENTRY(nactive);
4624 MAKE_ENTRY(maxnactive);
4625 MAKE_ENTRY(nbegins);
4626 MAKE_ENTRY(naborts);
4627 MAKE_ENTRY(ncommits);
4628 MAKE_ENTRY(regsize);
4629 MAKE_ENTRY(region_wait);
4630 MAKE_ENTRY(region_nowait);
4631
4632#undef MAKE_ENTRY
4633 free(sp);
4634 return d;
4635}
4636
4637
4638static PyObject*
4639DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4640{
4641 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004642 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004643
4644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4645 return NULL;
4646 CHECK_ENV_NOT_CLOSED(self);
4647
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004648 if (self->moduleFlags.getReturnsNone)
4649 ++oldValue;
4650 if (self->moduleFlags.cursorSetReturnsNone)
4651 ++oldValue;
4652 self->moduleFlags.getReturnsNone = (flags >= 1);
4653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004654 return PyInt_FromLong(oldValue);
4655}
4656
4657
4658/* --------------------------------------------------------------------- */
4659/* DBTxn methods */
4660
4661
4662static PyObject*
4663DBTxn_commit(DBTxnObject* self, PyObject* args)
4664{
4665 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004666 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004667
4668 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4669 return NULL;
4670
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004671 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004672 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4673 "after txn_commit or txn_abort");
4674 PyErr_SetObject(DBError, t);
4675 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004676 return NULL;
4677 }
4678 txn = self->txn;
4679 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680 MYDB_BEGIN_ALLOW_THREADS;
4681#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004682 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004685#endif
4686 MYDB_END_ALLOW_THREADS;
4687 RETURN_IF_ERR();
4688 RETURN_NONE();
4689}
4690
4691static PyObject*
4692DBTxn_prepare(DBTxnObject* self, PyObject* args)
4693{
4694#if (DBVER >= 33)
4695 int err;
4696 char* gid=NULL;
4697 int gid_size=0;
4698
4699 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4700 return NULL;
4701
4702 if (gid_size != DB_XIDDATASIZE) {
4703 PyErr_SetString(PyExc_TypeError,
4704 "gid must be DB_XIDDATASIZE bytes long");
4705 return NULL;
4706 }
4707
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004708 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004709 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4710 "after txn_commit or txn_abort");
4711 PyErr_SetObject(DBError, t);
4712 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004713 return NULL;
4714 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004715 MYDB_BEGIN_ALLOW_THREADS;
4716#if (DBVER >= 40)
4717 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4718#else
4719 err = txn_prepare(self->txn, (u_int8_t*)gid);
4720#endif
4721 MYDB_END_ALLOW_THREADS;
4722 RETURN_IF_ERR();
4723 RETURN_NONE();
4724#else
4725 int err;
4726
4727 if (!PyArg_ParseTuple(args, ":prepare"))
4728 return NULL;
4729
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004730 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004731 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4732 "after txn_commit or txn_abort");
4733 PyErr_SetObject(DBError, t);
4734 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004735 return NULL;
4736 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004737 MYDB_BEGIN_ALLOW_THREADS;
4738 err = txn_prepare(self->txn);
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4742#endif
4743}
4744
4745
4746static PyObject*
4747DBTxn_abort(DBTxnObject* self, PyObject* args)
4748{
4749 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004750 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004751
4752 if (!PyArg_ParseTuple(args, ":abort"))
4753 return NULL;
4754
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004755 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004756 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4757 "after txn_commit or txn_abort");
4758 PyErr_SetObject(DBError, t);
4759 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004760 return NULL;
4761 }
4762 txn = self->txn;
4763 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004764 MYDB_BEGIN_ALLOW_THREADS;
4765#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004766 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004767#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769#endif
4770 MYDB_END_ALLOW_THREADS;
4771 RETURN_IF_ERR();
4772 RETURN_NONE();
4773}
4774
4775
4776static PyObject*
4777DBTxn_id(DBTxnObject* self, PyObject* args)
4778{
4779 int id;
4780
4781 if (!PyArg_ParseTuple(args, ":id"))
4782 return NULL;
4783
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004784 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004785 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4786 "after txn_commit or txn_abort");
4787 PyErr_SetObject(DBError, t);
4788 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004789 return NULL;
4790 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791 MYDB_BEGIN_ALLOW_THREADS;
4792#if (DBVER >= 40)
4793 id = self->txn->id(self->txn);
4794#else
4795 id = txn_id(self->txn);
4796#endif
4797 MYDB_END_ALLOW_THREADS;
4798 return PyInt_FromLong(id);
4799}
4800
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004801#if (DBVER >= 43)
4802/* --------------------------------------------------------------------- */
4803/* DBSequence methods */
4804
4805
4806static PyObject*
4807DBSequence_close(DBSequenceObject* self, PyObject* args)
4808{
4809 int err, flags=0;
4810 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4811 return NULL;
4812 CHECK_SEQUENCE_NOT_CLOSED(self)
4813
4814 MYDB_BEGIN_ALLOW_THREADS
4815 err = self->sequence->close(self->sequence, flags);
4816 self->sequence = NULL;
4817 MYDB_END_ALLOW_THREADS
4818
4819 RETURN_IF_ERR();
4820
4821 RETURN_NONE();
4822}
4823
4824static PyObject*
4825DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4826{
4827 int err, flags = 0;
4828 int delta = 1;
4829 db_seq_t value;
4830 PyObject *txnobj = NULL;
4831 DB_TXN *txn = NULL;
4832 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4834 return NULL;
4835 CHECK_SEQUENCE_NOT_CLOSED(self)
4836
4837 if (!checkTxnObj(txnobj, &txn))
4838 return NULL;
4839
4840 MYDB_BEGIN_ALLOW_THREADS
4841 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4842 MYDB_END_ALLOW_THREADS
4843
4844 RETURN_IF_ERR();
4845 return PyLong_FromLongLong(value);
4846
4847}
4848
4849static PyObject*
4850DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4851{
4852 if (!PyArg_ParseTuple(args,":get_dbp"))
4853 return NULL;
4854 CHECK_SEQUENCE_NOT_CLOSED(self)
4855 Py_INCREF(self->mydb);
4856 return (PyObject* )self->mydb;
4857}
4858
4859static PyObject*
4860DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4861{
4862 int err;
4863 DBT key;
4864 CHECK_SEQUENCE_NOT_CLOSED(self)
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err = self->sequence->get_key(self->sequence, &key);
4867 MYDB_END_ALLOW_THREADS
4868
4869 RETURN_IF_ERR();
4870
4871 return PyString_FromStringAndSize(key.data, key.size);
4872}
4873
4874static PyObject*
4875DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4876{
4877 int err;
4878 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004879 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004880 return NULL;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882
4883 MYDB_BEGIN_ALLOW_THREADS
4884 err = self->sequence->initial_value(self->sequence, value);
4885 MYDB_END_ALLOW_THREADS
4886
4887 RETURN_IF_ERR();
4888
4889 RETURN_NONE();
4890}
4891
4892static PyObject*
4893DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4894{
4895 int err, flags = 0;
4896 PyObject* keyobj;
4897 PyObject *txnobj = NULL;
4898 DB_TXN *txn = NULL;
4899 DBT key;
4900
4901 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004903 return NULL;
4904
4905 if (!checkTxnObj(txnobj, &txn))
4906 return NULL;
4907
4908 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4909 return NULL;
4910
4911 MYDB_BEGIN_ALLOW_THREADS
4912 err = self->sequence->open(self->sequence, txn, &key, flags);
4913 MYDB_END_ALLOW_THREADS
4914
4915 CLEAR_DBT(key);
4916 RETURN_IF_ERR();
4917
4918 RETURN_NONE();
4919}
4920
4921static PyObject*
4922DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4923{
4924 int err, flags = 0;
4925 PyObject *txnobj = NULL;
4926 DB_TXN *txn = NULL;
4927
4928 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004930 return NULL;
4931
4932 if (!checkTxnObj(txnobj, &txn))
4933 return NULL;
4934
4935 CHECK_SEQUENCE_NOT_CLOSED(self)
4936
4937 MYDB_BEGIN_ALLOW_THREADS
4938 err = self->sequence->remove(self->sequence, txn, flags);
4939 MYDB_END_ALLOW_THREADS
4940
4941 RETURN_IF_ERR();
4942 RETURN_NONE();
4943}
4944
4945static PyObject*
4946DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4947{
4948 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004949 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004950 return NULL;
4951 CHECK_SEQUENCE_NOT_CLOSED(self)
4952
4953 MYDB_BEGIN_ALLOW_THREADS
4954 err = self->sequence->set_cachesize(self->sequence, size);
4955 MYDB_END_ALLOW_THREADS
4956
4957 RETURN_IF_ERR();
4958 RETURN_NONE();
4959}
4960
4961static PyObject*
4962DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4963{
4964 int err, size;
4965 if (!PyArg_ParseTuple(args,":get_cachesize"))
4966 return NULL;
4967 CHECK_SEQUENCE_NOT_CLOSED(self)
4968
4969 MYDB_BEGIN_ALLOW_THREADS
4970 err = self->sequence->get_cachesize(self->sequence, &size);
4971 MYDB_END_ALLOW_THREADS
4972
4973 RETURN_IF_ERR();
4974 return PyInt_FromLong(size);
4975}
4976
4977static PyObject*
4978DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4979{
4980 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004981 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004982 return NULL;
4983 CHECK_SEQUENCE_NOT_CLOSED(self)
4984
4985 MYDB_BEGIN_ALLOW_THREADS
4986 err = self->sequence->set_flags(self->sequence, flags);
4987 MYDB_END_ALLOW_THREADS
4988
4989 RETURN_IF_ERR();
4990 RETURN_NONE();
4991
4992}
4993
4994static PyObject*
4995DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4996{
4997 unsigned int flags;
4998 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004999 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005000 return NULL;
5001 CHECK_SEQUENCE_NOT_CLOSED(self)
5002
5003 MYDB_BEGIN_ALLOW_THREADS
5004 err = self->sequence->get_flags(self->sequence, &flags);
5005 MYDB_END_ALLOW_THREADS
5006
5007 RETURN_IF_ERR();
5008 return PyInt_FromLong((int)flags);
5009}
5010
5011static PyObject*
5012DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5013{
5014 int err;
5015 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005016 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5019
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->set_range(self->sequence, min, max);
5022 MYDB_END_ALLOW_THREADS
5023
5024 RETURN_IF_ERR();
5025 RETURN_NONE();
5026}
5027
5028static PyObject*
5029DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5030{
5031 int err;
5032 db_seq_t min, max;
5033 if (!PyArg_ParseTuple(args,":get_range"))
5034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5036
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->get_range(self->sequence, &min, &max);
5039 MYDB_END_ALLOW_THREADS
5040
5041 RETURN_IF_ERR();
5042 return Py_BuildValue("(LL)", min, max);
5043}
5044
5045static PyObject*
5046DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5047{
5048 int err, flags = 0;
5049 DB_SEQUENCE_STAT* sp = NULL;
5050 PyObject* dict_stat;
5051 static char* kwnames[] = {"flags", NULL };
5052 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5053 return NULL;
5054 CHECK_SEQUENCE_NOT_CLOSED(self);
5055
5056 MYDB_BEGIN_ALLOW_THREADS;
5057 err = self->sequence->stat(self->sequence, &sp, flags);
5058 MYDB_END_ALLOW_THREADS;
5059 RETURN_IF_ERR();
5060
5061 if ((dict_stat = PyDict_New()) == NULL) {
5062 free(sp);
5063 return NULL;
5064 }
5065
5066
5067#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5068#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5069
5070 MAKE_INT_ENTRY(wait);
5071 MAKE_INT_ENTRY(nowait);
5072 MAKE_LONG_LONG_ENTRY(current);
5073 MAKE_LONG_LONG_ENTRY(value);
5074 MAKE_LONG_LONG_ENTRY(last_value);
5075 MAKE_LONG_LONG_ENTRY(min);
5076 MAKE_LONG_LONG_ENTRY(max);
5077 MAKE_INT_ENTRY(cache_size);
5078 MAKE_INT_ENTRY(flags);
5079
5080#undef MAKE_INT_ENTRY
5081#undef MAKE_LONG_LONG_ENTRY
5082
5083 free(sp);
5084 return dict_stat;
5085}
5086#endif
5087
5088
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005089/* --------------------------------------------------------------------- */
5090/* Method definition tables and type objects */
5091
5092static PyMethodDef DB_methods[] = {
5093 {"append", (PyCFunction)DB_append, METH_VARARGS},
5094#if (DBVER >= 33)
5095 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5096#endif
5097 {"close", (PyCFunction)DB_close, METH_VARARGS},
5098#if (DBVER >= 32)
5099 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5100 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5101#endif
5102 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5103 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5104 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5105 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005106#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005107 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005108#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005109 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5110 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5111 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5112 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5113 {"join", (PyCFunction)DB_join, METH_VARARGS},
5114 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5115 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5116 {"items", (PyCFunction)DB_items, METH_VARARGS},
5117 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5118 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5119 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5120 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5121 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5122 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005123#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005124 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005127#if (DBVER >= 41)
5128 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5129#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005130 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5131 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5132 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5133 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5134 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5135 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5136 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5137 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5138 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5139#if (DBVER >= 32)
5140 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5141#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005142 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005143 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5144#if (DBVER >= 33)
5145 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5146#endif
5147 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5148 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5149 {"values", (PyCFunction)DB_values, METH_VARARGS},
5150 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5151 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5152 {NULL, NULL} /* sentinel */
5153};
5154
5155
5156static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005157 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 (binaryfunc)DB_subscript, /*mp_subscript*/
5159 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5160};
5161
5162
5163static PyMethodDef DBCursor_methods[] = {
5164 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5165 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5166 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5167 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5168 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5169 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5170 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005171#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005172 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005173#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005174 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5175 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5176 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5177 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5178 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5179 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5180 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5181 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005182 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005183 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005184 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5185 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5186 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5187 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5188 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5189 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5190 {NULL, NULL} /* sentinel */
5191};
5192
5193
5194static PyMethodDef DBEnv_methods[] = {
5195 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5196 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5197 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005198#if (DBVER >= 41)
5199 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5200 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5201 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5202#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005203#if (DBVER >= 40)
5204 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5205#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005206 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005207 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5208 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5209#if (DBVER >= 32)
5210 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5211#endif
5212 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5213 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5214 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005215#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005216 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005217#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5219 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5220#if (DBVER >= 32)
5221 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5222 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5223 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5224#endif
5225 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5226 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5227 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5228 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5229 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5230 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005231 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005232 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5233 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5234 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5235 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5236 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5237 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005238#if (DBVER >= 40)
5239 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5240#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005241#if (DBVER >= 44)
5242 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5243#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005244 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5245 {NULL, NULL} /* sentinel */
5246};
5247
5248
5249static PyMethodDef DBTxn_methods[] = {
5250 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5251 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5252 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5253 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5254 {NULL, NULL} /* sentinel */
5255};
5256
5257
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005258#if (DBVER >= 43)
5259static PyMethodDef DBSequence_methods[] = {
5260 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5261 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5262 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5263 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005264 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5265 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5266 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5267 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5268 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5269 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5270 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5271 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5272 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5273 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5274 {NULL, NULL} /* sentinel */
5275};
5276#endif
5277
5278
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005279static PyObject*
5280DB_getattr(DBObject* self, char *name)
5281{
5282 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5283}
5284
5285
5286static PyObject*
5287DBEnv_getattr(DBEnvObject* self, char *name)
5288{
5289 if (!strcmp(name, "db_home")) {
5290 CHECK_ENV_NOT_CLOSED(self);
5291 if (self->db_env->db_home == NULL) {
5292 RETURN_NONE();
5293 }
5294 return PyString_FromString(self->db_env->db_home);
5295 }
5296
5297 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5298}
5299
5300
5301static PyObject*
5302DBCursor_getattr(DBCursorObject* self, char *name)
5303{
5304 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5305}
5306
5307static PyObject*
5308DBTxn_getattr(DBTxnObject* self, char *name)
5309{
5310 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5311}
5312
5313static PyObject*
5314DBLock_getattr(DBLockObject* self, char *name)
5315{
5316 return NULL;
5317}
5318
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005319#if (DBVER >= 43)
5320static PyObject*
5321DBSequence_getattr(DBSequenceObject* self, char *name)
5322{
5323 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5324}
5325#endif
5326
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005327statichere PyTypeObject DB_Type = {
5328 PyObject_HEAD_INIT(NULL)
5329 0, /*ob_size*/
5330 "DB", /*tp_name*/
5331 sizeof(DBObject), /*tp_basicsize*/
5332 0, /*tp_itemsize*/
5333 /* methods */
5334 (destructor)DB_dealloc, /*tp_dealloc*/
5335 0, /*tp_print*/
5336 (getattrfunc)DB_getattr, /*tp_getattr*/
5337 0, /*tp_setattr*/
5338 0, /*tp_compare*/
5339 0, /*tp_repr*/
5340 0, /*tp_as_number*/
5341 0, /*tp_as_sequence*/
5342 &DB_mapping,/*tp_as_mapping*/
5343 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005344#ifdef HAVE_WEAKREF
5345 0, /* tp_call */
5346 0, /* tp_str */
5347 0, /* tp_getattro */
5348 0, /* tp_setattro */
5349 0, /* tp_as_buffer */
5350 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5351 0, /* tp_doc */
5352 0, /* tp_traverse */
5353 0, /* tp_clear */
5354 0, /* tp_richcompare */
5355 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5356#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005357};
5358
5359
5360statichere PyTypeObject DBCursor_Type = {
5361 PyObject_HEAD_INIT(NULL)
5362 0, /*ob_size*/
5363 "DBCursor", /*tp_name*/
5364 sizeof(DBCursorObject), /*tp_basicsize*/
5365 0, /*tp_itemsize*/
5366 /* methods */
5367 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5368 0, /*tp_print*/
5369 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5370 0, /*tp_setattr*/
5371 0, /*tp_compare*/
5372 0, /*tp_repr*/
5373 0, /*tp_as_number*/
5374 0, /*tp_as_sequence*/
5375 0, /*tp_as_mapping*/
5376 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005377#ifdef HAVE_WEAKREF
5378 0, /* tp_call */
5379 0, /* tp_str */
5380 0, /* tp_getattro */
5381 0, /* tp_setattro */
5382 0, /* tp_as_buffer */
5383 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5384 0, /* tp_doc */
5385 0, /* tp_traverse */
5386 0, /* tp_clear */
5387 0, /* tp_richcompare */
5388 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5389#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005390};
5391
5392
5393statichere PyTypeObject DBEnv_Type = {
5394 PyObject_HEAD_INIT(NULL)
5395 0, /*ob_size*/
5396 "DBEnv", /*tp_name*/
5397 sizeof(DBEnvObject), /*tp_basicsize*/
5398 0, /*tp_itemsize*/
5399 /* methods */
5400 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5401 0, /*tp_print*/
5402 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5403 0, /*tp_setattr*/
5404 0, /*tp_compare*/
5405 0, /*tp_repr*/
5406 0, /*tp_as_number*/
5407 0, /*tp_as_sequence*/
5408 0, /*tp_as_mapping*/
5409 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005410#ifdef HAVE_WEAKREF
5411 0, /* tp_call */
5412 0, /* tp_str */
5413 0, /* tp_getattro */
5414 0, /* tp_setattro */
5415 0, /* tp_as_buffer */
5416 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5417 0, /* tp_doc */
5418 0, /* tp_traverse */
5419 0, /* tp_clear */
5420 0, /* tp_richcompare */
5421 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5422#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005423};
5424
5425statichere PyTypeObject DBTxn_Type = {
5426 PyObject_HEAD_INIT(NULL)
5427 0, /*ob_size*/
5428 "DBTxn", /*tp_name*/
5429 sizeof(DBTxnObject), /*tp_basicsize*/
5430 0, /*tp_itemsize*/
5431 /* methods */
5432 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5433 0, /*tp_print*/
5434 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5435 0, /*tp_setattr*/
5436 0, /*tp_compare*/
5437 0, /*tp_repr*/
5438 0, /*tp_as_number*/
5439 0, /*tp_as_sequence*/
5440 0, /*tp_as_mapping*/
5441 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005442#ifdef HAVE_WEAKREF
5443 0, /* tp_call */
5444 0, /* tp_str */
5445 0, /* tp_getattro */
5446 0, /* tp_setattro */
5447 0, /* tp_as_buffer */
5448 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5449 0, /* tp_doc */
5450 0, /* tp_traverse */
5451 0, /* tp_clear */
5452 0, /* tp_richcompare */
5453 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5454#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005455};
5456
5457
5458statichere PyTypeObject DBLock_Type = {
5459 PyObject_HEAD_INIT(NULL)
5460 0, /*ob_size*/
5461 "DBLock", /*tp_name*/
5462 sizeof(DBLockObject), /*tp_basicsize*/
5463 0, /*tp_itemsize*/
5464 /* methods */
5465 (destructor)DBLock_dealloc, /*tp_dealloc*/
5466 0, /*tp_print*/
5467 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5468 0, /*tp_setattr*/
5469 0, /*tp_compare*/
5470 0, /*tp_repr*/
5471 0, /*tp_as_number*/
5472 0, /*tp_as_sequence*/
5473 0, /*tp_as_mapping*/
5474 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005475#ifdef HAVE_WEAKREF
5476 0, /* tp_call */
5477 0, /* tp_str */
5478 0, /* tp_getattro */
5479 0, /* tp_setattro */
5480 0, /* tp_as_buffer */
5481 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5482 0, /* tp_doc */
5483 0, /* tp_traverse */
5484 0, /* tp_clear */
5485 0, /* tp_richcompare */
5486 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5487#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005488};
5489
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005490#if (DBVER >= 43)
5491statichere PyTypeObject DBSequence_Type = {
5492 PyObject_HEAD_INIT(NULL)
5493 0, /*ob_size*/
5494 "DBSequence", /*tp_name*/
5495 sizeof(DBSequenceObject), /*tp_basicsize*/
5496 0, /*tp_itemsize*/
5497 /* methods */
5498 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5499 0, /*tp_print*/
5500 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5501 0, /*tp_setattr*/
5502 0, /*tp_compare*/
5503 0, /*tp_repr*/
5504 0, /*tp_as_number*/
5505 0, /*tp_as_sequence*/
5506 0, /*tp_as_mapping*/
5507 0, /*tp_hash*/
5508#ifdef HAVE_WEAKREF
5509 0, /* tp_call */
5510 0, /* tp_str */
5511 0, /* tp_getattro */
5512 0, /* tp_setattro */
5513 0, /* tp_as_buffer */
5514 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5515 0, /* tp_doc */
5516 0, /* tp_traverse */
5517 0, /* tp_clear */
5518 0, /* tp_richcompare */
5519 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5520#endif
5521};
5522#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005523
5524/* --------------------------------------------------------------------- */
5525/* Module-level functions */
5526
5527static PyObject*
5528DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5529{
5530 PyObject* dbenvobj = NULL;
5531 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005532 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005533
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005534 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5535 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536 return NULL;
5537 if (dbenvobj == Py_None)
5538 dbenvobj = NULL;
5539 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5540 makeTypeError("DBEnv", dbenvobj);
5541 return NULL;
5542 }
5543
5544 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5545}
5546
5547
5548static PyObject*
5549DBEnv_construct(PyObject* self, PyObject* args)
5550{
5551 int flags = 0;
5552 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5553 return (PyObject* )newDBEnvObject(flags);
5554}
5555
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005556#if (DBVER >= 43)
5557static PyObject*
5558DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5559{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005560 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005561 int flags = 0;
5562 static char* kwnames[] = { "db", "flags", NULL};
5563
5564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5565 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005566 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005567 makeTypeError("DB", dbobj);
5568 return NULL;
5569 }
5570 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5571}
5572#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005573
5574static char bsddb_version_doc[] =
5575"Returns a tuple of major, minor, and patch release numbers of the\n\
5576underlying DB library.";
5577
5578static PyObject*
5579bsddb_version(PyObject* self, PyObject* args)
5580{
5581 int major, minor, patch;
5582
5583 if (!PyArg_ParseTuple(args, ":version"))
5584 return NULL;
5585 db_version(&major, &minor, &patch);
5586 return Py_BuildValue("(iii)", major, minor, patch);
5587}
5588
5589
5590/* List of functions defined in the module */
5591
5592static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005593 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5594 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5595#if (DBVER >= 43)
5596 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5597#endif
5598 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005599 {NULL, NULL} /* sentinel */
5600};
5601
5602
5603/* --------------------------------------------------------------------- */
5604/* Module initialization */
5605
5606
5607/* Convenience routine to export an integer value.
5608 * Errors are silently ignored, for better or for worse...
5609 */
5610#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5611
Gregory P. Smith41631e82003-09-21 00:08:14 +00005612#define MODULE_NAME_MAX_LEN 11
5613static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005614
5615DL_EXPORT(void) init_bsddb(void)
5616{
5617 PyObject* m;
5618 PyObject* d;
5619 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5620 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5621 PyObject* cvsid_s = PyString_FromString( rcs_id );
5622
5623 /* Initialize the type of the new type objects here; doing it here
5624 is required for portability to Windows without requiring C++. */
5625 DB_Type.ob_type = &PyType_Type;
5626 DBCursor_Type.ob_type = &PyType_Type;
5627 DBEnv_Type.ob_type = &PyType_Type;
5628 DBTxn_Type.ob_type = &PyType_Type;
5629 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005630#if (DBVER >= 43)
5631 DBSequence_Type.ob_type = &PyType_Type;
5632#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633
5634
Mark Hammonda69d4092003-04-22 23:13:27 +00005635#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005636 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005637 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638#endif
5639
5640 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005641 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005642 if (m == NULL)
5643 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644
5645 /* Add some symbolic constants to the module */
5646 d = PyModule_GetDict(m);
5647 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5648 PyDict_SetItemString(d, "cvsid", cvsid_s);
5649 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5650 Py_DECREF(pybsddb_version_s);
5651 pybsddb_version_s = NULL;
5652 Py_DECREF(cvsid_s);
5653 cvsid_s = NULL;
5654 Py_DECREF(db_version_s);
5655 db_version_s = NULL;
5656
5657 ADD_INT(d, DB_VERSION_MAJOR);
5658 ADD_INT(d, DB_VERSION_MINOR);
5659 ADD_INT(d, DB_VERSION_PATCH);
5660
5661 ADD_INT(d, DB_MAX_PAGES);
5662 ADD_INT(d, DB_MAX_RECORDS);
5663
Gregory P. Smith41631e82003-09-21 00:08:14 +00005664#if (DBVER >= 42)
5665 ADD_INT(d, DB_RPCCLIENT);
5666#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005667 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005668 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5669 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5670#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005671 ADD_INT(d, DB_XA_CREATE);
5672
5673 ADD_INT(d, DB_CREATE);
5674 ADD_INT(d, DB_NOMMAP);
5675 ADD_INT(d, DB_THREAD);
5676
5677 ADD_INT(d, DB_FORCE);
5678 ADD_INT(d, DB_INIT_CDB);
5679 ADD_INT(d, DB_INIT_LOCK);
5680 ADD_INT(d, DB_INIT_LOG);
5681 ADD_INT(d, DB_INIT_MPOOL);
5682 ADD_INT(d, DB_INIT_TXN);
5683#if (DBVER >= 32)
5684 ADD_INT(d, DB_JOINENV);
5685#endif
5686
5687 ADD_INT(d, DB_RECOVER);
5688 ADD_INT(d, DB_RECOVER_FATAL);
5689 ADD_INT(d, DB_TXN_NOSYNC);
5690 ADD_INT(d, DB_USE_ENVIRON);
5691 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5692
5693 ADD_INT(d, DB_LOCKDOWN);
5694 ADD_INT(d, DB_PRIVATE);
5695 ADD_INT(d, DB_SYSTEM_MEM);
5696
5697 ADD_INT(d, DB_TXN_SYNC);
5698 ADD_INT(d, DB_TXN_NOWAIT);
5699
5700 ADD_INT(d, DB_EXCL);
5701 ADD_INT(d, DB_FCNTL_LOCKING);
5702 ADD_INT(d, DB_ODDFILESIZE);
5703 ADD_INT(d, DB_RDWRMASTER);
5704 ADD_INT(d, DB_RDONLY);
5705 ADD_INT(d, DB_TRUNCATE);
5706#if (DBVER >= 32)
5707 ADD_INT(d, DB_EXTENT);
5708 ADD_INT(d, DB_CDB_ALLDB);
5709 ADD_INT(d, DB_VERIFY);
5710#endif
5711 ADD_INT(d, DB_UPGRADE);
5712
5713 ADD_INT(d, DB_AGGRESSIVE);
5714 ADD_INT(d, DB_NOORDERCHK);
5715 ADD_INT(d, DB_ORDERCHKONLY);
5716 ADD_INT(d, DB_PR_PAGE);
5717#if ! (DBVER >= 33)
5718 ADD_INT(d, DB_VRFY_FLAGMASK);
5719 ADD_INT(d, DB_PR_HEADERS);
5720#endif
5721 ADD_INT(d, DB_PR_RECOVERYTEST);
5722 ADD_INT(d, DB_SALVAGE);
5723
5724 ADD_INT(d, DB_LOCK_NORUN);
5725 ADD_INT(d, DB_LOCK_DEFAULT);
5726 ADD_INT(d, DB_LOCK_OLDEST);
5727 ADD_INT(d, DB_LOCK_RANDOM);
5728 ADD_INT(d, DB_LOCK_YOUNGEST);
5729#if (DBVER >= 33)
5730 ADD_INT(d, DB_LOCK_MAXLOCKS);
5731 ADD_INT(d, DB_LOCK_MINLOCKS);
5732 ADD_INT(d, DB_LOCK_MINWRITE);
5733#endif
5734
5735
5736#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005737 /* docs say to use zero instead */
5738 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005739#else
5740 ADD_INT(d, DB_LOCK_CONFLICT);
5741#endif
5742
5743 ADD_INT(d, DB_LOCK_DUMP);
5744 ADD_INT(d, DB_LOCK_GET);
5745 ADD_INT(d, DB_LOCK_INHERIT);
5746 ADD_INT(d, DB_LOCK_PUT);
5747 ADD_INT(d, DB_LOCK_PUT_ALL);
5748 ADD_INT(d, DB_LOCK_PUT_OBJ);
5749
5750 ADD_INT(d, DB_LOCK_NG);
5751 ADD_INT(d, DB_LOCK_READ);
5752 ADD_INT(d, DB_LOCK_WRITE);
5753 ADD_INT(d, DB_LOCK_NOWAIT);
5754#if (DBVER >= 32)
5755 ADD_INT(d, DB_LOCK_WAIT);
5756#endif
5757 ADD_INT(d, DB_LOCK_IWRITE);
5758 ADD_INT(d, DB_LOCK_IREAD);
5759 ADD_INT(d, DB_LOCK_IWR);
5760#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005761#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005762 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005763#else
5764 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5765#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005766 ADD_INT(d, DB_LOCK_WWRITE);
5767#endif
5768
5769 ADD_INT(d, DB_LOCK_RECORD);
5770 ADD_INT(d, DB_LOCK_UPGRADE);
5771#if (DBVER >= 32)
5772 ADD_INT(d, DB_LOCK_SWITCH);
5773#endif
5774#if (DBVER >= 33)
5775 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5776#endif
5777
5778 ADD_INT(d, DB_LOCK_NOWAIT);
5779 ADD_INT(d, DB_LOCK_RECORD);
5780 ADD_INT(d, DB_LOCK_UPGRADE);
5781
5782#if (DBVER >= 33)
5783 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005784#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005786#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787 ADD_INT(d, DB_LSTAT_FREE);
5788 ADD_INT(d, DB_LSTAT_HELD);
5789#if (DBVER == 33)
5790 ADD_INT(d, DB_LSTAT_NOGRANT);
5791#endif
5792 ADD_INT(d, DB_LSTAT_PENDING);
5793 ADD_INT(d, DB_LSTAT_WAITING);
5794#endif
5795
5796 ADD_INT(d, DB_ARCH_ABS);
5797 ADD_INT(d, DB_ARCH_DATA);
5798 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005799#if (DBVER >= 42)
5800 ADD_INT(d, DB_ARCH_REMOVE);
5801#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802
5803 ADD_INT(d, DB_BTREE);
5804 ADD_INT(d, DB_HASH);
5805 ADD_INT(d, DB_RECNO);
5806 ADD_INT(d, DB_QUEUE);
5807 ADD_INT(d, DB_UNKNOWN);
5808
5809 ADD_INT(d, DB_DUP);
5810 ADD_INT(d, DB_DUPSORT);
5811 ADD_INT(d, DB_RECNUM);
5812 ADD_INT(d, DB_RENUMBER);
5813 ADD_INT(d, DB_REVSPLITOFF);
5814 ADD_INT(d, DB_SNAPSHOT);
5815
5816 ADD_INT(d, DB_JOIN_NOSORT);
5817
5818 ADD_INT(d, DB_AFTER);
5819 ADD_INT(d, DB_APPEND);
5820 ADD_INT(d, DB_BEFORE);
5821 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005822#if (DBVER >= 41)
5823 _addIntToDict(d, "DB_CHECKPOINT", 0);
5824#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005826 ADD_INT(d, DB_CURLSN);
5827#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005828#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_COMMIT);
5830#endif
5831 ADD_INT(d, DB_CONSUME);
5832#if (DBVER >= 32)
5833 ADD_INT(d, DB_CONSUME_WAIT);
5834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005835 ADD_INT(d, DB_CURRENT);
5836#if (DBVER >= 33)
5837 ADD_INT(d, DB_FAST_STAT);
5838#endif
5839 ADD_INT(d, DB_FIRST);
5840 ADD_INT(d, DB_FLUSH);
5841 ADD_INT(d, DB_GET_BOTH);
5842 ADD_INT(d, DB_GET_RECNO);
5843 ADD_INT(d, DB_JOIN_ITEM);
5844 ADD_INT(d, DB_KEYFIRST);
5845 ADD_INT(d, DB_KEYLAST);
5846 ADD_INT(d, DB_LAST);
5847 ADD_INT(d, DB_NEXT);
5848 ADD_INT(d, DB_NEXT_DUP);
5849 ADD_INT(d, DB_NEXT_NODUP);
5850 ADD_INT(d, DB_NODUPDATA);
5851 ADD_INT(d, DB_NOOVERWRITE);
5852 ADD_INT(d, DB_NOSYNC);
5853 ADD_INT(d, DB_POSITION);
5854 ADD_INT(d, DB_PREV);
5855 ADD_INT(d, DB_PREV_NODUP);
5856 ADD_INT(d, DB_RECORDCOUNT);
5857 ADD_INT(d, DB_SET);
5858 ADD_INT(d, DB_SET_RANGE);
5859 ADD_INT(d, DB_SET_RECNO);
5860 ADD_INT(d, DB_WRITECURSOR);
5861
5862 ADD_INT(d, DB_OPFLAGS_MASK);
5863 ADD_INT(d, DB_RMW);
5864#if (DBVER >= 33)
5865 ADD_INT(d, DB_DIRTY_READ);
5866 ADD_INT(d, DB_MULTIPLE);
5867 ADD_INT(d, DB_MULTIPLE_KEY);
5868#endif
5869
Gregory P. Smith29602d22006-01-24 09:46:48 +00005870#if (DBVER >= 44)
5871 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5872 ADD_INT(d, DB_READ_COMMITTED);
5873#endif
5874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875#if (DBVER >= 33)
5876 ADD_INT(d, DB_DONOTINDEX);
5877#endif
5878
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005879#if (DBVER >= 41)
5880 _addIntToDict(d, "DB_INCOMPLETE", 0);
5881#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005882 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005883#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005884 ADD_INT(d, DB_KEYEMPTY);
5885 ADD_INT(d, DB_KEYEXIST);
5886 ADD_INT(d, DB_LOCK_DEADLOCK);
5887 ADD_INT(d, DB_LOCK_NOTGRANTED);
5888 ADD_INT(d, DB_NOSERVER);
5889 ADD_INT(d, DB_NOSERVER_HOME);
5890 ADD_INT(d, DB_NOSERVER_ID);
5891 ADD_INT(d, DB_NOTFOUND);
5892 ADD_INT(d, DB_OLD_VERSION);
5893 ADD_INT(d, DB_RUNRECOVERY);
5894 ADD_INT(d, DB_VERIFY_BAD);
5895#if (DBVER >= 33)
5896 ADD_INT(d, DB_PAGE_NOTFOUND);
5897 ADD_INT(d, DB_SECONDARY_BAD);
5898#endif
5899#if (DBVER >= 40)
5900 ADD_INT(d, DB_STAT_CLEAR);
5901 ADD_INT(d, DB_REGION_INIT);
5902 ADD_INT(d, DB_NOLOCKING);
5903 ADD_INT(d, DB_YIELDCPU);
5904 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5905 ADD_INT(d, DB_NOPANIC);
5906#endif
5907
Gregory P. Smith41631e82003-09-21 00:08:14 +00005908#if (DBVER >= 42)
5909 ADD_INT(d, DB_TIME_NOTGRANTED);
5910 ADD_INT(d, DB_TXN_NOT_DURABLE);
5911 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5912 ADD_INT(d, DB_LOG_AUTOREMOVE);
5913 ADD_INT(d, DB_DIRECT_LOG);
5914 ADD_INT(d, DB_DIRECT_DB);
5915 ADD_INT(d, DB_INIT_REP);
5916 ADD_INT(d, DB_ENCRYPT);
5917 ADD_INT(d, DB_CHKSUM);
5918#endif
5919
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005920#if (DBVER >= 43)
5921 ADD_INT(d, DB_LOG_INMEMORY);
5922 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005923 ADD_INT(d, DB_SEQ_DEC);
5924 ADD_INT(d, DB_SEQ_INC);
5925 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005926#endif
5927
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005928#if (DBVER >= 41)
5929 ADD_INT(d, DB_ENCRYPT_AES);
5930 ADD_INT(d, DB_AUTO_COMMIT);
5931#else
5932 /* allow berkeleydb 4.1 aware apps to run on older versions */
5933 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5934#endif
5935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005936 ADD_INT(d, EINVAL);
5937 ADD_INT(d, EACCES);
5938 ADD_INT(d, ENOSPC);
5939 ADD_INT(d, ENOMEM);
5940 ADD_INT(d, EAGAIN);
5941 ADD_INT(d, EBUSY);
5942 ADD_INT(d, EEXIST);
5943 ADD_INT(d, ENOENT);
5944 ADD_INT(d, EPERM);
5945
Barry Warsaw1baa9822003-03-31 19:51:29 +00005946#if (DBVER >= 40)
5947 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5948 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5949#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005950
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005951 /* The exception name must be correct for pickled exception *
5952 * objects to unpickle properly. */
5953#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5954#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5955#else
5956#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5957#endif
5958
5959 /* All the rest of the exceptions derive only from DBError */
5960#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5961 PyDict_SetItemString(d, #name, name)
5962
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005963 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005964 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5965 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005966
Gregory P. Smithe9477062005-06-04 06:46:59 +00005967 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5968 * from both DBError and KeyError, since the API only supports
5969 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005970 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005971 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5972 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005973 Py_file_input, d, d);
5974 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005975 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005976 PyDict_DelItemString(d, "KeyError");
5977
5978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005979#if !INCOMPLETE_IS_WARNING
5980 MAKE_EX(DBIncompleteError);
5981#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005982 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005983 MAKE_EX(DBKeyEmptyError);
5984 MAKE_EX(DBKeyExistError);
5985 MAKE_EX(DBLockDeadlockError);
5986 MAKE_EX(DBLockNotGrantedError);
5987 MAKE_EX(DBOldVersionError);
5988 MAKE_EX(DBRunRecoveryError);
5989 MAKE_EX(DBVerifyBadError);
5990 MAKE_EX(DBNoServerError);
5991 MAKE_EX(DBNoServerHomeError);
5992 MAKE_EX(DBNoServerIDError);
5993#if (DBVER >= 33)
5994 MAKE_EX(DBPageNotFoundError);
5995 MAKE_EX(DBSecondaryBadError);
5996#endif
5997
5998 MAKE_EX(DBInvalidArgError);
5999 MAKE_EX(DBAccessError);
6000 MAKE_EX(DBNoSpaceError);
6001 MAKE_EX(DBNoMemoryError);
6002 MAKE_EX(DBAgainError);
6003 MAKE_EX(DBBusyError);
6004 MAKE_EX(DBFileExistsError);
6005 MAKE_EX(DBNoSuchFileError);
6006 MAKE_EX(DBPermissionsError);
6007
6008#undef MAKE_EX
6009
6010 /* Check for errors */
6011 if (PyErr_Occurred()) {
6012 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006013 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 }
6015}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006016
6017/* allow this module to be named _pybsddb so that it can be installed
6018 * and imported on top of python >= 2.3 that includes its own older
6019 * copy of the library named _bsddb without importing the old version. */
6020DL_EXPORT(void) init_pybsddb(void)
6021{
6022 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6023 init_bsddb();
6024}