blob: e00a64c172bee5623c0cc4ae51f2ee43f63ad8e3 [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 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
Gregory P. Smitha703a212003-11-03 01:04:41 +000087#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000088#include <Python.h>
89#include <db.h>
90
91/* --------------------------------------------------------------------- */
92/* Various macro definitions */
93
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000094/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
95#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000096#if DB_VERSION_MINOR > 9
97#error "eek! DBVER can't handle minor versions > 9"
98#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
Gregory P. Smith589c6ab2004-06-27 23:36:37 +0000100#define PY_BSDDB_VERSION "4.2.7"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000101static char *rcs_id = "$Id$";
102
103
104#ifdef WITH_THREAD
105
106/* These are for when calling Python --> C */
107#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
109
Mark Hammonda69d4092003-04-22 23:13:27 +0000110/* For 2.3, use the PyGILState_ calls */
111#if (PY_VERSION_HEX >= 0x02030000)
112#define MYDB_USE_GILSTATE
113#endif
114
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000115/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000116#if defined(MYDB_USE_GILSTATE)
117#define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119#define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121#else /* MYDB_USE_GILSTATE */
122/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000123static PyInterpreterState* _db_interpreterState = NULL;
124#define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
130
131#define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
136 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000137#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000138
139#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000140/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141#define MYDB_BEGIN_ALLOW_THREADS
142#define MYDB_END_ALLOW_THREADS
143#define MYDB_BEGIN_BLOCK_THREADS
144#define MYDB_END_BLOCK_THREADS
145
146#endif
147
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000148/* Should DB_INCOMPLETE be turned into a warning or an exception? */
149#define INCOMPLETE_IS_WARNING 1
150
151/* --------------------------------------------------------------------- */
152/* Exceptions */
153
154static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000155static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000156static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */
157static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164static PyObject* DBNoServerError; /* DB_NOSERVER */
165static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167#if (DBVER >= 33)
168static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170#endif
171
172#if !INCOMPLETE_IS_WARNING
173static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174#endif
175
176static PyObject* DBInvalidArgError; /* EINVAL */
177static PyObject* DBAccessError; /* EACCES */
178static PyObject* DBNoSpaceError; /* ENOSPC */
179static PyObject* DBNoMemoryError; /* ENOMEM */
180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
186
187
188/* --------------------------------------------------------------------- */
189/* Structure definitions */
190
Gregory P. Smitha703a212003-11-03 01:04:41 +0000191#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
192#define HAVE_WEAKREF
193#else
194#undef HAVE_WEAKREF
195#endif
196
Gregory P. Smith31c50652004-06-28 01:20:40 +0000197/* if Python >= 2.1 better support warnings */
198#if PYTHON_API_VERSION >= 1010
199#define HAVE_WARNINGS
200#else
201#undef HAVE_WARNINGS
202#endif
203
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000204struct behaviourFlags {
205 /* What is the default behaviour when DB->get or DBCursor->get returns a
206 DB_NOTFOUND error? Return None or raise an exception? */
207 unsigned int getReturnsNone : 1;
208 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
209 * returns a DB_NOTFOUND error? Return None or raise an exception? */
210 unsigned int cursorSetReturnsNone : 1;
211};
212
213#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000214#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000216typedef struct {
217 PyObject_HEAD
218 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000219 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000220 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000222#ifdef HAVE_WEAKREF
223 PyObject *in_weakreflist; /* List of weak references */
224#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000225} DBEnvObject;
226
227
228typedef struct {
229 PyObject_HEAD
230 DB* db;
231 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000232 u_int32_t flags; /* saved flags from open() */
233 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000236#if (DBVER >= 33)
237 PyObject* associateCallback;
238 int primaryDBType;
239#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000240#ifdef HAVE_WEAKREF
241 PyObject *in_weakreflist; /* List of weak references */
242#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243} DBObject;
244
245
246typedef struct {
247 PyObject_HEAD
248 DBC* dbc;
249 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000250#ifdef HAVE_WEAKREF
251 PyObject *in_weakreflist; /* List of weak references */
252#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253} DBCursorObject;
254
255
256typedef struct {
257 PyObject_HEAD
258 DB_TXN* txn;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000259#ifdef HAVE_WEAKREF
260 PyObject *in_weakreflist; /* List of weak references */
261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000262} DBTxnObject;
263
264
265typedef struct {
266 PyObject_HEAD
267 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000268#ifdef HAVE_WEAKREF
269 PyObject *in_weakreflist; /* List of weak references */
270#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000271} DBLockObject;
272
273
274
275staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
276
277#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
278#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
279#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
280#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
281#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
282
283
284/* --------------------------------------------------------------------- */
285/* Utility macros and functions */
286
287#define RETURN_IF_ERR() \
288 if (makeDBError(err)) { \
289 return NULL; \
290 }
291
292#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
293
Gregory P. Smithe2767172003-11-02 08:06:29 +0000294#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
295 if ((nonNull) == NULL) { \
296 PyObject *errTuple = NULL; \
297 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
298 PyErr_SetObject((pyErrObj), errTuple); \
299 Py_DECREF(errTuple); \
300 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301 }
302
Gregory P. Smithe2767172003-11-02 08:06:29 +0000303#define CHECK_DB_NOT_CLOSED(dbobj) \
304 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
305
306#define CHECK_ENV_NOT_CLOSED(env) \
307 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000308
309#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000310 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
314 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
315
316#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
317
318#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000319 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000320
321
322static int makeDBError(int err);
323
324
325/* Return the access method type of the DBObject */
326static int _DB_get_type(DBObject* self)
327{
328#if (DBVER >= 33)
329 DBTYPE type;
330 int err;
331 err = self->db->get_type(self->db, &type);
332 if (makeDBError(err)) {
333 return -1;
334 }
335 return type;
336#else
337 return self->db->get_type(self->db);
338#endif
339}
340
341
342/* Create a DBT structure (containing key and data values) from Python
343 strings. Returns 1 on success, 0 on an error. */
344static int make_dbt(PyObject* obj, DBT* dbt)
345{
346 CLEAR_DBT(*dbt);
347 if (obj == Py_None) {
348 /* no need to do anything, the structure has already been zeroed */
349 }
350 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
351 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353 return 0;
354 }
355 return 1;
356}
357
358
359/* Recno and Queue DBs can have integer keys. This function figures out
360 what's been given, verifies that it's allowed, and then makes the DBT.
361
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000362 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000363static int
364make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000365{
366 db_recno_t recno;
367 int type;
368
369 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000370 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000371 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000372 if (type == -1)
373 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000374 if (type == DB_RECNO || type == DB_QUEUE) {
375 PyErr_SetString(
376 PyExc_TypeError,
377 "None keys not allowed for Recno and Queue DB's");
378 return 0;
379 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000380 /* no need to do anything, the structure has already been zeroed */
381 }
382
383 else if (PyString_Check(keyobj)) {
384 /* verify access method type */
385 type = _DB_get_type(self);
386 if (type == -1)
387 return 0;
388 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000389 PyErr_SetString(
390 PyExc_TypeError,
391 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000392 return 0;
393 }
394
395 key->data = PyString_AS_STRING(keyobj);
396 key->size = PyString_GET_SIZE(keyobj);
397 }
398
399 else if (PyInt_Check(keyobj)) {
400 /* verify access method type */
401 type = _DB_get_type(self);
402 if (type == -1)
403 return 0;
404 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000405 /* if BTREE then an Integer key is allowed with the
406 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000407 *pflags |= DB_SET_RECNO;
408 }
409 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000410 PyErr_SetString(
411 PyExc_TypeError,
412 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 return 0;
414 }
415
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000416 /* Make a key out of the requested recno, use allocated space so DB
417 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000418 recno = PyInt_AS_LONG(keyobj);
419 key->data = malloc(sizeof(db_recno_t));
420 if (key->data == NULL) {
421 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
422 return 0;
423 }
424 key->ulen = key->size = sizeof(db_recno_t);
425 memcpy(key->data, &recno, sizeof(db_recno_t));
426 key->flags = DB_DBT_REALLOC;
427 }
428 else {
429 PyErr_Format(PyExc_TypeError,
430 "String or Integer object expected for key, %s found",
431 keyobj->ob_type->tp_name);
432 return 0;
433 }
434
435 return 1;
436}
437
438
439/* Add partial record access to an existing DBT data struct.
440 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
441 and the data storage/retrieval will be done using dlen and doff. */
442static int add_partial_dbt(DBT* d, int dlen, int doff) {
443 /* if neither were set we do nothing (-1 is the default value) */
444 if ((dlen == -1) && (doff == -1)) {
445 return 1;
446 }
447
448 if ((dlen < 0) || (doff < 0)) {
449 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
450 return 0;
451 }
452
453 d->flags = d->flags | DB_DBT_PARTIAL;
454 d->dlen = (unsigned int) dlen;
455 d->doff = (unsigned int) doff;
456 return 1;
457}
458
459
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000460/* Callback used to save away more information about errors from the DB
461 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000462static char _db_errmsg[1024];
463static void _db_errorCallback(const char* prefix, char* msg)
464{
465 strcpy(_db_errmsg, msg);
466}
467
468
469/* make a nice exception object to raise for errors. */
470static int makeDBError(int err)
471{
472 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000473 PyObject *errObj = NULL;
474 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000475 int exceptionRaised = 0;
476
477 switch (err) {
478 case 0: /* successful, no error */ break;
479
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000480#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000481 case DB_INCOMPLETE:
482#if INCOMPLETE_IS_WARNING
483 strcpy(errTxt, db_strerror(err));
484 if (_db_errmsg[0]) {
485 strcat(errTxt, " -- ");
486 strcat(errTxt, _db_errmsg);
487 _db_errmsg[0] = 0;
488 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000489#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000490 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
491#else
492 fprintf(stderr, errTxt);
493 fprintf(stderr, "\n");
494#endif
495
496#else /* do an exception instead */
497 errObj = DBIncompleteError;
498#endif
499 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000500#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000501
502 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
503 case DB_KEYEXIST: errObj = DBKeyExistError; break;
504 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
505 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
506 case DB_NOTFOUND: errObj = DBNotFoundError; break;
507 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
508 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
509 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
510 case DB_NOSERVER: errObj = DBNoServerError; break;
511 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
512 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
513#if (DBVER >= 33)
514 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
515 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
516#endif
517
518 case EINVAL: errObj = DBInvalidArgError; break;
519 case EACCES: errObj = DBAccessError; break;
520 case ENOSPC: errObj = DBNoSpaceError; break;
521 case ENOMEM: errObj = DBNoMemoryError; break;
522 case EAGAIN: errObj = DBAgainError; break;
523 case EBUSY : errObj = DBBusyError; break;
524 case EEXIST: errObj = DBFileExistsError; break;
525 case ENOENT: errObj = DBNoSuchFileError; break;
526 case EPERM : errObj = DBPermissionsError; break;
527
528 default: errObj = DBError; break;
529 }
530
531 if (errObj != NULL) {
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +0000532 /* FIXME this needs proper bounds checking on errTxt */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000533 strcpy(errTxt, db_strerror(err));
534 if (_db_errmsg[0]) {
535 strcat(errTxt, " -- ");
536 strcat(errTxt, _db_errmsg);
537 _db_errmsg[0] = 0;
538 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000539
540 errTuple = Py_BuildValue("(is)", err, errTxt);
541 PyErr_SetObject(errObj, errTuple);
542 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000543 }
544
545 return ((errObj != NULL) || exceptionRaised);
546}
547
548
549
550/* set a type exception */
551static void makeTypeError(char* expected, PyObject* found)
552{
553 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
554 expected, found->ob_type->tp_name);
555}
556
557
558/* verify that an obj is either None or a DBTxn, and set the txn pointer */
559static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
560{
561 if (txnobj == Py_None || txnobj == NULL) {
562 *txn = NULL;
563 return 1;
564 }
565 if (DBTxnObject_Check(txnobj)) {
566 *txn = ((DBTxnObject*)txnobj)->txn;
567 return 1;
568 }
569 else
570 makeTypeError("DBTxn", txnobj);
571 return 0;
572}
573
574
575/* Delete a key from a database
576 Returns 0 on success, -1 on an error. */
577static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
578{
579 int err;
580
581 MYDB_BEGIN_ALLOW_THREADS;
582 err = self->db->del(self->db, txn, key, 0);
583 MYDB_END_ALLOW_THREADS;
584 if (makeDBError(err)) {
585 return -1;
586 }
587 self->haveStat = 0;
588 return 0;
589}
590
591
592/* Store a key into a database
593 Returns 0 on success, -1 on an error. */
594static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
595{
596 int err;
597
598 MYDB_BEGIN_ALLOW_THREADS;
599 err = self->db->put(self->db, txn, key, data, flags);
600 MYDB_END_ALLOW_THREADS;
601 if (makeDBError(err)) {
602 return -1;
603 }
604 self->haveStat = 0;
605 return 0;
606}
607
608/* Get a key/data pair from a cursor */
609static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
610 PyObject *args, PyObject *kwargs, char *format)
611{
612 int err;
613 PyObject* retval = NULL;
614 DBT key, data;
615 int dlen = -1;
616 int doff = -1;
617 int flags = 0;
618 char* kwnames[] = { "flags", "dlen", "doff", NULL };
619
620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
621 &flags, &dlen, &doff))
622 return NULL;
623
624 CHECK_CURSOR_NOT_CLOSED(self);
625
626 flags |= extra_flags;
627 CLEAR_DBT(key);
628 CLEAR_DBT(data);
629 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
630 /* Tell BerkeleyDB to malloc the return value (thread safe) */
631 data.flags = DB_DBT_MALLOC;
632 key.flags = DB_DBT_MALLOC;
633 }
634 if (!add_partial_dbt(&data, dlen, doff))
635 return NULL;
636
637 MYDB_BEGIN_ALLOW_THREADS;
638 err = self->dbc->c_get(self->dbc, &key, &data, flags);
639 MYDB_END_ALLOW_THREADS;
640
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000641 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000642 Py_INCREF(Py_None);
643 retval = Py_None;
644 }
645 else if (makeDBError(err)) {
646 retval = NULL;
647 }
648 else { /* otherwise, success! */
649
650 /* if Recno or Queue, return the key as an Int */
651 switch (_DB_get_type(self->mydb)) {
652 case -1:
653 retval = NULL;
654 break;
655
656 case DB_RECNO:
657 case DB_QUEUE:
658 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
659 data.data, data.size);
660 break;
661 case DB_HASH:
662 case DB_BTREE:
663 default:
664 retval = Py_BuildValue("s#s#", key.data, key.size,
665 data.data, data.size);
666 break;
667 }
668 }
669 if (!err) {
670 FREE_DBT(key);
671 FREE_DBT(data);
672 }
673 return retval;
674}
675
676
677/* add an integer to a dictionary using the given name as a key */
678static void _addIntToDict(PyObject* dict, char *name, int value)
679{
680 PyObject* v = PyInt_FromLong((long) value);
681 if (!v || PyDict_SetItemString(dict, name, v))
682 PyErr_Clear();
683
684 Py_XDECREF(v);
685}
686
687
688
689
690/* --------------------------------------------------------------------- */
691/* Allocators and deallocators */
692
693static DBObject*
694newDBObject(DBEnvObject* arg, int flags)
695{
696 DBObject* self;
697 DB_ENV* db_env = NULL;
698 int err;
699
700#if PYTHON_API_VERSION <= 1007
701 /* 1.5 compatibility */
702 self = PyObject_NEW(DBObject, &DB_Type);
703#else
704 self = PyObject_New(DBObject, &DB_Type);
705#endif
706
707 if (self == NULL)
708 return NULL;
709
710 self->haveStat = 0;
711 self->flags = 0;
712 self->setflags = 0;
713 self->myenvobj = NULL;
714#if (DBVER >= 33)
715 self->associateCallback = NULL;
716 self->primaryDBType = 0;
717#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000718#ifdef HAVE_WEAKREF
719 self->in_weakreflist = NULL;
720#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000721
722 /* keep a reference to our python DBEnv object */
723 if (arg) {
724 Py_INCREF(arg);
725 self->myenvobj = arg;
726 db_env = arg->db_env;
727 }
728
729 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000730 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000731 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000732 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
733 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000734
735 MYDB_BEGIN_ALLOW_THREADS;
736 err = db_create(&self->db, db_env, flags);
737 self->db->set_errcall(self->db, _db_errorCallback);
738#if (DBVER >= 33)
739 self->db->app_private = (void*)self;
740#endif
741 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000742 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
743 * list so that a DBEnv can refuse to close without aborting any open
744 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000745 if (makeDBError(err)) {
746 if (self->myenvobj) {
747 Py_DECREF(self->myenvobj);
748 self->myenvobj = NULL;
749 }
750 self = NULL;
751 }
752 return self;
753}
754
755
756static void
757DB_dealloc(DBObject* self)
758{
759 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000760 /* avoid closing a DB when its DBEnv has been closed out from under
761 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000763 (self->myenvobj && self->myenvobj->db_env))
764 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765 MYDB_BEGIN_ALLOW_THREADS;
766 self->db->close(self->db, 0);
767 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000768#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769 } else {
770 PyErr_Warn(PyExc_RuntimeWarning,
771 "DB could not be closed in destructor: DBEnv already closed");
772#endif
773 }
774 self->db = NULL;
775 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000776#ifdef HAVE_WEAKREF
777 if (self->in_weakreflist != NULL) {
778 PyObject_ClearWeakRefs((PyObject *) self);
779 }
780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781 if (self->myenvobj) {
782 Py_DECREF(self->myenvobj);
783 self->myenvobj = NULL;
784 }
785#if (DBVER >= 33)
786 if (self->associateCallback != NULL) {
787 Py_DECREF(self->associateCallback);
788 self->associateCallback = NULL;
789 }
790#endif
791#if PYTHON_API_VERSION <= 1007
792 PyMem_DEL(self);
793#else
794 PyObject_Del(self);
795#endif
796}
797
798
799static DBCursorObject*
800newDBCursorObject(DBC* dbc, DBObject* db)
801{
802 DBCursorObject* self;
803#if PYTHON_API_VERSION <= 1007
804 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
805#else
806 self = PyObject_New(DBCursorObject, &DBCursor_Type);
807#endif
808 if (self == NULL)
809 return NULL;
810
811 self->dbc = dbc;
812 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000813#ifdef HAVE_WEAKREF
814 self->in_weakreflist = NULL;
815#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816 Py_INCREF(self->mydb);
817 return self;
818}
819
820
821static void
822DBCursor_dealloc(DBCursorObject* self)
823{
824 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000825
826#ifdef HAVE_WEAKREF
827 if (self->in_weakreflist != NULL) {
828 PyObject_ClearWeakRefs((PyObject *) self);
829 }
830#endif
831
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000832 if (self->dbc != NULL) {
833 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000834 /* If the underlying database has been closed, we don't
835 need to do anything. If the environment has been closed
836 we need to leak, as BerkeleyDB will crash trying to access
837 the environment. There was an exception when the
838 user closed the environment even though there still was
839 a database open. */
840 if (self->mydb->db && self->mydb->myenvobj &&
841 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000842 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000843 self->dbc = NULL;
844 MYDB_END_ALLOW_THREADS;
845 }
846 Py_XDECREF( self->mydb );
847#if PYTHON_API_VERSION <= 1007
848 PyMem_DEL(self);
849#else
850 PyObject_Del(self);
851#endif
852}
853
854
855static DBEnvObject*
856newDBEnvObject(int flags)
857{
858 int err;
859 DBEnvObject* self;
860#if PYTHON_API_VERSION <= 1007
861 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
862#else
863 self = PyObject_New(DBEnvObject, &DBEnv_Type);
864#endif
865
866 if (self == NULL)
867 return NULL;
868
869 self->closed = 1;
870 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000871 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
872 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000873#ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876
877 MYDB_BEGIN_ALLOW_THREADS;
878 err = db_env_create(&self->db_env, flags);
879 MYDB_END_ALLOW_THREADS;
880 if (makeDBError(err)) {
881 self = NULL;
882 }
883 else {
884 self->db_env->set_errcall(self->db_env, _db_errorCallback);
885 }
886 return self;
887}
888
889
890static void
891DBEnv_dealloc(DBEnvObject* self)
892{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000893#ifdef HAVE_WEAKREF
894 if (self->in_weakreflist != NULL) {
895 PyObject_ClearWeakRefs((PyObject *) self);
896 }
897#endif
898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899 if (!self->closed) {
900 MYDB_BEGIN_ALLOW_THREADS;
901 self->db_env->close(self->db_env, 0);
902 MYDB_END_ALLOW_THREADS;
903 }
904#if PYTHON_API_VERSION <= 1007
905 PyMem_DEL(self);
906#else
907 PyObject_Del(self);
908#endif
909}
910
911
912static DBTxnObject*
913newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
914{
915 int err;
916 DBTxnObject* self;
917
918#if PYTHON_API_VERSION <= 1007
919 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
920#else
921 self = PyObject_New(DBTxnObject, &DBTxn_Type);
922#endif
923 if (self == NULL)
924 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000925#ifdef HAVE_WEAKREF
926 self->in_weakreflist = NULL;
927#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928
929 MYDB_BEGIN_ALLOW_THREADS;
930#if (DBVER >= 40)
931 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
932#else
933 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
934#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000935 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
936 * list so that a DBEnv can refuse to close without aborting any open
937 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
940 self = NULL;
941 }
942 return self;
943}
944
945
946static void
947DBTxn_dealloc(DBTxnObject* self)
948{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000949#ifdef HAVE_WEAKREF
950 if (self->in_weakreflist != NULL) {
951 PyObject_ClearWeakRefs((PyObject *) self);
952 }
953#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954
Gregory P. Smith31c50652004-06-28 01:20:40 +0000955#ifdef HAVE_WARNINGS
956 if (self->txn) {
957 /* it hasn't been finalized, abort it! */
958 MYDB_BEGIN_ALLOW_THREADS;
959#if (DBVER >= 40)
960 self->txn->abort(self->txn);
961#else
962 txn_abort(self->txn);
963#endif
964 MYDB_END_ALLOW_THREADS;
965 PyErr_Warn(PyExc_RuntimeWarning,
966 "DBTxn aborted in destructor. No prior commit() or abort().");
967 }
968#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969
970#if PYTHON_API_VERSION <= 1007
971 PyMem_DEL(self);
972#else
973 PyObject_Del(self);
974#endif
975}
976
977
978static DBLockObject*
979newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
980 db_lockmode_t lock_mode, int flags)
981{
982 int err;
983 DBLockObject* self;
984
985#if PYTHON_API_VERSION <= 1007
986 self = PyObject_NEW(DBLockObject, &DBLock_Type);
987#else
988 self = PyObject_New(DBLockObject, &DBLock_Type);
989#endif
990 if (self == NULL)
991 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000992#ifdef HAVE_WEAKREF
993 self->in_weakreflist = NULL;
994#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000995
996 MYDB_BEGIN_ALLOW_THREADS;
997#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000998 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
999 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001000#else
1001 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1002#endif
1003 MYDB_END_ALLOW_THREADS;
1004 if (makeDBError(err)) {
1005 self = NULL;
1006 }
1007
1008 return self;
1009}
1010
1011
1012static void
1013DBLock_dealloc(DBLockObject* self)
1014{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001015#ifdef HAVE_WEAKREF
1016 if (self->in_weakreflist != NULL) {
1017 PyObject_ClearWeakRefs((PyObject *) self);
1018 }
1019#endif
1020 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001021
1022#if PYTHON_API_VERSION <= 1007
1023 PyMem_DEL(self);
1024#else
1025 PyObject_Del(self);
1026#endif
1027}
1028
1029
1030/* --------------------------------------------------------------------- */
1031/* DB methods */
1032
1033static PyObject*
1034DB_append(DBObject* self, PyObject* args)
1035{
1036 PyObject* txnobj = NULL;
1037 PyObject* dataobj;
1038 db_recno_t recno;
1039 DBT key, data;
1040 DB_TXN *txn = NULL;
1041
1042 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1043 return NULL;
1044
1045 CHECK_DB_NOT_CLOSED(self);
1046
1047 /* make a dummy key out of a recno */
1048 recno = 0;
1049 CLEAR_DBT(key);
1050 key.data = &recno;
1051 key.size = sizeof(recno);
1052 key.ulen = key.size;
1053 key.flags = DB_DBT_USERMEM;
1054
1055 if (!make_dbt(dataobj, &data)) return NULL;
1056 if (!checkTxnObj(txnobj, &txn)) return NULL;
1057
1058 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1059 return NULL;
1060
1061 return PyInt_FromLong(recno);
1062}
1063
1064
1065#if (DBVER >= 33)
1066
1067static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001068_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1069 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001070{
1071 int retval = DB_DONOTINDEX;
1072 DBObject* secondaryDB = (DBObject*)db->app_private;
1073 PyObject* callback = secondaryDB->associateCallback;
1074 int type = secondaryDB->primaryDBType;
1075 PyObject* key;
1076 PyObject* data;
1077 PyObject* args;
1078 PyObject* result;
1079
1080
1081 if (callback != NULL) {
1082 MYDB_BEGIN_BLOCK_THREADS;
1083
1084 if (type == DB_RECNO || type == DB_QUEUE) {
1085 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1086 }
1087 else {
1088 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1089 }
1090 data = PyString_FromStringAndSize(priData->data, priData->size);
1091 args = PyTuple_New(2);
1092 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1093 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1094
1095 result = PyEval_CallObject(callback, args);
1096
1097 if (result == NULL) {
1098 PyErr_Print();
1099 }
1100 else if (result == Py_None) {
1101 retval = DB_DONOTINDEX;
1102 }
1103 else if (PyInt_Check(result)) {
1104 retval = PyInt_AsLong(result);
1105 }
1106 else if (PyString_Check(result)) {
1107 char* data;
1108 int size;
1109
1110 CLEAR_DBT(*secKey);
1111#if PYTHON_API_VERSION <= 1007
1112 /* 1.5 compatibility */
1113 size = PyString_Size(result);
1114 data = PyString_AsString(result);
1115#else
1116 PyString_AsStringAndSize(result, &data, &size);
1117#endif
1118 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1119 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001120 if (secKey->data) {
1121 memcpy(secKey->data, data, size);
1122 secKey->size = size;
1123 retval = 0;
1124 }
1125 else {
1126 PyErr_SetString(PyExc_MemoryError,
1127 "malloc failed in _db_associateCallback");
1128 PyErr_Print();
1129 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001130 }
1131 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001132 PyErr_SetString(
1133 PyExc_TypeError,
1134 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001135 PyErr_Print();
1136 }
1137
1138 Py_DECREF(args);
1139 if (result) {
1140 Py_DECREF(result);
1141 }
1142
1143 MYDB_END_BLOCK_THREADS;
1144 }
1145 return retval;
1146}
1147
1148
1149static PyObject*
1150DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1151{
1152 int err, flags=0;
1153 DBObject* secondaryDB;
1154 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001155#if (DBVER >= 41)
1156 PyObject *txnobj = NULL;
1157 DB_TXN *txn = NULL;
1158 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1159#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001160 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001161#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001162
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001163#if (DBVER >= 41)
1164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1165 &secondaryDB, &callback, &flags,
1166 &txnobj)) {
1167#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001168 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001169 &secondaryDB, &callback, &flags)) {
1170#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001172 }
1173
1174#if (DBVER >= 41)
1175 if (!checkTxnObj(txnobj, &txn)) return NULL;
1176#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177
1178 CHECK_DB_NOT_CLOSED(self);
1179 if (!DBObject_Check(secondaryDB)) {
1180 makeTypeError("DB", (PyObject*)secondaryDB);
1181 return NULL;
1182 }
1183 if (callback == Py_None) {
1184 callback = NULL;
1185 }
1186 else if (!PyCallable_Check(callback)) {
1187 makeTypeError("Callable", callback);
1188 return NULL;
1189 }
1190
1191 /* Save a reference to the callback in the secondary DB. */
1192 if (self->associateCallback != NULL) {
1193 Py_DECREF(self->associateCallback);
1194 }
1195 Py_INCREF(callback);
1196 secondaryDB->associateCallback = callback;
1197 secondaryDB->primaryDBType = _DB_get_type(self);
1198
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001199 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1200 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1201 * The global interepreter lock is not initialized until the first
1202 * thread is created using thread.start_new_thread() or fork() is
1203 * called. that would cause the ALLOW_THREADS here to segfault due
1204 * to a null pointer reference if no threads or child processes
1205 * have been created. This works around that and is a no-op if
1206 * threads have already been initialized.
1207 * (see pybsddb-users mailing list post on 2002-08-07)
1208 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001209#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001210 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001211#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001212 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001213#if (DBVER >= 41)
1214 err = self->db->associate(self->db,
1215 txn,
1216 secondaryDB->db,
1217 _db_associateCallback,
1218 flags);
1219#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001220 err = self->db->associate(self->db,
1221 secondaryDB->db,
1222 _db_associateCallback,
1223 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001224#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225 MYDB_END_ALLOW_THREADS;
1226
1227 if (err) {
1228 Py_DECREF(self->associateCallback);
1229 self->associateCallback = NULL;
1230 secondaryDB->primaryDBType = 0;
1231 }
1232
1233 RETURN_IF_ERR();
1234 RETURN_NONE();
1235}
1236
1237
1238#endif
1239
1240
1241static PyObject*
1242DB_close(DBObject* self, PyObject* args)
1243{
1244 int err, flags=0;
1245 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1246 return NULL;
1247 if (self->db != NULL) {
1248 if (self->myenvobj)
1249 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251 self->db = NULL;
1252 RETURN_IF_ERR();
1253 }
1254 RETURN_NONE();
1255}
1256
1257
1258#if (DBVER >= 32)
1259static PyObject*
1260_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1261{
1262 int err, flags=0, type;
1263 PyObject* txnobj = NULL;
1264 PyObject* retval = NULL;
1265 DBT key, data;
1266 DB_TXN *txn = NULL;
1267 char* kwnames[] = { "txn", "flags", NULL };
1268
1269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1270 &txnobj, &flags))
1271 return NULL;
1272
1273 CHECK_DB_NOT_CLOSED(self);
1274 type = _DB_get_type(self);
1275 if (type == -1)
1276 return NULL;
1277 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001278 PyErr_SetString(PyExc_TypeError,
1279 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001280 return NULL;
1281 }
1282 if (!checkTxnObj(txnobj, &txn))
1283 return NULL;
1284
1285 CLEAR_DBT(key);
1286 CLEAR_DBT(data);
1287 if (CHECK_DBFLAG(self, DB_THREAD)) {
1288 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1289 data.flags = DB_DBT_MALLOC;
1290 key.flags = DB_DBT_MALLOC;
1291 }
1292
1293 MYDB_BEGIN_ALLOW_THREADS;
1294 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1295 MYDB_END_ALLOW_THREADS;
1296
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001297 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 err = 0;
1299 Py_INCREF(Py_None);
1300 retval = Py_None;
1301 }
1302 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001303 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1304 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305 FREE_DBT(key);
1306 FREE_DBT(data);
1307 }
1308
1309 RETURN_IF_ERR();
1310 return retval;
1311}
1312
1313static PyObject*
1314DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1315{
1316 return _DB_consume(self, args, kwargs, DB_CONSUME);
1317}
1318
1319static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001320DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1321 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001322{
1323 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1324}
1325#endif
1326
1327
1328
1329static PyObject*
1330DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1331{
1332 int err, flags=0;
1333 DBC* dbc;
1334 PyObject* txnobj = NULL;
1335 DB_TXN *txn = NULL;
1336 char* kwnames[] = { "txn", "flags", NULL };
1337
1338 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1339 &txnobj, &flags))
1340 return NULL;
1341 CHECK_DB_NOT_CLOSED(self);
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1344
1345 MYDB_BEGIN_ALLOW_THREADS;
1346 err = self->db->cursor(self->db, txn, &dbc, flags);
1347 MYDB_END_ALLOW_THREADS;
1348 RETURN_IF_ERR();
1349 return (PyObject*) newDBCursorObject(dbc, self);
1350}
1351
1352
1353static PyObject*
1354DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1355{
1356 PyObject* txnobj = NULL;
1357 int flags = 0;
1358 PyObject* keyobj;
1359 DBT key;
1360 DB_TXN *txn = NULL;
1361 char* kwnames[] = { "key", "txn", "flags", NULL };
1362
1363 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1364 &keyobj, &txnobj, &flags))
1365 return NULL;
1366 CHECK_DB_NOT_CLOSED(self);
1367 if (!make_key_dbt(self, keyobj, &key, NULL))
1368 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001369 if (!checkTxnObj(txnobj, &txn)) {
1370 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001372 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001373
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001374 if (-1 == _DB_delete(self, txn, &key, 0)) {
1375 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001376 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001377 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001378
1379 FREE_DBT(key);
1380 RETURN_NONE();
1381}
1382
1383
1384static PyObject*
1385DB_fd(DBObject* self, PyObject* args)
1386{
1387 int err, the_fd;
1388
1389 if (!PyArg_ParseTuple(args,":fd"))
1390 return NULL;
1391 CHECK_DB_NOT_CLOSED(self);
1392
1393 MYDB_BEGIN_ALLOW_THREADS;
1394 err = self->db->fd(self->db, &the_fd);
1395 MYDB_END_ALLOW_THREADS;
1396 RETURN_IF_ERR();
1397 return PyInt_FromLong(the_fd);
1398}
1399
1400
1401static PyObject*
1402DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1403{
1404 int err, flags=0;
1405 PyObject* txnobj = NULL;
1406 PyObject* keyobj;
1407 PyObject* dfltobj = NULL;
1408 PyObject* retval = NULL;
1409 int dlen = -1;
1410 int doff = -1;
1411 DBT key, data;
1412 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001413 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001414
1415 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001416 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1417 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001418 return NULL;
1419
1420 CHECK_DB_NOT_CLOSED(self);
1421 if (!make_key_dbt(self, keyobj, &key, &flags))
1422 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001423 if (!checkTxnObj(txnobj, &txn)) {
1424 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001425 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001426 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 CLEAR_DBT(data);
1429 if (CHECK_DBFLAG(self, DB_THREAD)) {
1430 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1431 data.flags = DB_DBT_MALLOC;
1432 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001433 if (!add_partial_dbt(&data, dlen, doff)) {
1434 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001435 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001436 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437
1438 MYDB_BEGIN_ALLOW_THREADS;
1439 err = self->db->get(self->db, txn, &key, &data, flags);
1440 MYDB_END_ALLOW_THREADS;
1441
1442 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1443 err = 0;
1444 Py_INCREF(dfltobj);
1445 retval = dfltobj;
1446 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001447 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001448 err = 0;
1449 Py_INCREF(Py_None);
1450 retval = Py_None;
1451 }
1452 else if (!err) {
1453 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001454 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1455 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456 else /* return just the data */
1457 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001458 FREE_DBT(data);
1459 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001460 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461
1462 RETURN_IF_ERR();
1463 return retval;
1464}
1465
1466
1467/* Return size of entry */
1468static PyObject*
1469DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1470{
1471 int err, flags=0;
1472 PyObject* txnobj = NULL;
1473 PyObject* keyobj;
1474 PyObject* retval = NULL;
1475 DBT key, data;
1476 DB_TXN *txn = NULL;
1477 char* kwnames[] = { "key", "txn", NULL };
1478
1479 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1480 &keyobj, &txnobj))
1481 return NULL;
1482 CHECK_DB_NOT_CLOSED(self);
1483 if (!make_key_dbt(self, keyobj, &key, &flags))
1484 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001485 if (!checkTxnObj(txnobj, &txn)) {
1486 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001488 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489 CLEAR_DBT(data);
1490
1491 /* We don't allocate any memory, forcing a ENOMEM error and thus
1492 getting the record size. */
1493 data.flags = DB_DBT_USERMEM;
1494 data.ulen = 0;
1495 MYDB_BEGIN_ALLOW_THREADS;
1496 err = self->db->get(self->db, txn, &key, &data, flags);
1497 MYDB_END_ALLOW_THREADS;
1498 if (err == ENOMEM) {
1499 retval = PyInt_FromLong((long)data.size);
1500 err = 0;
1501 }
1502
1503 FREE_DBT(key);
1504 FREE_DBT(data);
1505 RETURN_IF_ERR();
1506 return retval;
1507}
1508
1509
1510static PyObject*
1511DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1512{
1513 int err, flags=0;
1514 PyObject* txnobj = NULL;
1515 PyObject* keyobj;
1516 PyObject* dataobj;
1517 PyObject* retval = NULL;
1518 DBT key, data;
1519 DB_TXN *txn = NULL;
1520 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1521
1522
1523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1524 &keyobj, &dataobj, &txnobj, &flags))
1525 return NULL;
1526
1527 CHECK_DB_NOT_CLOSED(self);
1528 if (!make_key_dbt(self, keyobj, &key, NULL))
1529 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001530 if ( !make_dbt(dataobj, &data) ||
1531 !checkTxnObj(txnobj, &txn) )
1532 {
1533 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001535 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001536
1537 flags |= DB_GET_BOTH;
1538
1539 if (CHECK_DBFLAG(self, DB_THREAD)) {
1540 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1541 data.flags = DB_DBT_MALLOC;
1542 /* TODO: Is this flag needed? We're passing a data object that should
1543 match what's in the DB, so there should be no need to malloc.
1544 We run the risk of freeing something twice! Check this. */
1545 }
1546
1547 MYDB_BEGIN_ALLOW_THREADS;
1548 err = self->db->get(self->db, txn, &key, &data, flags);
1549 MYDB_END_ALLOW_THREADS;
1550
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001551 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001552 err = 0;
1553 Py_INCREF(Py_None);
1554 retval = Py_None;
1555 }
1556 else if (!err) {
1557 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1558 FREE_DBT(data); /* Only if retrieval was successful */
1559 }
1560
1561 FREE_DBT(key);
1562 RETURN_IF_ERR();
1563 return retval;
1564}
1565
1566
1567static PyObject*
1568DB_get_byteswapped(DBObject* self, PyObject* args)
1569{
1570#if (DBVER >= 33)
1571 int err = 0;
1572#endif
1573 int retval = -1;
1574
1575 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1576 return NULL;
1577 CHECK_DB_NOT_CLOSED(self);
1578
1579#if (DBVER >= 33)
1580 MYDB_BEGIN_ALLOW_THREADS;
1581 err = self->db->get_byteswapped(self->db, &retval);
1582 MYDB_END_ALLOW_THREADS;
1583 RETURN_IF_ERR();
1584#else
1585 MYDB_BEGIN_ALLOW_THREADS;
1586 retval = self->db->get_byteswapped(self->db);
1587 MYDB_END_ALLOW_THREADS;
1588#endif
1589 return PyInt_FromLong(retval);
1590}
1591
1592
1593static PyObject*
1594DB_get_type(DBObject* self, PyObject* args)
1595{
1596 int type;
1597
1598 if (!PyArg_ParseTuple(args,":get_type"))
1599 return NULL;
1600 CHECK_DB_NOT_CLOSED(self);
1601
1602 MYDB_BEGIN_ALLOW_THREADS;
1603 type = _DB_get_type(self);
1604 MYDB_END_ALLOW_THREADS;
1605 if (type == -1)
1606 return NULL;
1607 return PyInt_FromLong(type);
1608}
1609
1610
1611static PyObject*
1612DB_join(DBObject* self, PyObject* args)
1613{
1614 int err, flags=0;
1615 int length, x;
1616 PyObject* cursorsObj;
1617 DBC** cursors;
1618 DBC* dbc;
1619
1620
1621 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1622 return NULL;
1623
1624 CHECK_DB_NOT_CLOSED(self);
1625
1626 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001627 PyErr_SetString(PyExc_TypeError,
1628 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001629 return NULL;
1630 }
1631
1632 length = PyObject_Length(cursorsObj);
1633 cursors = malloc((length+1) * sizeof(DBC*));
1634 cursors[length] = NULL;
1635 for (x=0; x<length; x++) {
1636 PyObject* item = PySequence_GetItem(cursorsObj, x);
1637 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001638 PyErr_SetString(PyExc_TypeError,
1639 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 free(cursors);
1641 return NULL;
1642 }
1643 cursors[x] = ((DBCursorObject*)item)->dbc;
1644 }
1645
1646 MYDB_BEGIN_ALLOW_THREADS;
1647 err = self->db->join(self->db, cursors, &dbc, flags);
1648 MYDB_END_ALLOW_THREADS;
1649 free(cursors);
1650 RETURN_IF_ERR();
1651
Gregory P. Smith7441e652003-11-03 21:35:31 +00001652 /* FIXME: this is a buggy interface. The returned cursor
1653 contains internal references to the passed in cursors
1654 but does not hold python references to them or prevent
1655 them from being closed prematurely. This can cause
1656 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 return (PyObject*) newDBCursorObject(dbc, self);
1658}
1659
1660
1661static PyObject*
1662DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1663{
1664 int err, flags=0;
1665 PyObject* txnobj = NULL;
1666 PyObject* keyobj;
1667 DBT key;
1668 DB_TXN *txn = NULL;
1669 DB_KEY_RANGE range;
1670 char* kwnames[] = { "key", "txn", "flags", NULL };
1671
1672 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1673 &keyobj, &txnobj, &flags))
1674 return NULL;
1675 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001676 if (!make_dbt(keyobj, &key))
1677 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 return NULL;
1679 if (!checkTxnObj(txnobj, &txn))
1680 return NULL;
1681
1682 MYDB_BEGIN_ALLOW_THREADS;
1683 err = self->db->key_range(self->db, txn, &key, &range, flags);
1684 MYDB_END_ALLOW_THREADS;
1685
1686 RETURN_IF_ERR();
1687 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1688}
1689
1690
1691static PyObject*
1692DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1693{
1694 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1695 char* filename = NULL;
1696 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001697#if (DBVER >= 41)
1698 PyObject *txnobj = NULL;
1699 DB_TXN *txn = NULL;
1700 /* with dbname */
1701 char* kwnames[] = {
1702 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1703 /* without dbname */
1704 char* kwnames_basic[] = {
1705 "filename", "dbtype", "flags", "mode", "txn", NULL};
1706#else
1707 /* with dbname */
1708 char* kwnames[] = {
1709 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1710 /* without dbname */
1711 char* kwnames_basic[] = {
1712 "filename", "dbtype", "flags", "mode", NULL};
1713#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001715#if (DBVER >= 41)
1716 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1717 &filename, &dbname, &type, &flags, &mode,
1718 &txnobj))
1719#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001720 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001721 &filename, &dbname, &type, &flags,
1722 &mode))
1723#endif
1724 {
1725 PyErr_Clear();
1726 type = DB_UNKNOWN; flags = 0; mode = 0660;
1727 filename = NULL; dbname = NULL;
1728#if (DBVER >= 41)
1729 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1730 kwnames_basic,
1731 &filename, &type, &flags, &mode,
1732 &txnobj))
1733 return NULL;
1734#else
1735 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1736 kwnames_basic,
1737 &filename, &type, &flags, &mode))
1738 return NULL;
1739#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001740 }
1741
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001742#if (DBVER >= 41)
1743 if (!checkTxnObj(txnobj, &txn)) return NULL;
1744#endif
1745
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746 if (NULL == self->db) {
1747 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1748 "Cannot call open() twice for DB object"));
1749 return NULL;
1750 }
1751
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001752#if 0 && (DBVER >= 41)
1753 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1754 && (self->myenvobj->flags & DB_INIT_TXN))
1755 {
1756 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1757 * explicitly passed) but we are in a transaction ready environment:
1758 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1759 * to work on BerkeleyDB 4.1 without needing to modify their
1760 * DBEnv or DB open calls.
1761 * TODO make this behaviour of the library configurable.
1762 */
1763 flags |= DB_AUTO_COMMIT;
1764 }
1765#endif
1766
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001767 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001768#if (DBVER >= 41)
1769 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1770#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001771 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001772#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001773 MYDB_END_ALLOW_THREADS;
1774 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001775 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001776 self->db = NULL;
1777 return NULL;
1778 }
1779
1780 self->flags = flags;
1781 RETURN_NONE();
1782}
1783
1784
1785static PyObject*
1786DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1787{
1788 int flags=0;
1789 PyObject* txnobj = NULL;
1790 int dlen = -1;
1791 int doff = -1;
1792 PyObject* keyobj, *dataobj, *retval;
1793 DBT key, data;
1794 DB_TXN *txn = NULL;
1795 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1796
1797 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1798 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1799 return NULL;
1800
1801 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001802 if (!make_key_dbt(self, keyobj, &key, NULL))
1803 return NULL;
1804 if ( !make_dbt(dataobj, &data) ||
1805 !add_partial_dbt(&data, dlen, doff) ||
1806 !checkTxnObj(txnobj, &txn) )
1807 {
1808 FREE_DBT(key);
1809 return NULL;
1810 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001811
1812 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1813 FREE_DBT(key);
1814 return NULL;
1815 }
1816
1817 if (flags & DB_APPEND)
1818 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1819 else {
1820 retval = Py_None;
1821 Py_INCREF(retval);
1822 }
1823 FREE_DBT(key);
1824 return retval;
1825}
1826
1827
1828
1829static PyObject*
1830DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1831{
1832 char* filename;
1833 char* database = NULL;
1834 int err, flags=0;
1835 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1836
1837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1838 &filename, &database, &flags))
1839 return NULL;
1840 CHECK_DB_NOT_CLOSED(self);
1841
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001843 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 RETURN_IF_ERR();
1845 RETURN_NONE();
1846}
1847
1848
1849
1850static PyObject*
1851DB_rename(DBObject* self, PyObject* args)
1852{
1853 char* filename;
1854 char* database;
1855 char* newname;
1856 int err, flags=0;
1857
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001858 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1859 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860 return NULL;
1861 CHECK_DB_NOT_CLOSED(self);
1862
1863 MYDB_BEGIN_ALLOW_THREADS;
1864 err = self->db->rename(self->db, filename, database, newname, flags);
1865 MYDB_END_ALLOW_THREADS;
1866 RETURN_IF_ERR();
1867 RETURN_NONE();
1868}
1869
1870
1871static PyObject*
1872DB_set_bt_minkey(DBObject* self, PyObject* args)
1873{
1874 int err, minkey;
1875
1876 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1877 return NULL;
1878 CHECK_DB_NOT_CLOSED(self);
1879
1880 MYDB_BEGIN_ALLOW_THREADS;
1881 err = self->db->set_bt_minkey(self->db, minkey);
1882 MYDB_END_ALLOW_THREADS;
1883 RETURN_IF_ERR();
1884 RETURN_NONE();
1885}
1886
1887
1888static PyObject*
1889DB_set_cachesize(DBObject* self, PyObject* args)
1890{
1891 int err;
1892 int gbytes = 0, bytes = 0, ncache = 0;
1893
1894 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1895 &gbytes,&bytes,&ncache))
1896 return NULL;
1897 CHECK_DB_NOT_CLOSED(self);
1898
1899 MYDB_BEGIN_ALLOW_THREADS;
1900 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1901 MYDB_END_ALLOW_THREADS;
1902 RETURN_IF_ERR();
1903 RETURN_NONE();
1904}
1905
1906
1907static PyObject*
1908DB_set_flags(DBObject* self, PyObject* args)
1909{
1910 int err, flags;
1911
1912 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1913 return NULL;
1914 CHECK_DB_NOT_CLOSED(self);
1915
1916 MYDB_BEGIN_ALLOW_THREADS;
1917 err = self->db->set_flags(self->db, flags);
1918 MYDB_END_ALLOW_THREADS;
1919 RETURN_IF_ERR();
1920
1921 self->setflags |= flags;
1922 RETURN_NONE();
1923}
1924
1925
1926static PyObject*
1927DB_set_h_ffactor(DBObject* self, PyObject* args)
1928{
1929 int err, ffactor;
1930
1931 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1932 return NULL;
1933 CHECK_DB_NOT_CLOSED(self);
1934
1935 MYDB_BEGIN_ALLOW_THREADS;
1936 err = self->db->set_h_ffactor(self->db, ffactor);
1937 MYDB_END_ALLOW_THREADS;
1938 RETURN_IF_ERR();
1939 RETURN_NONE();
1940}
1941
1942
1943static PyObject*
1944DB_set_h_nelem(DBObject* self, PyObject* args)
1945{
1946 int err, nelem;
1947
1948 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1949 return NULL;
1950 CHECK_DB_NOT_CLOSED(self);
1951
1952 MYDB_BEGIN_ALLOW_THREADS;
1953 err = self->db->set_h_nelem(self->db, nelem);
1954 MYDB_END_ALLOW_THREADS;
1955 RETURN_IF_ERR();
1956 RETURN_NONE();
1957}
1958
1959
1960static PyObject*
1961DB_set_lorder(DBObject* self, PyObject* args)
1962{
1963 int err, lorder;
1964
1965 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1966 return NULL;
1967 CHECK_DB_NOT_CLOSED(self);
1968
1969 MYDB_BEGIN_ALLOW_THREADS;
1970 err = self->db->set_lorder(self->db, lorder);
1971 MYDB_END_ALLOW_THREADS;
1972 RETURN_IF_ERR();
1973 RETURN_NONE();
1974}
1975
1976
1977static PyObject*
1978DB_set_pagesize(DBObject* self, PyObject* args)
1979{
1980 int err, pagesize;
1981
1982 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1983 return NULL;
1984 CHECK_DB_NOT_CLOSED(self);
1985
1986 MYDB_BEGIN_ALLOW_THREADS;
1987 err = self->db->set_pagesize(self->db, pagesize);
1988 MYDB_END_ALLOW_THREADS;
1989 RETURN_IF_ERR();
1990 RETURN_NONE();
1991}
1992
1993
1994static PyObject*
1995DB_set_re_delim(DBObject* self, PyObject* args)
1996{
1997 int err;
1998 char delim;
1999
2000 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2001 PyErr_Clear();
2002 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2003 return NULL;
2004 }
2005
2006 CHECK_DB_NOT_CLOSED(self);
2007
2008 MYDB_BEGIN_ALLOW_THREADS;
2009 err = self->db->set_re_delim(self->db, delim);
2010 MYDB_END_ALLOW_THREADS;
2011 RETURN_IF_ERR();
2012 RETURN_NONE();
2013}
2014
2015static PyObject*
2016DB_set_re_len(DBObject* self, PyObject* args)
2017{
2018 int err, len;
2019
2020 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2021 return NULL;
2022 CHECK_DB_NOT_CLOSED(self);
2023
2024 MYDB_BEGIN_ALLOW_THREADS;
2025 err = self->db->set_re_len(self->db, len);
2026 MYDB_END_ALLOW_THREADS;
2027 RETURN_IF_ERR();
2028 RETURN_NONE();
2029}
2030
2031
2032static PyObject*
2033DB_set_re_pad(DBObject* self, PyObject* args)
2034{
2035 int err;
2036 char pad;
2037
2038 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2039 PyErr_Clear();
2040 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2041 return NULL;
2042 }
2043 CHECK_DB_NOT_CLOSED(self);
2044
2045 MYDB_BEGIN_ALLOW_THREADS;
2046 err = self->db->set_re_pad(self->db, pad);
2047 MYDB_END_ALLOW_THREADS;
2048 RETURN_IF_ERR();
2049 RETURN_NONE();
2050}
2051
2052
2053static PyObject*
2054DB_set_re_source(DBObject* self, PyObject* args)
2055{
2056 int err;
2057 char *re_source;
2058
2059 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2060 return NULL;
2061 CHECK_DB_NOT_CLOSED(self);
2062
2063 MYDB_BEGIN_ALLOW_THREADS;
2064 err = self->db->set_re_source(self->db, re_source);
2065 MYDB_END_ALLOW_THREADS;
2066 RETURN_IF_ERR();
2067 RETURN_NONE();
2068}
2069
2070
2071#if (DBVER >= 32)
2072static PyObject*
2073DB_set_q_extentsize(DBObject* self, PyObject* args)
2074{
2075 int err;
2076 int extentsize;
2077
2078 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2079 return NULL;
2080 CHECK_DB_NOT_CLOSED(self);
2081
2082 MYDB_BEGIN_ALLOW_THREADS;
2083 err = self->db->set_q_extentsize(self->db, extentsize);
2084 MYDB_END_ALLOW_THREADS;
2085 RETURN_IF_ERR();
2086 RETURN_NONE();
2087}
2088#endif
2089
2090static PyObject*
2091DB_stat(DBObject* self, PyObject* args)
2092{
2093 int err, flags = 0, type;
2094 void* sp;
2095 PyObject* d;
2096
2097
2098 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2099 return NULL;
2100 CHECK_DB_NOT_CLOSED(self);
2101
2102 MYDB_BEGIN_ALLOW_THREADS;
2103#if (DBVER >= 33)
2104 err = self->db->stat(self->db, &sp, flags);
2105#else
2106 err = self->db->stat(self->db, &sp, NULL, flags);
2107#endif
2108 MYDB_END_ALLOW_THREADS;
2109 RETURN_IF_ERR();
2110
2111 self->haveStat = 1;
2112
2113 /* Turn the stat structure into a dictionary */
2114 type = _DB_get_type(self);
2115 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2116 free(sp);
2117 return NULL;
2118 }
2119
2120#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2121#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2122#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2123
2124 switch (type) {
2125 case DB_HASH:
2126 MAKE_HASH_ENTRY(magic);
2127 MAKE_HASH_ENTRY(version);
2128 MAKE_HASH_ENTRY(nkeys);
2129 MAKE_HASH_ENTRY(ndata);
2130 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002131#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002132 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002133#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002134 MAKE_HASH_ENTRY(ffactor);
2135 MAKE_HASH_ENTRY(buckets);
2136 MAKE_HASH_ENTRY(free);
2137 MAKE_HASH_ENTRY(bfree);
2138 MAKE_HASH_ENTRY(bigpages);
2139 MAKE_HASH_ENTRY(big_bfree);
2140 MAKE_HASH_ENTRY(overflows);
2141 MAKE_HASH_ENTRY(ovfl_free);
2142 MAKE_HASH_ENTRY(dup);
2143 MAKE_HASH_ENTRY(dup_free);
2144 break;
2145
2146 case DB_BTREE:
2147 case DB_RECNO:
2148 MAKE_BT_ENTRY(magic);
2149 MAKE_BT_ENTRY(version);
2150 MAKE_BT_ENTRY(nkeys);
2151 MAKE_BT_ENTRY(ndata);
2152 MAKE_BT_ENTRY(pagesize);
2153 MAKE_BT_ENTRY(minkey);
2154 MAKE_BT_ENTRY(re_len);
2155 MAKE_BT_ENTRY(re_pad);
2156 MAKE_BT_ENTRY(levels);
2157 MAKE_BT_ENTRY(int_pg);
2158 MAKE_BT_ENTRY(leaf_pg);
2159 MAKE_BT_ENTRY(dup_pg);
2160 MAKE_BT_ENTRY(over_pg);
2161 MAKE_BT_ENTRY(free);
2162 MAKE_BT_ENTRY(int_pgfree);
2163 MAKE_BT_ENTRY(leaf_pgfree);
2164 MAKE_BT_ENTRY(dup_pgfree);
2165 MAKE_BT_ENTRY(over_pgfree);
2166 break;
2167
2168 case DB_QUEUE:
2169 MAKE_QUEUE_ENTRY(magic);
2170 MAKE_QUEUE_ENTRY(version);
2171 MAKE_QUEUE_ENTRY(nkeys);
2172 MAKE_QUEUE_ENTRY(ndata);
2173 MAKE_QUEUE_ENTRY(pagesize);
2174 MAKE_QUEUE_ENTRY(pages);
2175 MAKE_QUEUE_ENTRY(re_len);
2176 MAKE_QUEUE_ENTRY(re_pad);
2177 MAKE_QUEUE_ENTRY(pgfree);
2178#if (DBVER == 31)
2179 MAKE_QUEUE_ENTRY(start);
2180#endif
2181 MAKE_QUEUE_ENTRY(first_recno);
2182 MAKE_QUEUE_ENTRY(cur_recno);
2183 break;
2184
2185 default:
2186 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2187 Py_DECREF(d);
2188 d = NULL;
2189 }
2190
2191#undef MAKE_HASH_ENTRY
2192#undef MAKE_BT_ENTRY
2193#undef MAKE_QUEUE_ENTRY
2194
2195 free(sp);
2196 return d;
2197}
2198
2199static PyObject*
2200DB_sync(DBObject* self, PyObject* args)
2201{
2202 int err;
2203 int flags = 0;
2204
2205 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2206 return NULL;
2207 CHECK_DB_NOT_CLOSED(self);
2208
2209 MYDB_BEGIN_ALLOW_THREADS;
2210 err = self->db->sync(self->db, flags);
2211 MYDB_END_ALLOW_THREADS;
2212 RETURN_IF_ERR();
2213 RETURN_NONE();
2214}
2215
2216
2217#if (DBVER >= 33)
2218static PyObject*
2219DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2220{
2221 int err, flags=0;
2222 u_int32_t count=0;
2223 PyObject* txnobj = NULL;
2224 DB_TXN *txn = NULL;
2225 char* kwnames[] = { "txn", "flags", NULL };
2226
2227 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2228 &txnobj, &flags))
2229 return NULL;
2230 CHECK_DB_NOT_CLOSED(self);
2231 if (!checkTxnObj(txnobj, &txn))
2232 return NULL;
2233
2234 MYDB_BEGIN_ALLOW_THREADS;
2235 err = self->db->truncate(self->db, txn, &count, flags);
2236 MYDB_END_ALLOW_THREADS;
2237 RETURN_IF_ERR();
2238 return PyInt_FromLong(count);
2239}
2240#endif
2241
2242
2243static PyObject*
2244DB_upgrade(DBObject* self, PyObject* args)
2245{
2246 int err, flags=0;
2247 char *filename;
2248
2249 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2250 return NULL;
2251 CHECK_DB_NOT_CLOSED(self);
2252
2253 MYDB_BEGIN_ALLOW_THREADS;
2254 err = self->db->upgrade(self->db, filename, flags);
2255 MYDB_END_ALLOW_THREADS;
2256 RETURN_IF_ERR();
2257 RETURN_NONE();
2258}
2259
2260
2261static PyObject*
2262DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2263{
2264 int err, flags=0;
2265 char* fileName;
2266 char* dbName=NULL;
2267 char* outFileName=NULL;
2268 FILE* outFile=NULL;
2269 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2270
2271 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2272 &fileName, &dbName, &outFileName, &flags))
2273 return NULL;
2274
2275 CHECK_DB_NOT_CLOSED(self);
2276 if (outFileName)
2277 outFile = fopen(outFileName, "w");
2278
2279 MYDB_BEGIN_ALLOW_THREADS;
2280 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2281 MYDB_END_ALLOW_THREADS;
2282 if (outFileName)
2283 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002284
2285 /* DB.verify acts as a DB handle destructor (like close); this was
2286 * documented in BerkeleyDB 4.2 but had the undocumented effect
2287 * of not being safe in prior versions while still requiring an explicit
2288 * DB.close call afterwards. Lets call close for the user to emulate
2289 * the safe 4.2 behaviour. */
2290#if (DBVER <= 41)
2291 self->db->close(self->db, 0);
2292#endif
2293 self->db = NULL;
2294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002295 RETURN_IF_ERR();
2296 RETURN_NONE();
2297}
2298
2299
2300static PyObject*
2301DB_set_get_returns_none(DBObject* self, PyObject* args)
2302{
2303 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002304 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002305
2306 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2307 return NULL;
2308 CHECK_DB_NOT_CLOSED(self);
2309
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002310 if (self->moduleFlags.getReturnsNone)
2311 ++oldValue;
2312 if (self->moduleFlags.cursorSetReturnsNone)
2313 ++oldValue;
2314 self->moduleFlags.getReturnsNone = (flags >= 1);
2315 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002316 return PyInt_FromLong(oldValue);
2317}
2318
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002319#if (DBVER >= 41)
2320static PyObject*
2321DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2322{
2323 int err;
2324 u_int32_t flags=0;
2325 char *passwd = NULL;
2326 char* kwnames[] = { "passwd", "flags", NULL };
2327
2328 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2329 &passwd, &flags)) {
2330 return NULL;
2331 }
2332
2333 MYDB_BEGIN_ALLOW_THREADS;
2334 err = self->db->set_encrypt(self->db, passwd, flags);
2335 MYDB_END_ALLOW_THREADS;
2336
2337 RETURN_IF_ERR();
2338 RETURN_NONE();
2339}
2340#endif /* DBVER >= 41 */
2341
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002342
2343/*-------------------------------------------------------------- */
2344/* Mapping and Dictionary-like access routines */
2345
2346int DB_length(DBObject* self)
2347{
2348 int err;
2349 long size = 0;
2350 int flags = 0;
2351 void* sp;
2352
2353 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002354 PyErr_SetObject(DBError,
2355 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002356 return -1;
2357 }
2358
2359 if (self->haveStat) { /* Has the stat function been called recently? If
2360 so, we can use the cached value. */
2361 flags = DB_CACHED_COUNTS;
2362 }
2363
2364 MYDB_BEGIN_ALLOW_THREADS;
2365#if (DBVER >= 33)
2366 err = self->db->stat(self->db, &sp, flags);
2367#else
2368 err = self->db->stat(self->db, &sp, NULL, flags);
2369#endif
2370 MYDB_END_ALLOW_THREADS;
2371
2372 if (err)
2373 return -1;
2374
2375 self->haveStat = 1;
2376
2377 /* All the stat structures have matching fields upto the ndata field,
2378 so we can use any of them for the type cast */
2379 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2380 free(sp);
2381 return size;
2382}
2383
2384
2385PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2386{
2387 int err;
2388 PyObject* retval;
2389 DBT key;
2390 DBT data;
2391
2392 CHECK_DB_NOT_CLOSED(self);
2393 if (!make_key_dbt(self, keyobj, &key, NULL))
2394 return NULL;
2395
2396 CLEAR_DBT(data);
2397 if (CHECK_DBFLAG(self, DB_THREAD)) {
2398 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2399 data.flags = DB_DBT_MALLOC;
2400 }
2401 MYDB_BEGIN_ALLOW_THREADS;
2402 err = self->db->get(self->db, NULL, &key, &data, 0);
2403 MYDB_END_ALLOW_THREADS;
2404 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2405 PyErr_SetObject(PyExc_KeyError, keyobj);
2406 retval = NULL;
2407 }
2408 else if (makeDBError(err)) {
2409 retval = NULL;
2410 }
2411 else {
2412 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2413 FREE_DBT(data);
2414 }
2415
2416 FREE_DBT(key);
2417 return retval;
2418}
2419
2420
2421static int
2422DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2423{
2424 DBT key, data;
2425 int retval;
2426 int flags = 0;
2427
2428 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002429 PyErr_SetObject(DBError,
2430 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002431 return -1;
2432 }
2433
2434 if (!make_key_dbt(self, keyobj, &key, NULL))
2435 return -1;
2436
2437 if (dataobj != NULL) {
2438 if (!make_dbt(dataobj, &data))
2439 retval = -1;
2440 else {
2441 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002442 /* dictionaries shouldn't have duplicate keys */
2443 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 retval = _DB_put(self, NULL, &key, &data, flags);
2445
2446 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002447 /* try deleting any old record that matches and then PUT it
2448 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002449 _DB_delete(self, NULL, &key, 0);
2450 PyErr_Clear();
2451 retval = _DB_put(self, NULL, &key, &data, flags);
2452 }
2453 }
2454 }
2455 else {
2456 /* dataobj == NULL, so delete the key */
2457 retval = _DB_delete(self, NULL, &key, 0);
2458 }
2459 FREE_DBT(key);
2460 return retval;
2461}
2462
2463
2464static PyObject*
2465DB_has_key(DBObject* self, PyObject* args)
2466{
2467 int err;
2468 PyObject* keyobj;
2469 DBT key, data;
2470 PyObject* txnobj = NULL;
2471 DB_TXN *txn = NULL;
2472
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002473 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002474 return NULL;
2475 CHECK_DB_NOT_CLOSED(self);
2476 if (!make_key_dbt(self, keyobj, &key, NULL))
2477 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002478 if (!checkTxnObj(txnobj, &txn)) {
2479 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002480 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002481 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002482
2483 /* This causes ENOMEM to be returned when the db has the key because
2484 it has a record but can't allocate a buffer for the data. This saves
2485 having to deal with data we won't be using.
2486 */
2487 CLEAR_DBT(data);
2488 data.flags = DB_DBT_USERMEM;
2489
2490 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002491 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002492 MYDB_END_ALLOW_THREADS;
2493 FREE_DBT(key);
2494 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2495}
2496
2497
2498#define _KEYS_LIST 1
2499#define _VALUES_LIST 2
2500#define _ITEMS_LIST 3
2501
2502static PyObject*
2503_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2504{
2505 int err, dbtype;
2506 DBT key;
2507 DBT data;
2508 DBC *cursor;
2509 PyObject* list;
2510 PyObject* item = NULL;
2511
2512 CHECK_DB_NOT_CLOSED(self);
2513 CLEAR_DBT(key);
2514 CLEAR_DBT(data);
2515
2516 dbtype = _DB_get_type(self);
2517 if (dbtype == -1)
2518 return NULL;
2519
2520 list = PyList_New(0);
2521 if (list == NULL) {
2522 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2523 return NULL;
2524 }
2525
2526 /* get a cursor */
2527 MYDB_BEGIN_ALLOW_THREADS;
2528 err = self->db->cursor(self->db, NULL, &cursor, 0);
2529 MYDB_END_ALLOW_THREADS;
2530 RETURN_IF_ERR();
2531
2532 if (CHECK_DBFLAG(self, DB_THREAD)) {
2533 key.flags = DB_DBT_REALLOC;
2534 data.flags = DB_DBT_REALLOC;
2535 }
2536
2537 while (1) { /* use the cursor to traverse the DB, collecting items */
2538 MYDB_BEGIN_ALLOW_THREADS;
2539 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2540 MYDB_END_ALLOW_THREADS;
2541
2542 if (err) {
2543 /* for any error, break out of the loop */
2544 break;
2545 }
2546
2547 switch (type) {
2548 case _KEYS_LIST:
2549 switch(dbtype) {
2550 case DB_BTREE:
2551 case DB_HASH:
2552 default:
2553 item = PyString_FromStringAndSize((char*)key.data, key.size);
2554 break;
2555 case DB_RECNO:
2556 case DB_QUEUE:
2557 item = PyInt_FromLong(*((db_recno_t*)key.data));
2558 break;
2559 }
2560 break;
2561
2562 case _VALUES_LIST:
2563 item = PyString_FromStringAndSize((char*)data.data, data.size);
2564 break;
2565
2566 case _ITEMS_LIST:
2567 switch(dbtype) {
2568 case DB_BTREE:
2569 case DB_HASH:
2570 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002571 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2572 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573 break;
2574 case DB_RECNO:
2575 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002576 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2577 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002578 break;
2579 }
2580 break;
2581 }
2582 if (item == NULL) {
2583 Py_DECREF(list);
2584 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2585 list = NULL;
2586 goto done;
2587 }
2588 PyList_Append(list, item);
2589 Py_DECREF(item);
2590 }
2591
2592 /* DB_NOTFOUND is okay, it just means we got to the end */
2593 if (err != DB_NOTFOUND && makeDBError(err)) {
2594 Py_DECREF(list);
2595 list = NULL;
2596 }
2597
2598 done:
2599 FREE_DBT(key);
2600 FREE_DBT(data);
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 cursor->c_close(cursor);
2603 MYDB_END_ALLOW_THREADS;
2604 return list;
2605}
2606
2607
2608static PyObject*
2609DB_keys(DBObject* self, PyObject* args)
2610{
2611 PyObject* txnobj = NULL;
2612 DB_TXN *txn = NULL;
2613
2614 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2615 return NULL;
2616 if (!checkTxnObj(txnobj, &txn))
2617 return NULL;
2618 return _DB_make_list(self, txn, _KEYS_LIST);
2619}
2620
2621
2622static PyObject*
2623DB_items(DBObject* self, PyObject* args)
2624{
2625 PyObject* txnobj = NULL;
2626 DB_TXN *txn = NULL;
2627
2628 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2629 return NULL;
2630 if (!checkTxnObj(txnobj, &txn))
2631 return NULL;
2632 return _DB_make_list(self, txn, _ITEMS_LIST);
2633}
2634
2635
2636static PyObject*
2637DB_values(DBObject* self, PyObject* args)
2638{
2639 PyObject* txnobj = NULL;
2640 DB_TXN *txn = NULL;
2641
2642 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2643 return NULL;
2644 if (!checkTxnObj(txnobj, &txn))
2645 return NULL;
2646 return _DB_make_list(self, txn, _VALUES_LIST);
2647}
2648
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002649/* --------------------------------------------------------------------- */
2650/* DBCursor methods */
2651
2652
2653static PyObject*
2654DBC_close(DBCursorObject* self, PyObject* args)
2655{
2656 int err = 0;
2657
2658 if (!PyArg_ParseTuple(args, ":close"))
2659 return NULL;
2660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002661 if (self->dbc != NULL) {
2662 MYDB_BEGIN_ALLOW_THREADS;
2663 err = self->dbc->c_close(self->dbc);
2664 self->dbc = NULL;
2665 MYDB_END_ALLOW_THREADS;
2666 }
2667 RETURN_IF_ERR();
2668 RETURN_NONE();
2669}
2670
2671
2672static PyObject*
2673DBC_count(DBCursorObject* self, PyObject* args)
2674{
2675 int err = 0;
2676 db_recno_t count;
2677 int flags = 0;
2678
2679 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2680 return NULL;
2681
2682 CHECK_CURSOR_NOT_CLOSED(self);
2683
2684 MYDB_BEGIN_ALLOW_THREADS;
2685 err = self->dbc->c_count(self->dbc, &count, flags);
2686 MYDB_END_ALLOW_THREADS;
2687 RETURN_IF_ERR();
2688
2689 return PyInt_FromLong(count);
2690}
2691
2692
2693static PyObject*
2694DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2695{
2696 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2697}
2698
2699
2700static PyObject*
2701DBC_delete(DBCursorObject* self, PyObject* args)
2702{
2703 int err, flags=0;
2704
2705 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2706 return NULL;
2707
2708 CHECK_CURSOR_NOT_CLOSED(self);
2709
2710 MYDB_BEGIN_ALLOW_THREADS;
2711 err = self->dbc->c_del(self->dbc, flags);
2712 MYDB_END_ALLOW_THREADS;
2713 RETURN_IF_ERR();
2714
2715 self->mydb->haveStat = 0;
2716 RETURN_NONE();
2717}
2718
2719
2720static PyObject*
2721DBC_dup(DBCursorObject* self, PyObject* args)
2722{
2723 int err, flags =0;
2724 DBC* dbc = NULL;
2725
2726 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2727 return NULL;
2728
2729 CHECK_CURSOR_NOT_CLOSED(self);
2730
2731 MYDB_BEGIN_ALLOW_THREADS;
2732 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2733 MYDB_END_ALLOW_THREADS;
2734 RETURN_IF_ERR();
2735
2736 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2737}
2738
2739static PyObject*
2740DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2741{
2742 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2743}
2744
2745
2746static PyObject*
2747DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2748{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002749 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002750 PyObject* keyobj = NULL;
2751 PyObject* dataobj = NULL;
2752 PyObject* retval = NULL;
2753 int dlen = -1;
2754 int doff = -1;
2755 DBT key, data;
2756 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2757
2758 CLEAR_DBT(key);
2759 CLEAR_DBT(data);
2760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002761 &flags, &dlen, &doff))
2762 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002763 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002764 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2765 &kwnames[1],
2766 &keyobj, &flags, &dlen, &doff))
2767 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002768 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002769 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2770 kwnames, &keyobj, &dataobj,
2771 &flags, &dlen, &doff))
2772 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002773 return NULL;
2774 }
2775 }
2776 }
2777
2778 CHECK_CURSOR_NOT_CLOSED(self);
2779
2780 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2781 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002782 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2783 (!add_partial_dbt(&data, dlen, doff)) )
2784 {
2785 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002787 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788
2789 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2790 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002791 if (!(key.flags & DB_DBT_REALLOC)) {
2792 key.flags |= DB_DBT_MALLOC;
2793 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002794 }
2795
2796 MYDB_BEGIN_ALLOW_THREADS;
2797 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2798 MYDB_END_ALLOW_THREADS;
2799
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002800 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801 Py_INCREF(Py_None);
2802 retval = Py_None;
2803 }
2804 else if (makeDBError(err)) {
2805 retval = NULL;
2806 }
2807 else {
2808 switch (_DB_get_type(self->mydb)) {
2809 case -1:
2810 retval = NULL;
2811 break;
2812 case DB_BTREE:
2813 case DB_HASH:
2814 default:
2815 retval = Py_BuildValue("s#s#", key.data, key.size,
2816 data.data, data.size);
2817 break;
2818 case DB_RECNO:
2819 case DB_QUEUE:
2820 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2821 data.data, data.size);
2822 break;
2823 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824 FREE_DBT(data);
2825 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002826 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002827 return retval;
2828}
2829
2830
2831static PyObject*
2832DBC_get_recno(DBCursorObject* self, PyObject* args)
2833{
2834 int err;
2835 db_recno_t recno;
2836 DBT key;
2837 DBT data;
2838
2839 if (!PyArg_ParseTuple(args, ":get_recno"))
2840 return NULL;
2841
2842 CHECK_CURSOR_NOT_CLOSED(self);
2843
2844 CLEAR_DBT(key);
2845 CLEAR_DBT(data);
2846 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2847 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2848 data.flags = DB_DBT_MALLOC;
2849 key.flags = DB_DBT_MALLOC;
2850 }
2851
2852 MYDB_BEGIN_ALLOW_THREADS;
2853 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2854 MYDB_END_ALLOW_THREADS;
2855 RETURN_IF_ERR();
2856
2857 recno = *((db_recno_t*)data.data);
2858 FREE_DBT(key);
2859 FREE_DBT(data);
2860 return PyInt_FromLong(recno);
2861}
2862
2863
2864static PyObject*
2865DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2866{
2867 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2868}
2869
2870
2871static PyObject*
2872DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2873{
2874 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2875}
2876
2877
2878static PyObject*
2879DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2880{
2881 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2882}
2883
2884
2885static PyObject*
2886DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2887{
2888 int err, flags = 0;
2889 PyObject* keyobj, *dataobj;
2890 DBT key, data;
2891 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2892 int dlen = -1;
2893 int doff = -1;
2894
2895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2896 &keyobj, &dataobj, &flags, &dlen, &doff))
2897 return NULL;
2898
2899 CHECK_CURSOR_NOT_CLOSED(self);
2900
2901 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2902 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002903 if (!make_dbt(dataobj, &data) ||
2904 !add_partial_dbt(&data, dlen, doff) )
2905 {
2906 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002907 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002908 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002909
2910 MYDB_BEGIN_ALLOW_THREADS;
2911 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2912 MYDB_END_ALLOW_THREADS;
2913 FREE_DBT(key);
2914 RETURN_IF_ERR();
2915 self->mydb->haveStat = 0;
2916 RETURN_NONE();
2917}
2918
2919
2920static PyObject*
2921DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2922{
2923 int err, flags = 0;
2924 DBT key, data;
2925 PyObject* retval, *keyobj;
2926 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2927 int dlen = -1;
2928 int doff = -1;
2929
2930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2931 &keyobj, &flags, &dlen, &doff))
2932 return NULL;
2933
2934 CHECK_CURSOR_NOT_CLOSED(self);
2935
2936 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2937 return NULL;
2938
2939 CLEAR_DBT(data);
2940 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2941 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2942 data.flags = DB_DBT_MALLOC;
2943 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002944 if (!add_partial_dbt(&data, dlen, doff)) {
2945 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002946 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002947 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948
2949 MYDB_BEGIN_ALLOW_THREADS;
2950 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2951 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002952 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2953 Py_INCREF(Py_None);
2954 retval = Py_None;
2955 }
2956 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002957 retval = NULL;
2958 }
2959 else {
2960 switch (_DB_get_type(self->mydb)) {
2961 case -1:
2962 retval = NULL;
2963 break;
2964 case DB_BTREE:
2965 case DB_HASH:
2966 default:
2967 retval = Py_BuildValue("s#s#", key.data, key.size,
2968 data.data, data.size);
2969 break;
2970 case DB_RECNO:
2971 case DB_QUEUE:
2972 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2973 data.data, data.size);
2974 break;
2975 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 FREE_DBT(data);
2977 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002978 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002979
2980 return retval;
2981}
2982
2983
2984static PyObject*
2985DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2986{
2987 int err, flags = 0;
2988 DBT key, data;
2989 PyObject* retval, *keyobj;
2990 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2991 int dlen = -1;
2992 int doff = -1;
2993
2994 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2995 &keyobj, &flags, &dlen, &doff))
2996 return NULL;
2997
2998 CHECK_CURSOR_NOT_CLOSED(self);
2999
3000 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3001 return NULL;
3002
3003 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003004 if (!add_partial_dbt(&data, dlen, doff)) {
3005 FREE_DBT(key);
3006 return NULL;
3007 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003008 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3009 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003010 data.flags |= DB_DBT_MALLOC;
3011 /* only BTREE databases will return anything in the key */
3012 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3013 key.flags |= DB_DBT_MALLOC;
3014 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016 MYDB_BEGIN_ALLOW_THREADS;
3017 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3018 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003019 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3020 Py_INCREF(Py_None);
3021 retval = Py_None;
3022 }
3023 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003024 retval = NULL;
3025 }
3026 else {
3027 switch (_DB_get_type(self->mydb)) {
3028 case -1:
3029 retval = NULL;
3030 break;
3031 case DB_BTREE:
3032 case DB_HASH:
3033 default:
3034 retval = Py_BuildValue("s#s#", key.data, key.size,
3035 data.data, data.size);
3036 break;
3037 case DB_RECNO:
3038 case DB_QUEUE:
3039 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3040 data.data, data.size);
3041 break;
3042 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003043 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 FREE_DBT(data);
3045 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003046 /* the only time REALLOC should be set is if we used an integer
3047 * key that make_dbt_key malloc'd for us. always free these. */
3048 if (key.flags & DB_DBT_REALLOC) {
3049 FREE_DBT(key);
3050 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051
3052 return retval;
3053}
3054
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003055static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003056_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3057 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003058{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003059 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003061 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062
Gregory P. Smith7441e652003-11-03 21:35:31 +00003063 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003064 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3065 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003066 if (!make_dbt(dataobj, &data)) {
3067 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003069 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003070
3071 MYDB_BEGIN_ALLOW_THREADS;
3072 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3073 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003074 if ((err == DB_NOTFOUND) && returnsNone) {
3075 Py_INCREF(Py_None);
3076 retval = Py_None;
3077 }
3078 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 retval = NULL;
3080 }
3081 else {
3082 switch (_DB_get_type(self->mydb)) {
3083 case -1:
3084 retval = NULL;
3085 break;
3086 case DB_BTREE:
3087 case DB_HASH:
3088 default:
3089 retval = Py_BuildValue("s#s#", key.data, key.size,
3090 data.data, data.size);
3091 break;
3092 case DB_RECNO:
3093 case DB_QUEUE:
3094 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3095 data.data, data.size);
3096 break;
3097 }
3098 }
3099
3100 FREE_DBT(key);
3101 return retval;
3102}
3103
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003104static PyObject*
3105DBC_get_both(DBCursorObject* self, PyObject* args)
3106{
3107 int flags=0;
3108 PyObject *keyobj, *dataobj;
3109
3110 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3111 return NULL;
3112
Gregory P. Smith7441e652003-11-03 21:35:31 +00003113 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003114 CHECK_CURSOR_NOT_CLOSED(self);
3115
3116 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3117 self->mydb->moduleFlags.getReturnsNone);
3118}
3119
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003120/* Return size of entry */
3121static PyObject*
3122DBC_get_current_size(DBCursorObject* self, PyObject* args)
3123{
3124 int err, flags=DB_CURRENT;
3125 PyObject* retval = NULL;
3126 DBT key, data;
3127
3128 if (!PyArg_ParseTuple(args, ":get_current_size"))
3129 return NULL;
3130 CHECK_CURSOR_NOT_CLOSED(self);
3131 CLEAR_DBT(key);
3132 CLEAR_DBT(data);
3133
3134 /* We don't allocate any memory, forcing a ENOMEM error and thus
3135 getting the record size. */
3136 data.flags = DB_DBT_USERMEM;
3137 data.ulen = 0;
3138 MYDB_BEGIN_ALLOW_THREADS;
3139 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3140 MYDB_END_ALLOW_THREADS;
3141 if (err == ENOMEM || !err) {
3142 /* ENOMEM means positive size, !err means zero length value */
3143 retval = PyInt_FromLong((long)data.size);
3144 err = 0;
3145 }
3146
3147 FREE_DBT(key);
3148 FREE_DBT(data);
3149 RETURN_IF_ERR();
3150 return retval;
3151}
3152
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003153static PyObject*
3154DBC_set_both(DBCursorObject* self, PyObject* args)
3155{
3156 int flags=0;
3157 PyObject *keyobj, *dataobj;
3158
3159 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3160 return NULL;
3161
Gregory P. Smith7441e652003-11-03 21:35:31 +00003162 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003163 CHECK_CURSOR_NOT_CLOSED(self);
3164
3165 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3166 self->mydb->moduleFlags.cursorSetReturnsNone);
3167}
3168
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169
3170static PyObject*
3171DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3172{
3173 int err, irecno, flags=0;
3174 db_recno_t recno;
3175 DBT key, data;
3176 PyObject* retval;
3177 int dlen = -1;
3178 int doff = -1;
3179 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3180
3181 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3182 &irecno, &flags, &dlen, &doff))
3183 return NULL;
3184
3185 CHECK_CURSOR_NOT_CLOSED(self);
3186
3187 CLEAR_DBT(key);
3188 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003189 /* use allocated space so DB will be able to realloc room for the real
3190 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191 key.data = malloc(sizeof(db_recno_t));
3192 if (key.data == NULL) {
3193 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3194 return NULL;
3195 }
3196 key.size = sizeof(db_recno_t);
3197 key.ulen = key.size;
3198 memcpy(key.data, &recno, sizeof(db_recno_t));
3199 key.flags = DB_DBT_REALLOC;
3200
3201 CLEAR_DBT(data);
3202 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3203 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3204 data.flags = DB_DBT_MALLOC;
3205 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003206 if (!add_partial_dbt(&data, dlen, doff)) {
3207 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003209 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210
3211 MYDB_BEGIN_ALLOW_THREADS;
3212 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3213 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003214 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3215 Py_INCREF(Py_None);
3216 retval = Py_None;
3217 }
3218 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003219 retval = NULL;
3220 }
3221 else { /* Can only be used for BTrees, so no need to return int key */
3222 retval = Py_BuildValue("s#s#", key.data, key.size,
3223 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003224 FREE_DBT(data);
3225 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003226 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003227
3228 return retval;
3229}
3230
3231
3232static PyObject*
3233DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3234{
3235 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3236}
3237
3238
3239static PyObject*
3240DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3241{
3242 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3243}
3244
3245
3246static PyObject*
3247DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3248{
3249 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3250}
3251
3252
3253static PyObject*
3254DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3255{
3256 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3257}
3258
3259
3260static PyObject*
3261DBC_join_item(DBCursorObject* self, PyObject* args)
3262{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003263 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 DBT key, data;
3265 PyObject* retval;
3266
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003267 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003268 return NULL;
3269
3270 CHECK_CURSOR_NOT_CLOSED(self);
3271
3272 CLEAR_DBT(key);
3273 CLEAR_DBT(data);
3274 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3275 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3276 key.flags = DB_DBT_MALLOC;
3277 }
3278
3279 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003280 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003281 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003282 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3283 Py_INCREF(Py_None);
3284 retval = Py_None;
3285 }
3286 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003287 retval = NULL;
3288 }
3289 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003290 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003291 FREE_DBT(key);
3292 }
3293
3294 return retval;
3295}
3296
3297
3298
3299/* --------------------------------------------------------------------- */
3300/* DBEnv methods */
3301
3302
3303static PyObject*
3304DBEnv_close(DBEnvObject* self, PyObject* args)
3305{
3306 int err, flags = 0;
3307
3308 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3309 return NULL;
3310 if (!self->closed) { /* Don't close more than once */
3311 MYDB_BEGIN_ALLOW_THREADS;
3312 err = self->db_env->close(self->db_env, flags);
3313 MYDB_END_ALLOW_THREADS;
3314 /* after calling DBEnv->close, regardless of error, this DBEnv
3315 * may not be accessed again (BerkeleyDB docs). */
3316 self->closed = 1;
3317 self->db_env = NULL;
3318 RETURN_IF_ERR();
3319 }
3320 RETURN_NONE();
3321}
3322
3323
3324static PyObject*
3325DBEnv_open(DBEnvObject* self, PyObject* args)
3326{
3327 int err, flags=0, mode=0660;
3328 char *db_home;
3329
3330 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3331 return NULL;
3332
3333 CHECK_ENV_NOT_CLOSED(self);
3334
3335 MYDB_BEGIN_ALLOW_THREADS;
3336 err = self->db_env->open(self->db_env, db_home, flags, mode);
3337 MYDB_END_ALLOW_THREADS;
3338 RETURN_IF_ERR();
3339 self->closed = 0;
3340 self->flags = flags;
3341 RETURN_NONE();
3342}
3343
3344
3345static PyObject*
3346DBEnv_remove(DBEnvObject* self, PyObject* args)
3347{
3348 int err, flags=0;
3349 char *db_home;
3350
3351 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3352 return NULL;
3353 CHECK_ENV_NOT_CLOSED(self);
3354 MYDB_BEGIN_ALLOW_THREADS;
3355 err = self->db_env->remove(self->db_env, db_home, flags);
3356 MYDB_END_ALLOW_THREADS;
3357 RETURN_IF_ERR();
3358 RETURN_NONE();
3359}
3360
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003361#if (DBVER >= 41)
3362static PyObject*
3363DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3364{
3365 int err;
3366 u_int32_t flags=0;
3367 char *file = NULL;
3368 char *database = NULL;
3369 PyObject *txnobj = NULL;
3370 DB_TXN *txn = NULL;
3371 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3372
3373 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3374 &file, &database, &txnobj, &flags)) {
3375 return NULL;
3376 }
3377 if (!checkTxnObj(txnobj, &txn)) {
3378 return NULL;
3379 }
3380 CHECK_ENV_NOT_CLOSED(self);
3381 MYDB_BEGIN_ALLOW_THREADS;
3382 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3383 MYDB_END_ALLOW_THREADS;
3384 RETURN_IF_ERR();
3385 RETURN_NONE();
3386}
3387
3388static PyObject*
3389DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3390{
3391 int err;
3392 u_int32_t flags=0;
3393 char *file = NULL;
3394 char *database = NULL;
3395 char *newname = NULL;
3396 PyObject *txnobj = NULL;
3397 DB_TXN *txn = NULL;
3398 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3399
3400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3401 &file, &database, &newname, &txnobj, &flags)) {
3402 return NULL;
3403 }
3404 if (!checkTxnObj(txnobj, &txn)) {
3405 return NULL;
3406 }
3407 CHECK_ENV_NOT_CLOSED(self);
3408 MYDB_BEGIN_ALLOW_THREADS;
3409 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3410 flags);
3411 MYDB_END_ALLOW_THREADS;
3412 RETURN_IF_ERR();
3413 RETURN_NONE();
3414}
3415
3416static PyObject*
3417DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3418{
3419 int err;
3420 u_int32_t flags=0;
3421 char *passwd = NULL;
3422 char* kwnames[] = { "passwd", "flags", NULL };
3423
3424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3425 &passwd, &flags)) {
3426 return NULL;
3427 }
3428
3429 MYDB_BEGIN_ALLOW_THREADS;
3430 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3431 MYDB_END_ALLOW_THREADS;
3432
3433 RETURN_IF_ERR();
3434 RETURN_NONE();
3435}
3436#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003437
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003438#if (DBVER >= 40)
3439static PyObject*
3440DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3441{
3442 int err;
3443 u_int32_t flags=0;
3444 u_int32_t timeout = 0;
3445 char* kwnames[] = { "timeout", "flags", NULL };
3446
3447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3448 &timeout, &flags)) {
3449 return NULL;
3450 }
3451
3452 MYDB_BEGIN_ALLOW_THREADS;
3453 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3454 MYDB_END_ALLOW_THREADS;
3455
3456 RETURN_IF_ERR();
3457 RETURN_NONE();
3458}
3459#endif /* DBVER >= 40 */
3460
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003462DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3463{
3464 int err;
3465 long shm_key = 0;
3466
3467 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3468 return NULL;
3469 CHECK_ENV_NOT_CLOSED(self);
3470
3471 err = self->db_env->set_shm_key(self->db_env, shm_key);
3472 RETURN_IF_ERR();
3473 RETURN_NONE();
3474}
3475
3476static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003477DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3478{
3479 int err, gbytes=0, bytes=0, ncache=0;
3480
3481 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3482 &gbytes, &bytes, &ncache))
3483 return NULL;
3484 CHECK_ENV_NOT_CLOSED(self);
3485
3486 MYDB_BEGIN_ALLOW_THREADS;
3487 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3488 MYDB_END_ALLOW_THREADS;
3489 RETURN_IF_ERR();
3490 RETURN_NONE();
3491}
3492
3493
3494#if (DBVER >= 32)
3495static PyObject*
3496DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3497{
3498 int err, flags=0, onoff=0;
3499
3500 if (!PyArg_ParseTuple(args, "ii:set_flags",
3501 &flags, &onoff))
3502 return NULL;
3503 CHECK_ENV_NOT_CLOSED(self);
3504
3505 MYDB_BEGIN_ALLOW_THREADS;
3506 err = self->db_env->set_flags(self->db_env, flags, onoff);
3507 MYDB_END_ALLOW_THREADS;
3508 RETURN_IF_ERR();
3509 RETURN_NONE();
3510}
3511#endif
3512
3513
3514static PyObject*
3515DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3516{
3517 int err;
3518 char *dir;
3519
3520 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3521 return NULL;
3522 CHECK_ENV_NOT_CLOSED(self);
3523
3524 MYDB_BEGIN_ALLOW_THREADS;
3525 err = self->db_env->set_data_dir(self->db_env, dir);
3526 MYDB_END_ALLOW_THREADS;
3527 RETURN_IF_ERR();
3528 RETURN_NONE();
3529}
3530
3531
3532static PyObject*
3533DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3534{
3535 int err, lg_bsize;
3536
3537 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3538 return NULL;
3539 CHECK_ENV_NOT_CLOSED(self);
3540
3541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3543 MYDB_END_ALLOW_THREADS;
3544 RETURN_IF_ERR();
3545 RETURN_NONE();
3546}
3547
3548
3549static PyObject*
3550DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3551{
3552 int err;
3553 char *dir;
3554
3555 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3556 return NULL;
3557 CHECK_ENV_NOT_CLOSED(self);
3558
3559 MYDB_BEGIN_ALLOW_THREADS;
3560 err = self->db_env->set_lg_dir(self->db_env, dir);
3561 MYDB_END_ALLOW_THREADS;
3562 RETURN_IF_ERR();
3563 RETURN_NONE();
3564}
3565
3566static PyObject*
3567DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3568{
3569 int err, lg_max;
3570
3571 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3572 return NULL;
3573 CHECK_ENV_NOT_CLOSED(self);
3574
3575 MYDB_BEGIN_ALLOW_THREADS;
3576 err = self->db_env->set_lg_max(self->db_env, lg_max);
3577 MYDB_END_ALLOW_THREADS;
3578 RETURN_IF_ERR();
3579 RETURN_NONE();
3580}
3581
3582
3583static PyObject*
3584DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3585{
3586 int err, lk_detect;
3587
3588 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3589 return NULL;
3590 CHECK_ENV_NOT_CLOSED(self);
3591
3592 MYDB_BEGIN_ALLOW_THREADS;
3593 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3594 MYDB_END_ALLOW_THREADS;
3595 RETURN_IF_ERR();
3596 RETURN_NONE();
3597}
3598
3599
3600static PyObject*
3601DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3602{
3603 int err, max;
3604
3605 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3606 return NULL;
3607 CHECK_ENV_NOT_CLOSED(self);
3608
3609 MYDB_BEGIN_ALLOW_THREADS;
3610 err = self->db_env->set_lk_max(self->db_env, max);
3611 MYDB_END_ALLOW_THREADS;
3612 RETURN_IF_ERR();
3613 RETURN_NONE();
3614}
3615
3616
3617#if (DBVER >= 32)
3618
3619static PyObject*
3620DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3621{
3622 int err, max;
3623
3624 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3625 return NULL;
3626 CHECK_ENV_NOT_CLOSED(self);
3627
3628 MYDB_BEGIN_ALLOW_THREADS;
3629 err = self->db_env->set_lk_max_locks(self->db_env, max);
3630 MYDB_END_ALLOW_THREADS;
3631 RETURN_IF_ERR();
3632 RETURN_NONE();
3633}
3634
3635
3636static PyObject*
3637DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3638{
3639 int err, max;
3640
3641 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3642 return NULL;
3643 CHECK_ENV_NOT_CLOSED(self);
3644
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3647 MYDB_END_ALLOW_THREADS;
3648 RETURN_IF_ERR();
3649 RETURN_NONE();
3650}
3651
3652
3653static PyObject*
3654DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3655{
3656 int err, max;
3657
3658 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3659 return NULL;
3660 CHECK_ENV_NOT_CLOSED(self);
3661
3662 MYDB_BEGIN_ALLOW_THREADS;
3663 err = self->db_env->set_lk_max_objects(self->db_env, max);
3664 MYDB_END_ALLOW_THREADS;
3665 RETURN_IF_ERR();
3666 RETURN_NONE();
3667}
3668
3669#endif
3670
3671
3672static PyObject*
3673DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3674{
3675 int err, mp_mmapsize;
3676
3677 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3678 return NULL;
3679 CHECK_ENV_NOT_CLOSED(self);
3680
3681 MYDB_BEGIN_ALLOW_THREADS;
3682 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3683 MYDB_END_ALLOW_THREADS;
3684 RETURN_IF_ERR();
3685 RETURN_NONE();
3686}
3687
3688
3689static PyObject*
3690DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3691{
3692 int err;
3693 char *dir;
3694
3695 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3696 return NULL;
3697 CHECK_ENV_NOT_CLOSED(self);
3698
3699 MYDB_BEGIN_ALLOW_THREADS;
3700 err = self->db_env->set_tmp_dir(self->db_env, dir);
3701 MYDB_END_ALLOW_THREADS;
3702 RETURN_IF_ERR();
3703 RETURN_NONE();
3704}
3705
3706
3707static PyObject*
3708DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3709{
3710 int flags = 0;
3711 PyObject* txnobj = NULL;
3712 DB_TXN *txn = NULL;
3713 char* kwnames[] = { "parent", "flags", NULL };
3714
3715 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3716 &txnobj, &flags))
3717 return NULL;
3718
3719 if (!checkTxnObj(txnobj, &txn))
3720 return NULL;
3721 CHECK_ENV_NOT_CLOSED(self);
3722
3723 return (PyObject*)newDBTxnObject(self, txn, flags);
3724}
3725
3726
3727static PyObject*
3728DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3729{
3730 int err, kbyte=0, min=0, flags=0;
3731
3732 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3733 return NULL;
3734 CHECK_ENV_NOT_CLOSED(self);
3735
3736 MYDB_BEGIN_ALLOW_THREADS;
3737#if (DBVER >= 40)
3738 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3739#else
3740 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3741#endif
3742 MYDB_END_ALLOW_THREADS;
3743 RETURN_IF_ERR();
3744 RETURN_NONE();
3745}
3746
3747
3748static PyObject*
3749DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3750{
3751 int err, max;
3752
3753 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3754 return NULL;
3755 CHECK_ENV_NOT_CLOSED(self);
3756
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 err = self->db_env->set_tx_max(self->db_env, max);
3759 MYDB_END_ALLOW_THREADS;
3760 RETURN_IF_ERR();
3761 RETURN_NONE();
3762}
3763
3764
3765static PyObject*
3766DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3767{
3768 int err, atype, flags=0;
3769 int aborted = 0;
3770
3771 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3772 return NULL;
3773 CHECK_ENV_NOT_CLOSED(self);
3774
3775 MYDB_BEGIN_ALLOW_THREADS;
3776#if (DBVER >= 40)
3777 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3778#else
3779 err = lock_detect(self->db_env, flags, atype, &aborted);
3780#endif
3781 MYDB_END_ALLOW_THREADS;
3782 RETURN_IF_ERR();
3783 return PyInt_FromLong(aborted);
3784}
3785
3786
3787static PyObject*
3788DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3789{
3790 int flags=0;
3791 int locker, lock_mode;
3792 DBT obj;
3793 PyObject* objobj;
3794
3795 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3796 return NULL;
3797
3798
3799 if (!make_dbt(objobj, &obj))
3800 return NULL;
3801
3802 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3803}
3804
3805
3806static PyObject*
3807DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3808{
3809 int err;
3810 u_int32_t theID;
3811
3812 if (!PyArg_ParseTuple(args, ":lock_id"))
3813 return NULL;
3814
3815 CHECK_ENV_NOT_CLOSED(self);
3816 MYDB_BEGIN_ALLOW_THREADS;
3817#if (DBVER >= 40)
3818 err = self->db_env->lock_id(self->db_env, &theID);
3819#else
3820 err = lock_id(self->db_env, &theID);
3821#endif
3822 MYDB_END_ALLOW_THREADS;
3823 RETURN_IF_ERR();
3824
3825 return PyInt_FromLong((long)theID);
3826}
3827
3828
3829static PyObject*
3830DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3831{
3832 int err;
3833 DBLockObject* dblockobj;
3834
3835 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3836 return NULL;
3837
3838 CHECK_ENV_NOT_CLOSED(self);
3839 MYDB_BEGIN_ALLOW_THREADS;
3840#if (DBVER >= 40)
3841 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3842#else
3843 err = lock_put(self->db_env, &dblockobj->lock);
3844#endif
3845 MYDB_END_ALLOW_THREADS;
3846 RETURN_IF_ERR();
3847 RETURN_NONE();
3848}
3849
3850
3851static PyObject*
3852DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3853{
3854 int err;
3855 DB_LOCK_STAT* sp;
3856 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003857 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003858
3859 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3860 return NULL;
3861 CHECK_ENV_NOT_CLOSED(self);
3862
3863 MYDB_BEGIN_ALLOW_THREADS;
3864#if (DBVER >= 40)
3865 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3866#else
3867#if (DBVER >= 33)
3868 err = lock_stat(self->db_env, &sp);
3869#else
3870 err = lock_stat(self->db_env, &sp, NULL);
3871#endif
3872#endif
3873 MYDB_END_ALLOW_THREADS;
3874 RETURN_IF_ERR();
3875
3876 /* Turn the stat structure into a dictionary */
3877 d = PyDict_New();
3878 if (d == NULL) {
3879 free(sp);
3880 return NULL;
3881 }
3882
3883#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3884
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003885#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003886 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003887#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003888 MAKE_ENTRY(nmodes);
3889#if (DBVER >= 32)
3890 MAKE_ENTRY(maxlocks);
3891 MAKE_ENTRY(maxlockers);
3892 MAKE_ENTRY(maxobjects);
3893 MAKE_ENTRY(nlocks);
3894 MAKE_ENTRY(maxnlocks);
3895#endif
3896 MAKE_ENTRY(nlockers);
3897 MAKE_ENTRY(maxnlockers);
3898#if (DBVER >= 32)
3899 MAKE_ENTRY(nobjects);
3900 MAKE_ENTRY(maxnobjects);
3901#endif
3902 MAKE_ENTRY(nrequests);
3903 MAKE_ENTRY(nreleases);
3904 MAKE_ENTRY(nnowaits);
3905 MAKE_ENTRY(nconflicts);
3906 MAKE_ENTRY(ndeadlocks);
3907 MAKE_ENTRY(regsize);
3908 MAKE_ENTRY(region_wait);
3909 MAKE_ENTRY(region_nowait);
3910
3911#undef MAKE_ENTRY
3912 free(sp);
3913 return d;
3914}
3915
3916
3917static PyObject*
3918DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3919{
3920 int flags=0;
3921 int err;
3922 char **log_list_start, **log_list;
3923 PyObject* list;
3924 PyObject* item = NULL;
3925
3926 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3927 return NULL;
3928
3929 CHECK_ENV_NOT_CLOSED(self);
3930 MYDB_BEGIN_ALLOW_THREADS;
3931#if (DBVER >= 40)
3932 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3933#elif (DBVER == 33)
3934 err = log_archive(self->db_env, &log_list, flags);
3935#else
3936 err = log_archive(self->db_env, &log_list, flags, NULL);
3937#endif
3938 MYDB_END_ALLOW_THREADS;
3939 RETURN_IF_ERR();
3940
3941 list = PyList_New(0);
3942 if (list == NULL) {
3943 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3944 return NULL;
3945 }
3946
3947 if (log_list) {
3948 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3949 item = PyString_FromString (*log_list);
3950 if (item == NULL) {
3951 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003952 PyErr_SetString(PyExc_MemoryError,
3953 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003954 list = NULL;
3955 break;
3956 }
3957 PyList_Append(list, item);
3958 Py_DECREF(item);
3959 }
3960 free(log_list_start);
3961 }
3962 return list;
3963}
3964
3965
3966static PyObject*
3967DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3968{
3969 int err;
3970 DB_TXN_STAT* sp;
3971 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003972 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003973
3974 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3975 return NULL;
3976 CHECK_ENV_NOT_CLOSED(self);
3977
3978 MYDB_BEGIN_ALLOW_THREADS;
3979#if (DBVER >= 40)
3980 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3981#elif (DBVER == 33)
3982 err = txn_stat(self->db_env, &sp);
3983#else
3984 err = txn_stat(self->db_env, &sp, NULL);
3985#endif
3986 MYDB_END_ALLOW_THREADS;
3987 RETURN_IF_ERR();
3988
3989 /* Turn the stat structure into a dictionary */
3990 d = PyDict_New();
3991 if (d == NULL) {
3992 free(sp);
3993 return NULL;
3994 }
3995
3996#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3997
3998 MAKE_ENTRY(time_ckp);
3999 MAKE_ENTRY(last_txnid);
4000 MAKE_ENTRY(maxtxns);
4001 MAKE_ENTRY(nactive);
4002 MAKE_ENTRY(maxnactive);
4003 MAKE_ENTRY(nbegins);
4004 MAKE_ENTRY(naborts);
4005 MAKE_ENTRY(ncommits);
4006 MAKE_ENTRY(regsize);
4007 MAKE_ENTRY(region_wait);
4008 MAKE_ENTRY(region_nowait);
4009
4010#undef MAKE_ENTRY
4011 free(sp);
4012 return d;
4013}
4014
4015
4016static PyObject*
4017DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4018{
4019 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004020 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004021
4022 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4023 return NULL;
4024 CHECK_ENV_NOT_CLOSED(self);
4025
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004026 if (self->moduleFlags.getReturnsNone)
4027 ++oldValue;
4028 if (self->moduleFlags.cursorSetReturnsNone)
4029 ++oldValue;
4030 self->moduleFlags.getReturnsNone = (flags >= 1);
4031 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004032 return PyInt_FromLong(oldValue);
4033}
4034
4035
4036/* --------------------------------------------------------------------- */
4037/* DBTxn methods */
4038
4039
4040static PyObject*
4041DBTxn_commit(DBTxnObject* self, PyObject* args)
4042{
4043 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004044 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004045
4046 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4047 return NULL;
4048
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004049 if (!self->txn) {
4050 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4051 "DBTxn must not be used after txn_commit or txn_abort"));
4052 return NULL;
4053 }
4054 txn = self->txn;
4055 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004056 MYDB_BEGIN_ALLOW_THREADS;
4057#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004058 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004059#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004060 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004061#endif
4062 MYDB_END_ALLOW_THREADS;
4063 RETURN_IF_ERR();
4064 RETURN_NONE();
4065}
4066
4067static PyObject*
4068DBTxn_prepare(DBTxnObject* self, PyObject* args)
4069{
4070#if (DBVER >= 33)
4071 int err;
4072 char* gid=NULL;
4073 int gid_size=0;
4074
4075 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4076 return NULL;
4077
4078 if (gid_size != DB_XIDDATASIZE) {
4079 PyErr_SetString(PyExc_TypeError,
4080 "gid must be DB_XIDDATASIZE bytes long");
4081 return NULL;
4082 }
4083
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004084 if (!self->txn) {
4085 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4086 "DBTxn must not be used after txn_commit or txn_abort"));
4087 return NULL;
4088 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004089 MYDB_BEGIN_ALLOW_THREADS;
4090#if (DBVER >= 40)
4091 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4092#else
4093 err = txn_prepare(self->txn, (u_int8_t*)gid);
4094#endif
4095 MYDB_END_ALLOW_THREADS;
4096 RETURN_IF_ERR();
4097 RETURN_NONE();
4098#else
4099 int err;
4100
4101 if (!PyArg_ParseTuple(args, ":prepare"))
4102 return NULL;
4103
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004104 if (!self->txn) {
4105 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4106 "DBTxn must not be used after txn_commit or txn_abort"));
4107 return NULL;
4108 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = txn_prepare(self->txn);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114#endif
4115}
4116
4117
4118static PyObject*
4119DBTxn_abort(DBTxnObject* self, PyObject* args)
4120{
4121 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004122 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004123
4124 if (!PyArg_ParseTuple(args, ":abort"))
4125 return NULL;
4126
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004127 if (!self->txn) {
4128 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4129 "DBTxn must not be used after txn_commit or txn_abort"));
4130 return NULL;
4131 }
4132 txn = self->txn;
4133 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004134 MYDB_BEGIN_ALLOW_THREADS;
4135#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004136 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004137#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004138 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004139#endif
4140 MYDB_END_ALLOW_THREADS;
4141 RETURN_IF_ERR();
4142 RETURN_NONE();
4143}
4144
4145
4146static PyObject*
4147DBTxn_id(DBTxnObject* self, PyObject* args)
4148{
4149 int id;
4150
4151 if (!PyArg_ParseTuple(args, ":id"))
4152 return NULL;
4153
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004154 if (!self->txn) {
4155 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4156 "DBTxn must not be used after txn_commit or txn_abort"));
4157 return NULL;
4158 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004159 MYDB_BEGIN_ALLOW_THREADS;
4160#if (DBVER >= 40)
4161 id = self->txn->id(self->txn);
4162#else
4163 id = txn_id(self->txn);
4164#endif
4165 MYDB_END_ALLOW_THREADS;
4166 return PyInt_FromLong(id);
4167}
4168
4169/* --------------------------------------------------------------------- */
4170/* Method definition tables and type objects */
4171
4172static PyMethodDef DB_methods[] = {
4173 {"append", (PyCFunction)DB_append, METH_VARARGS},
4174#if (DBVER >= 33)
4175 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4176#endif
4177 {"close", (PyCFunction)DB_close, METH_VARARGS},
4178#if (DBVER >= 32)
4179 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4180 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4181#endif
4182 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4183 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4184 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4185 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4186 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4187 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4188 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4189 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4190 {"join", (PyCFunction)DB_join, METH_VARARGS},
4191 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4192 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4193 {"items", (PyCFunction)DB_items, METH_VARARGS},
4194 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4195 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4196 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4197 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4198 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4199 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4200 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004201#if (DBVER >= 41)
4202 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4203#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004204 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4205 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4206 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4207 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4208 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4209 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4210 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4211 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4212 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4213#if (DBVER >= 32)
4214 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4215#endif
4216 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4217 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4218#if (DBVER >= 33)
4219 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4220#endif
4221 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4222 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4223 {"values", (PyCFunction)DB_values, METH_VARARGS},
4224 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4225 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4226 {NULL, NULL} /* sentinel */
4227};
4228
4229
4230static PyMappingMethods DB_mapping = {
4231 (inquiry)DB_length, /*mp_length*/
4232 (binaryfunc)DB_subscript, /*mp_subscript*/
4233 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4234};
4235
4236
4237static PyMethodDef DBCursor_methods[] = {
4238 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4239 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4240 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4241 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4242 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4243 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4244 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4245 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4246 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4247 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4248 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4249 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4250 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4251 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4252 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004253 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004254 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004255 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4256 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4257 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4258 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4259 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4260 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4261 {NULL, NULL} /* sentinel */
4262};
4263
4264
4265static PyMethodDef DBEnv_methods[] = {
4266 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4267 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4268 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004269#if (DBVER >= 41)
4270 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4271 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4272 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4273#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004274#if (DBVER >= 40)
4275 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4276#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004277 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004278 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4279 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4280#if (DBVER >= 32)
4281 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4282#endif
4283 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4284 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4285 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4286 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4287 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4288#if (DBVER >= 32)
4289 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4290 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4291 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4292#endif
4293 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4294 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4295 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4296 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4297 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4298 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4299 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4300 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4301 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4302 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4303 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4304 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4305 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4306 {NULL, NULL} /* sentinel */
4307};
4308
4309
4310static PyMethodDef DBTxn_methods[] = {
4311 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4312 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4313 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4314 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4315 {NULL, NULL} /* sentinel */
4316};
4317
4318
4319static PyObject*
4320DB_getattr(DBObject* self, char *name)
4321{
4322 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4323}
4324
4325
4326static PyObject*
4327DBEnv_getattr(DBEnvObject* self, char *name)
4328{
4329 if (!strcmp(name, "db_home")) {
4330 CHECK_ENV_NOT_CLOSED(self);
4331 if (self->db_env->db_home == NULL) {
4332 RETURN_NONE();
4333 }
4334 return PyString_FromString(self->db_env->db_home);
4335 }
4336
4337 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4338}
4339
4340
4341static PyObject*
4342DBCursor_getattr(DBCursorObject* self, char *name)
4343{
4344 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4345}
4346
4347static PyObject*
4348DBTxn_getattr(DBTxnObject* self, char *name)
4349{
4350 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4351}
4352
4353static PyObject*
4354DBLock_getattr(DBLockObject* self, char *name)
4355{
4356 return NULL;
4357}
4358
4359statichere PyTypeObject DB_Type = {
4360 PyObject_HEAD_INIT(NULL)
4361 0, /*ob_size*/
4362 "DB", /*tp_name*/
4363 sizeof(DBObject), /*tp_basicsize*/
4364 0, /*tp_itemsize*/
4365 /* methods */
4366 (destructor)DB_dealloc, /*tp_dealloc*/
4367 0, /*tp_print*/
4368 (getattrfunc)DB_getattr, /*tp_getattr*/
4369 0, /*tp_setattr*/
4370 0, /*tp_compare*/
4371 0, /*tp_repr*/
4372 0, /*tp_as_number*/
4373 0, /*tp_as_sequence*/
4374 &DB_mapping,/*tp_as_mapping*/
4375 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004376#ifdef HAVE_WEAKREF
4377 0, /* tp_call */
4378 0, /* tp_str */
4379 0, /* tp_getattro */
4380 0, /* tp_setattro */
4381 0, /* tp_as_buffer */
4382 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4383 0, /* tp_doc */
4384 0, /* tp_traverse */
4385 0, /* tp_clear */
4386 0, /* tp_richcompare */
4387 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4388#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004389};
4390
4391
4392statichere PyTypeObject DBCursor_Type = {
4393 PyObject_HEAD_INIT(NULL)
4394 0, /*ob_size*/
4395 "DBCursor", /*tp_name*/
4396 sizeof(DBCursorObject), /*tp_basicsize*/
4397 0, /*tp_itemsize*/
4398 /* methods */
4399 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4400 0, /*tp_print*/
4401 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4402 0, /*tp_setattr*/
4403 0, /*tp_compare*/
4404 0, /*tp_repr*/
4405 0, /*tp_as_number*/
4406 0, /*tp_as_sequence*/
4407 0, /*tp_as_mapping*/
4408 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004409#ifdef HAVE_WEAKREF
4410 0, /* tp_call */
4411 0, /* tp_str */
4412 0, /* tp_getattro */
4413 0, /* tp_setattro */
4414 0, /* tp_as_buffer */
4415 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4416 0, /* tp_doc */
4417 0, /* tp_traverse */
4418 0, /* tp_clear */
4419 0, /* tp_richcompare */
4420 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4421#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004422};
4423
4424
4425statichere PyTypeObject DBEnv_Type = {
4426 PyObject_HEAD_INIT(NULL)
4427 0, /*ob_size*/
4428 "DBEnv", /*tp_name*/
4429 sizeof(DBEnvObject), /*tp_basicsize*/
4430 0, /*tp_itemsize*/
4431 /* methods */
4432 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4433 0, /*tp_print*/
4434 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4435 0, /*tp_setattr*/
4436 0, /*tp_compare*/
4437 0, /*tp_repr*/
4438 0, /*tp_as_number*/
4439 0, /*tp_as_sequence*/
4440 0, /*tp_as_mapping*/
4441 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004442#ifdef HAVE_WEAKREF
4443 0, /* tp_call */
4444 0, /* tp_str */
4445 0, /* tp_getattro */
4446 0, /* tp_setattro */
4447 0, /* tp_as_buffer */
4448 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4449 0, /* tp_doc */
4450 0, /* tp_traverse */
4451 0, /* tp_clear */
4452 0, /* tp_richcompare */
4453 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4454#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004455};
4456
4457statichere PyTypeObject DBTxn_Type = {
4458 PyObject_HEAD_INIT(NULL)
4459 0, /*ob_size*/
4460 "DBTxn", /*tp_name*/
4461 sizeof(DBTxnObject), /*tp_basicsize*/
4462 0, /*tp_itemsize*/
4463 /* methods */
4464 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4465 0, /*tp_print*/
4466 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4467 0, /*tp_setattr*/
4468 0, /*tp_compare*/
4469 0, /*tp_repr*/
4470 0, /*tp_as_number*/
4471 0, /*tp_as_sequence*/
4472 0, /*tp_as_mapping*/
4473 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004474#ifdef HAVE_WEAKREF
4475 0, /* tp_call */
4476 0, /* tp_str */
4477 0, /* tp_getattro */
4478 0, /* tp_setattro */
4479 0, /* tp_as_buffer */
4480 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4481 0, /* tp_doc */
4482 0, /* tp_traverse */
4483 0, /* tp_clear */
4484 0, /* tp_richcompare */
4485 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4486#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004487};
4488
4489
4490statichere PyTypeObject DBLock_Type = {
4491 PyObject_HEAD_INIT(NULL)
4492 0, /*ob_size*/
4493 "DBLock", /*tp_name*/
4494 sizeof(DBLockObject), /*tp_basicsize*/
4495 0, /*tp_itemsize*/
4496 /* methods */
4497 (destructor)DBLock_dealloc, /*tp_dealloc*/
4498 0, /*tp_print*/
4499 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4500 0, /*tp_setattr*/
4501 0, /*tp_compare*/
4502 0, /*tp_repr*/
4503 0, /*tp_as_number*/
4504 0, /*tp_as_sequence*/
4505 0, /*tp_as_mapping*/
4506 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004507#ifdef HAVE_WEAKREF
4508 0, /* tp_call */
4509 0, /* tp_str */
4510 0, /* tp_getattro */
4511 0, /* tp_setattro */
4512 0, /* tp_as_buffer */
4513 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4514 0, /* tp_doc */
4515 0, /* tp_traverse */
4516 0, /* tp_clear */
4517 0, /* tp_richcompare */
4518 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4519#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004520};
4521
4522
4523/* --------------------------------------------------------------------- */
4524/* Module-level functions */
4525
4526static PyObject*
4527DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4528{
4529 PyObject* dbenvobj = NULL;
4530 int flags = 0;
4531 char* kwnames[] = { "dbEnv", "flags", NULL};
4532
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004533 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4534 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004535 return NULL;
4536 if (dbenvobj == Py_None)
4537 dbenvobj = NULL;
4538 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4539 makeTypeError("DBEnv", dbenvobj);
4540 return NULL;
4541 }
4542
4543 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4544}
4545
4546
4547static PyObject*
4548DBEnv_construct(PyObject* self, PyObject* args)
4549{
4550 int flags = 0;
4551 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4552 return (PyObject* )newDBEnvObject(flags);
4553}
4554
4555
4556static char bsddb_version_doc[] =
4557"Returns a tuple of major, minor, and patch release numbers of the\n\
4558underlying DB library.";
4559
4560static PyObject*
4561bsddb_version(PyObject* self, PyObject* args)
4562{
4563 int major, minor, patch;
4564
4565 if (!PyArg_ParseTuple(args, ":version"))
4566 return NULL;
4567 db_version(&major, &minor, &patch);
4568 return Py_BuildValue("(iii)", major, minor, patch);
4569}
4570
4571
4572/* List of functions defined in the module */
4573
4574static PyMethodDef bsddb_methods[] = {
4575 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4576 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4577 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4578 {NULL, NULL} /* sentinel */
4579};
4580
4581
4582/* --------------------------------------------------------------------- */
4583/* Module initialization */
4584
4585
4586/* Convenience routine to export an integer value.
4587 * Errors are silently ignored, for better or for worse...
4588 */
4589#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4590
Gregory P. Smith41631e82003-09-21 00:08:14 +00004591#define MODULE_NAME_MAX_LEN 11
4592static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593
4594DL_EXPORT(void) init_bsddb(void)
4595{
4596 PyObject* m;
4597 PyObject* d;
4598 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4599 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4600 PyObject* cvsid_s = PyString_FromString( rcs_id );
4601
4602 /* Initialize the type of the new type objects here; doing it here
4603 is required for portability to Windows without requiring C++. */
4604 DB_Type.ob_type = &PyType_Type;
4605 DBCursor_Type.ob_type = &PyType_Type;
4606 DBEnv_Type.ob_type = &PyType_Type;
4607 DBTxn_Type.ob_type = &PyType_Type;
4608 DBLock_Type.ob_type = &PyType_Type;
4609
4610
Mark Hammonda69d4092003-04-22 23:13:27 +00004611#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004613 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614#endif
4615
4616 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004617 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004618
4619 /* Add some symbolic constants to the module */
4620 d = PyModule_GetDict(m);
4621 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4622 PyDict_SetItemString(d, "cvsid", cvsid_s);
4623 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4624 Py_DECREF(pybsddb_version_s);
4625 pybsddb_version_s = NULL;
4626 Py_DECREF(cvsid_s);
4627 cvsid_s = NULL;
4628 Py_DECREF(db_version_s);
4629 db_version_s = NULL;
4630
4631 ADD_INT(d, DB_VERSION_MAJOR);
4632 ADD_INT(d, DB_VERSION_MINOR);
4633 ADD_INT(d, DB_VERSION_PATCH);
4634
4635 ADD_INT(d, DB_MAX_PAGES);
4636 ADD_INT(d, DB_MAX_RECORDS);
4637
Gregory P. Smith41631e82003-09-21 00:08:14 +00004638#if (DBVER >= 42)
4639 ADD_INT(d, DB_RPCCLIENT);
4640#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004641 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004642 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4643 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4644#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004645 ADD_INT(d, DB_XA_CREATE);
4646
4647 ADD_INT(d, DB_CREATE);
4648 ADD_INT(d, DB_NOMMAP);
4649 ADD_INT(d, DB_THREAD);
4650
4651 ADD_INT(d, DB_FORCE);
4652 ADD_INT(d, DB_INIT_CDB);
4653 ADD_INT(d, DB_INIT_LOCK);
4654 ADD_INT(d, DB_INIT_LOG);
4655 ADD_INT(d, DB_INIT_MPOOL);
4656 ADD_INT(d, DB_INIT_TXN);
4657#if (DBVER >= 32)
4658 ADD_INT(d, DB_JOINENV);
4659#endif
4660
4661 ADD_INT(d, DB_RECOVER);
4662 ADD_INT(d, DB_RECOVER_FATAL);
4663 ADD_INT(d, DB_TXN_NOSYNC);
4664 ADD_INT(d, DB_USE_ENVIRON);
4665 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4666
4667 ADD_INT(d, DB_LOCKDOWN);
4668 ADD_INT(d, DB_PRIVATE);
4669 ADD_INT(d, DB_SYSTEM_MEM);
4670
4671 ADD_INT(d, DB_TXN_SYNC);
4672 ADD_INT(d, DB_TXN_NOWAIT);
4673
4674 ADD_INT(d, DB_EXCL);
4675 ADD_INT(d, DB_FCNTL_LOCKING);
4676 ADD_INT(d, DB_ODDFILESIZE);
4677 ADD_INT(d, DB_RDWRMASTER);
4678 ADD_INT(d, DB_RDONLY);
4679 ADD_INT(d, DB_TRUNCATE);
4680#if (DBVER >= 32)
4681 ADD_INT(d, DB_EXTENT);
4682 ADD_INT(d, DB_CDB_ALLDB);
4683 ADD_INT(d, DB_VERIFY);
4684#endif
4685 ADD_INT(d, DB_UPGRADE);
4686
4687 ADD_INT(d, DB_AGGRESSIVE);
4688 ADD_INT(d, DB_NOORDERCHK);
4689 ADD_INT(d, DB_ORDERCHKONLY);
4690 ADD_INT(d, DB_PR_PAGE);
4691#if ! (DBVER >= 33)
4692 ADD_INT(d, DB_VRFY_FLAGMASK);
4693 ADD_INT(d, DB_PR_HEADERS);
4694#endif
4695 ADD_INT(d, DB_PR_RECOVERYTEST);
4696 ADD_INT(d, DB_SALVAGE);
4697
4698 ADD_INT(d, DB_LOCK_NORUN);
4699 ADD_INT(d, DB_LOCK_DEFAULT);
4700 ADD_INT(d, DB_LOCK_OLDEST);
4701 ADD_INT(d, DB_LOCK_RANDOM);
4702 ADD_INT(d, DB_LOCK_YOUNGEST);
4703#if (DBVER >= 33)
4704 ADD_INT(d, DB_LOCK_MAXLOCKS);
4705 ADD_INT(d, DB_LOCK_MINLOCKS);
4706 ADD_INT(d, DB_LOCK_MINWRITE);
4707#endif
4708
4709
4710#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004711 /* docs say to use zero instead */
4712 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004713#else
4714 ADD_INT(d, DB_LOCK_CONFLICT);
4715#endif
4716
4717 ADD_INT(d, DB_LOCK_DUMP);
4718 ADD_INT(d, DB_LOCK_GET);
4719 ADD_INT(d, DB_LOCK_INHERIT);
4720 ADD_INT(d, DB_LOCK_PUT);
4721 ADD_INT(d, DB_LOCK_PUT_ALL);
4722 ADD_INT(d, DB_LOCK_PUT_OBJ);
4723
4724 ADD_INT(d, DB_LOCK_NG);
4725 ADD_INT(d, DB_LOCK_READ);
4726 ADD_INT(d, DB_LOCK_WRITE);
4727 ADD_INT(d, DB_LOCK_NOWAIT);
4728#if (DBVER >= 32)
4729 ADD_INT(d, DB_LOCK_WAIT);
4730#endif
4731 ADD_INT(d, DB_LOCK_IWRITE);
4732 ADD_INT(d, DB_LOCK_IREAD);
4733 ADD_INT(d, DB_LOCK_IWR);
4734#if (DBVER >= 33)
4735 ADD_INT(d, DB_LOCK_DIRTY);
4736 ADD_INT(d, DB_LOCK_WWRITE);
4737#endif
4738
4739 ADD_INT(d, DB_LOCK_RECORD);
4740 ADD_INT(d, DB_LOCK_UPGRADE);
4741#if (DBVER >= 32)
4742 ADD_INT(d, DB_LOCK_SWITCH);
4743#endif
4744#if (DBVER >= 33)
4745 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4746#endif
4747
4748 ADD_INT(d, DB_LOCK_NOWAIT);
4749 ADD_INT(d, DB_LOCK_RECORD);
4750 ADD_INT(d, DB_LOCK_UPGRADE);
4751
4752#if (DBVER >= 33)
4753 ADD_INT(d, DB_LSTAT_ABORTED);
4754 ADD_INT(d, DB_LSTAT_ERR);
4755 ADD_INT(d, DB_LSTAT_FREE);
4756 ADD_INT(d, DB_LSTAT_HELD);
4757#if (DBVER == 33)
4758 ADD_INT(d, DB_LSTAT_NOGRANT);
4759#endif
4760 ADD_INT(d, DB_LSTAT_PENDING);
4761 ADD_INT(d, DB_LSTAT_WAITING);
4762#endif
4763
4764 ADD_INT(d, DB_ARCH_ABS);
4765 ADD_INT(d, DB_ARCH_DATA);
4766 ADD_INT(d, DB_ARCH_LOG);
4767
4768 ADD_INT(d, DB_BTREE);
4769 ADD_INT(d, DB_HASH);
4770 ADD_INT(d, DB_RECNO);
4771 ADD_INT(d, DB_QUEUE);
4772 ADD_INT(d, DB_UNKNOWN);
4773
4774 ADD_INT(d, DB_DUP);
4775 ADD_INT(d, DB_DUPSORT);
4776 ADD_INT(d, DB_RECNUM);
4777 ADD_INT(d, DB_RENUMBER);
4778 ADD_INT(d, DB_REVSPLITOFF);
4779 ADD_INT(d, DB_SNAPSHOT);
4780
4781 ADD_INT(d, DB_JOIN_NOSORT);
4782
4783 ADD_INT(d, DB_AFTER);
4784 ADD_INT(d, DB_APPEND);
4785 ADD_INT(d, DB_BEFORE);
4786 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004787#if (DBVER >= 41)
4788 _addIntToDict(d, "DB_CHECKPOINT", 0);
4789#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004790 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004791 ADD_INT(d, DB_CURLSN);
4792#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004793#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004794 ADD_INT(d, DB_COMMIT);
4795#endif
4796 ADD_INT(d, DB_CONSUME);
4797#if (DBVER >= 32)
4798 ADD_INT(d, DB_CONSUME_WAIT);
4799#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004800 ADD_INT(d, DB_CURRENT);
4801#if (DBVER >= 33)
4802 ADD_INT(d, DB_FAST_STAT);
4803#endif
4804 ADD_INT(d, DB_FIRST);
4805 ADD_INT(d, DB_FLUSH);
4806 ADD_INT(d, DB_GET_BOTH);
4807 ADD_INT(d, DB_GET_RECNO);
4808 ADD_INT(d, DB_JOIN_ITEM);
4809 ADD_INT(d, DB_KEYFIRST);
4810 ADD_INT(d, DB_KEYLAST);
4811 ADD_INT(d, DB_LAST);
4812 ADD_INT(d, DB_NEXT);
4813 ADD_INT(d, DB_NEXT_DUP);
4814 ADD_INT(d, DB_NEXT_NODUP);
4815 ADD_INT(d, DB_NODUPDATA);
4816 ADD_INT(d, DB_NOOVERWRITE);
4817 ADD_INT(d, DB_NOSYNC);
4818 ADD_INT(d, DB_POSITION);
4819 ADD_INT(d, DB_PREV);
4820 ADD_INT(d, DB_PREV_NODUP);
4821 ADD_INT(d, DB_RECORDCOUNT);
4822 ADD_INT(d, DB_SET);
4823 ADD_INT(d, DB_SET_RANGE);
4824 ADD_INT(d, DB_SET_RECNO);
4825 ADD_INT(d, DB_WRITECURSOR);
4826
4827 ADD_INT(d, DB_OPFLAGS_MASK);
4828 ADD_INT(d, DB_RMW);
4829#if (DBVER >= 33)
4830 ADD_INT(d, DB_DIRTY_READ);
4831 ADD_INT(d, DB_MULTIPLE);
4832 ADD_INT(d, DB_MULTIPLE_KEY);
4833#endif
4834
4835#if (DBVER >= 33)
4836 ADD_INT(d, DB_DONOTINDEX);
4837#endif
4838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004839#if (DBVER >= 41)
4840 _addIntToDict(d, "DB_INCOMPLETE", 0);
4841#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004842 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004843#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004844 ADD_INT(d, DB_KEYEMPTY);
4845 ADD_INT(d, DB_KEYEXIST);
4846 ADD_INT(d, DB_LOCK_DEADLOCK);
4847 ADD_INT(d, DB_LOCK_NOTGRANTED);
4848 ADD_INT(d, DB_NOSERVER);
4849 ADD_INT(d, DB_NOSERVER_HOME);
4850 ADD_INT(d, DB_NOSERVER_ID);
4851 ADD_INT(d, DB_NOTFOUND);
4852 ADD_INT(d, DB_OLD_VERSION);
4853 ADD_INT(d, DB_RUNRECOVERY);
4854 ADD_INT(d, DB_VERIFY_BAD);
4855#if (DBVER >= 33)
4856 ADD_INT(d, DB_PAGE_NOTFOUND);
4857 ADD_INT(d, DB_SECONDARY_BAD);
4858#endif
4859#if (DBVER >= 40)
4860 ADD_INT(d, DB_STAT_CLEAR);
4861 ADD_INT(d, DB_REGION_INIT);
4862 ADD_INT(d, DB_NOLOCKING);
4863 ADD_INT(d, DB_YIELDCPU);
4864 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4865 ADD_INT(d, DB_NOPANIC);
4866#endif
4867
Gregory P. Smith41631e82003-09-21 00:08:14 +00004868#if (DBVER >= 42)
4869 ADD_INT(d, DB_TIME_NOTGRANTED);
4870 ADD_INT(d, DB_TXN_NOT_DURABLE);
4871 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4872 ADD_INT(d, DB_LOG_AUTOREMOVE);
4873 ADD_INT(d, DB_DIRECT_LOG);
4874 ADD_INT(d, DB_DIRECT_DB);
4875 ADD_INT(d, DB_INIT_REP);
4876 ADD_INT(d, DB_ENCRYPT);
4877 ADD_INT(d, DB_CHKSUM);
4878#endif
4879
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004880#if (DBVER >= 41)
4881 ADD_INT(d, DB_ENCRYPT_AES);
4882 ADD_INT(d, DB_AUTO_COMMIT);
4883#else
4884 /* allow berkeleydb 4.1 aware apps to run on older versions */
4885 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4886#endif
4887
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004888 ADD_INT(d, EINVAL);
4889 ADD_INT(d, EACCES);
4890 ADD_INT(d, ENOSPC);
4891 ADD_INT(d, ENOMEM);
4892 ADD_INT(d, EAGAIN);
4893 ADD_INT(d, EBUSY);
4894 ADD_INT(d, EEXIST);
4895 ADD_INT(d, ENOENT);
4896 ADD_INT(d, EPERM);
4897
Barry Warsaw1baa9822003-03-31 19:51:29 +00004898#if (DBVER >= 40)
4899 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4900 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4901#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004902
4903 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004904 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004905 PyDict_SetItemString(d, "DBError", DBError);
4906
4907 /* Some magic to make DBNotFoundError derive from both DBError and
4908 KeyError, since the API only supports using one base class. */
4909 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4910 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4911 Py_file_input, d, d);
4912 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4913 PyDict_DelItemString(d, "KeyError");
4914
4915
4916 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004917#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004918 PyDict_SetItemString(d, #name, name)
4919
4920#if !INCOMPLETE_IS_WARNING
4921 MAKE_EX(DBIncompleteError);
4922#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00004923 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004924 MAKE_EX(DBKeyEmptyError);
4925 MAKE_EX(DBKeyExistError);
4926 MAKE_EX(DBLockDeadlockError);
4927 MAKE_EX(DBLockNotGrantedError);
4928 MAKE_EX(DBOldVersionError);
4929 MAKE_EX(DBRunRecoveryError);
4930 MAKE_EX(DBVerifyBadError);
4931 MAKE_EX(DBNoServerError);
4932 MAKE_EX(DBNoServerHomeError);
4933 MAKE_EX(DBNoServerIDError);
4934#if (DBVER >= 33)
4935 MAKE_EX(DBPageNotFoundError);
4936 MAKE_EX(DBSecondaryBadError);
4937#endif
4938
4939 MAKE_EX(DBInvalidArgError);
4940 MAKE_EX(DBAccessError);
4941 MAKE_EX(DBNoSpaceError);
4942 MAKE_EX(DBNoMemoryError);
4943 MAKE_EX(DBAgainError);
4944 MAKE_EX(DBBusyError);
4945 MAKE_EX(DBFileExistsError);
4946 MAKE_EX(DBNoSuchFileError);
4947 MAKE_EX(DBPermissionsError);
4948
4949#undef MAKE_EX
4950
4951 /* Check for errors */
4952 if (PyErr_Occurred()) {
4953 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004954 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004955 }
4956}
Gregory P. Smith41631e82003-09-21 00:08:14 +00004957
4958/* allow this module to be named _pybsddb so that it can be installed
4959 * and imported on top of python >= 2.3 that includes its own older
4960 * copy of the library named _bsddb without importing the old version. */
4961DL_EXPORT(void) init_pybsddb(void)
4962{
4963 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
4964 init_bsddb();
4965}