blob: b7f651861f016974fbd677cbf119d9e01dbe8703 [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. Smith19699a92004-06-28 04:06:49 +0000100#define PY_BSDDB_VERSION "4.2.8"
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
Gregory P. Smith19699a92004-06-28 04:06:49 +00001466static PyObject*
1467DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1468{
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, pkey, data;
1477 DB_TXN *txn = NULL;
1478 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1479
1480 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1481 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1482 &doff))
1483 return NULL;
1484
1485 CHECK_DB_NOT_CLOSED(self);
1486 if (!make_key_dbt(self, keyobj, &key, &flags))
1487 return NULL;
1488 if (!checkTxnObj(txnobj, &txn)) {
1489 FREE_DBT(key);
1490 return NULL;
1491 }
1492
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
1495 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1496 data.flags = DB_DBT_MALLOC;
1497 }
1498 if (!add_partial_dbt(&data, dlen, doff)) {
1499 FREE_DBT(key);
1500 return NULL;
1501 }
1502
1503 CLEAR_DBT(pkey);
1504 pkey.flags = DB_DBT_MALLOC;
1505
1506 MYDB_BEGIN_ALLOW_THREADS;
1507 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1508 MYDB_END_ALLOW_THREADS;
1509
1510 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1511 err = 0;
1512 Py_INCREF(dfltobj);
1513 retval = dfltobj;
1514 }
1515 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1516 err = 0;
1517 Py_INCREF(Py_None);
1518 retval = Py_None;
1519 }
1520 else if (!err) {
1521 PyObject *pkeyObj;
1522 PyObject *dataObj;
1523 dataObj = PyString_FromStringAndSize(data.data, data.size);
1524
1525 if (self->primaryDBType == DB_RECNO ||
1526 self->primaryDBType == DB_QUEUE)
1527 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1528 else
1529 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1530
1531 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1532 {
1533 PyObject *keyObj;
1534 int type = _DB_get_type(self);
1535 if (type == DB_RECNO || type == DB_QUEUE)
1536 keyObj = PyInt_FromLong(*(long *)key.data);
1537 else
1538 keyObj = PyString_FromStringAndSize(key.data, key.size);
1539 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1540 }
1541 else /* return just the pkey and data */
1542 {
1543 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1544 }
1545 FREE_DBT(pkey);
1546 FREE_DBT(data);
1547 }
1548 FREE_DBT(key);
1549
1550 RETURN_IF_ERR();
1551 return retval;
1552}
1553
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554
1555/* Return size of entry */
1556static PyObject*
1557DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1558{
1559 int err, flags=0;
1560 PyObject* txnobj = NULL;
1561 PyObject* keyobj;
1562 PyObject* retval = NULL;
1563 DBT key, data;
1564 DB_TXN *txn = NULL;
1565 char* kwnames[] = { "key", "txn", NULL };
1566
1567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1568 &keyobj, &txnobj))
1569 return NULL;
1570 CHECK_DB_NOT_CLOSED(self);
1571 if (!make_key_dbt(self, keyobj, &key, &flags))
1572 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001573 if (!checkTxnObj(txnobj, &txn)) {
1574 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001575 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001577 CLEAR_DBT(data);
1578
1579 /* We don't allocate any memory, forcing a ENOMEM error and thus
1580 getting the record size. */
1581 data.flags = DB_DBT_USERMEM;
1582 data.ulen = 0;
1583 MYDB_BEGIN_ALLOW_THREADS;
1584 err = self->db->get(self->db, txn, &key, &data, flags);
1585 MYDB_END_ALLOW_THREADS;
1586 if (err == ENOMEM) {
1587 retval = PyInt_FromLong((long)data.size);
1588 err = 0;
1589 }
1590
1591 FREE_DBT(key);
1592 FREE_DBT(data);
1593 RETURN_IF_ERR();
1594 return retval;
1595}
1596
1597
1598static PyObject*
1599DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1600{
1601 int err, flags=0;
1602 PyObject* txnobj = NULL;
1603 PyObject* keyobj;
1604 PyObject* dataobj;
1605 PyObject* retval = NULL;
1606 DBT key, data;
1607 DB_TXN *txn = NULL;
1608 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1609
1610
1611 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1612 &keyobj, &dataobj, &txnobj, &flags))
1613 return NULL;
1614
1615 CHECK_DB_NOT_CLOSED(self);
1616 if (!make_key_dbt(self, keyobj, &key, NULL))
1617 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001618 if ( !make_dbt(dataobj, &data) ||
1619 !checkTxnObj(txnobj, &txn) )
1620 {
1621 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001622 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001623 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001624
1625 flags |= DB_GET_BOTH;
1626
1627 if (CHECK_DBFLAG(self, DB_THREAD)) {
1628 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1629 data.flags = DB_DBT_MALLOC;
1630 /* TODO: Is this flag needed? We're passing a data object that should
1631 match what's in the DB, so there should be no need to malloc.
1632 We run the risk of freeing something twice! Check this. */
1633 }
1634
1635 MYDB_BEGIN_ALLOW_THREADS;
1636 err = self->db->get(self->db, txn, &key, &data, flags);
1637 MYDB_END_ALLOW_THREADS;
1638
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001639 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 err = 0;
1641 Py_INCREF(Py_None);
1642 retval = Py_None;
1643 }
1644 else if (!err) {
1645 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1646 FREE_DBT(data); /* Only if retrieval was successful */
1647 }
1648
1649 FREE_DBT(key);
1650 RETURN_IF_ERR();
1651 return retval;
1652}
1653
1654
1655static PyObject*
1656DB_get_byteswapped(DBObject* self, PyObject* args)
1657{
1658#if (DBVER >= 33)
1659 int err = 0;
1660#endif
1661 int retval = -1;
1662
1663 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1664 return NULL;
1665 CHECK_DB_NOT_CLOSED(self);
1666
1667#if (DBVER >= 33)
1668 MYDB_BEGIN_ALLOW_THREADS;
1669 err = self->db->get_byteswapped(self->db, &retval);
1670 MYDB_END_ALLOW_THREADS;
1671 RETURN_IF_ERR();
1672#else
1673 MYDB_BEGIN_ALLOW_THREADS;
1674 retval = self->db->get_byteswapped(self->db);
1675 MYDB_END_ALLOW_THREADS;
1676#endif
1677 return PyInt_FromLong(retval);
1678}
1679
1680
1681static PyObject*
1682DB_get_type(DBObject* self, PyObject* args)
1683{
1684 int type;
1685
1686 if (!PyArg_ParseTuple(args,":get_type"))
1687 return NULL;
1688 CHECK_DB_NOT_CLOSED(self);
1689
1690 MYDB_BEGIN_ALLOW_THREADS;
1691 type = _DB_get_type(self);
1692 MYDB_END_ALLOW_THREADS;
1693 if (type == -1)
1694 return NULL;
1695 return PyInt_FromLong(type);
1696}
1697
1698
1699static PyObject*
1700DB_join(DBObject* self, PyObject* args)
1701{
1702 int err, flags=0;
1703 int length, x;
1704 PyObject* cursorsObj;
1705 DBC** cursors;
1706 DBC* dbc;
1707
1708
1709 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1710 return NULL;
1711
1712 CHECK_DB_NOT_CLOSED(self);
1713
1714 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001715 PyErr_SetString(PyExc_TypeError,
1716 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001717 return NULL;
1718 }
1719
1720 length = PyObject_Length(cursorsObj);
1721 cursors = malloc((length+1) * sizeof(DBC*));
1722 cursors[length] = NULL;
1723 for (x=0; x<length; x++) {
1724 PyObject* item = PySequence_GetItem(cursorsObj, x);
1725 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001726 PyErr_SetString(PyExc_TypeError,
1727 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001728 free(cursors);
1729 return NULL;
1730 }
1731 cursors[x] = ((DBCursorObject*)item)->dbc;
1732 }
1733
1734 MYDB_BEGIN_ALLOW_THREADS;
1735 err = self->db->join(self->db, cursors, &dbc, flags);
1736 MYDB_END_ALLOW_THREADS;
1737 free(cursors);
1738 RETURN_IF_ERR();
1739
Gregory P. Smith7441e652003-11-03 21:35:31 +00001740 /* FIXME: this is a buggy interface. The returned cursor
1741 contains internal references to the passed in cursors
1742 but does not hold python references to them or prevent
1743 them from being closed prematurely. This can cause
1744 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001745 return (PyObject*) newDBCursorObject(dbc, self);
1746}
1747
1748
1749static PyObject*
1750DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1751{
1752 int err, flags=0;
1753 PyObject* txnobj = NULL;
1754 PyObject* keyobj;
1755 DBT key;
1756 DB_TXN *txn = NULL;
1757 DB_KEY_RANGE range;
1758 char* kwnames[] = { "key", "txn", "flags", NULL };
1759
1760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1761 &keyobj, &txnobj, &flags))
1762 return NULL;
1763 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001764 if (!make_dbt(keyobj, &key))
1765 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001766 return NULL;
1767 if (!checkTxnObj(txnobj, &txn))
1768 return NULL;
1769
1770 MYDB_BEGIN_ALLOW_THREADS;
1771 err = self->db->key_range(self->db, txn, &key, &range, flags);
1772 MYDB_END_ALLOW_THREADS;
1773
1774 RETURN_IF_ERR();
1775 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1776}
1777
1778
1779static PyObject*
1780DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1781{
1782 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1783 char* filename = NULL;
1784 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001785#if (DBVER >= 41)
1786 PyObject *txnobj = NULL;
1787 DB_TXN *txn = NULL;
1788 /* with dbname */
1789 char* kwnames[] = {
1790 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1791 /* without dbname */
1792 char* kwnames_basic[] = {
1793 "filename", "dbtype", "flags", "mode", "txn", NULL};
1794#else
1795 /* with dbname */
1796 char* kwnames[] = {
1797 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1798 /* without dbname */
1799 char* kwnames_basic[] = {
1800 "filename", "dbtype", "flags", "mode", NULL};
1801#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001803#if (DBVER >= 41)
1804 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1805 &filename, &dbname, &type, &flags, &mode,
1806 &txnobj))
1807#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001809 &filename, &dbname, &type, &flags,
1810 &mode))
1811#endif
1812 {
1813 PyErr_Clear();
1814 type = DB_UNKNOWN; flags = 0; mode = 0660;
1815 filename = NULL; dbname = NULL;
1816#if (DBVER >= 41)
1817 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1818 kwnames_basic,
1819 &filename, &type, &flags, &mode,
1820 &txnobj))
1821 return NULL;
1822#else
1823 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1824 kwnames_basic,
1825 &filename, &type, &flags, &mode))
1826 return NULL;
1827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 }
1829
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001830#if (DBVER >= 41)
1831 if (!checkTxnObj(txnobj, &txn)) return NULL;
1832#endif
1833
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 if (NULL == self->db) {
1835 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1836 "Cannot call open() twice for DB object"));
1837 return NULL;
1838 }
1839
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001840#if 0 && (DBVER >= 41)
1841 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1842 && (self->myenvobj->flags & DB_INIT_TXN))
1843 {
1844 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1845 * explicitly passed) but we are in a transaction ready environment:
1846 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1847 * to work on BerkeleyDB 4.1 without needing to modify their
1848 * DBEnv or DB open calls.
1849 * TODO make this behaviour of the library configurable.
1850 */
1851 flags |= DB_AUTO_COMMIT;
1852 }
1853#endif
1854
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001856#if (DBVER >= 41)
1857 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1858#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001860#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 MYDB_END_ALLOW_THREADS;
1862 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001863 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001864 self->db = NULL;
1865 return NULL;
1866 }
1867
1868 self->flags = flags;
1869 RETURN_NONE();
1870}
1871
1872
1873static PyObject*
1874DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1875{
1876 int flags=0;
1877 PyObject* txnobj = NULL;
1878 int dlen = -1;
1879 int doff = -1;
1880 PyObject* keyobj, *dataobj, *retval;
1881 DBT key, data;
1882 DB_TXN *txn = NULL;
1883 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1884
1885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1886 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1887 return NULL;
1888
1889 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001890 if (!make_key_dbt(self, keyobj, &key, NULL))
1891 return NULL;
1892 if ( !make_dbt(dataobj, &data) ||
1893 !add_partial_dbt(&data, dlen, doff) ||
1894 !checkTxnObj(txnobj, &txn) )
1895 {
1896 FREE_DBT(key);
1897 return NULL;
1898 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001899
1900 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1901 FREE_DBT(key);
1902 return NULL;
1903 }
1904
1905 if (flags & DB_APPEND)
1906 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1907 else {
1908 retval = Py_None;
1909 Py_INCREF(retval);
1910 }
1911 FREE_DBT(key);
1912 return retval;
1913}
1914
1915
1916
1917static PyObject*
1918DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1919{
1920 char* filename;
1921 char* database = NULL;
1922 int err, flags=0;
1923 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1924
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1926 &filename, &database, &flags))
1927 return NULL;
1928 CHECK_DB_NOT_CLOSED(self);
1929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001930 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001931 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 RETURN_IF_ERR();
1933 RETURN_NONE();
1934}
1935
1936
1937
1938static PyObject*
1939DB_rename(DBObject* self, PyObject* args)
1940{
1941 char* filename;
1942 char* database;
1943 char* newname;
1944 int err, flags=0;
1945
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1947 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 return NULL;
1949 CHECK_DB_NOT_CLOSED(self);
1950
1951 MYDB_BEGIN_ALLOW_THREADS;
1952 err = self->db->rename(self->db, filename, database, newname, flags);
1953 MYDB_END_ALLOW_THREADS;
1954 RETURN_IF_ERR();
1955 RETURN_NONE();
1956}
1957
1958
1959static PyObject*
1960DB_set_bt_minkey(DBObject* self, PyObject* args)
1961{
1962 int err, minkey;
1963
1964 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1965 return NULL;
1966 CHECK_DB_NOT_CLOSED(self);
1967
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->set_bt_minkey(self->db, minkey);
1970 MYDB_END_ALLOW_THREADS;
1971 RETURN_IF_ERR();
1972 RETURN_NONE();
1973}
1974
1975
1976static PyObject*
1977DB_set_cachesize(DBObject* self, PyObject* args)
1978{
1979 int err;
1980 int gbytes = 0, bytes = 0, ncache = 0;
1981
1982 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1983 &gbytes,&bytes,&ncache))
1984 return NULL;
1985 CHECK_DB_NOT_CLOSED(self);
1986
1987 MYDB_BEGIN_ALLOW_THREADS;
1988 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1989 MYDB_END_ALLOW_THREADS;
1990 RETURN_IF_ERR();
1991 RETURN_NONE();
1992}
1993
1994
1995static PyObject*
1996DB_set_flags(DBObject* self, PyObject* args)
1997{
1998 int err, flags;
1999
2000 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2001 return NULL;
2002 CHECK_DB_NOT_CLOSED(self);
2003
2004 MYDB_BEGIN_ALLOW_THREADS;
2005 err = self->db->set_flags(self->db, flags);
2006 MYDB_END_ALLOW_THREADS;
2007 RETURN_IF_ERR();
2008
2009 self->setflags |= flags;
2010 RETURN_NONE();
2011}
2012
2013
2014static PyObject*
2015DB_set_h_ffactor(DBObject* self, PyObject* args)
2016{
2017 int err, ffactor;
2018
2019 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2020 return NULL;
2021 CHECK_DB_NOT_CLOSED(self);
2022
2023 MYDB_BEGIN_ALLOW_THREADS;
2024 err = self->db->set_h_ffactor(self->db, ffactor);
2025 MYDB_END_ALLOW_THREADS;
2026 RETURN_IF_ERR();
2027 RETURN_NONE();
2028}
2029
2030
2031static PyObject*
2032DB_set_h_nelem(DBObject* self, PyObject* args)
2033{
2034 int err, nelem;
2035
2036 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2037 return NULL;
2038 CHECK_DB_NOT_CLOSED(self);
2039
2040 MYDB_BEGIN_ALLOW_THREADS;
2041 err = self->db->set_h_nelem(self->db, nelem);
2042 MYDB_END_ALLOW_THREADS;
2043 RETURN_IF_ERR();
2044 RETURN_NONE();
2045}
2046
2047
2048static PyObject*
2049DB_set_lorder(DBObject* self, PyObject* args)
2050{
2051 int err, lorder;
2052
2053 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2054 return NULL;
2055 CHECK_DB_NOT_CLOSED(self);
2056
2057 MYDB_BEGIN_ALLOW_THREADS;
2058 err = self->db->set_lorder(self->db, lorder);
2059 MYDB_END_ALLOW_THREADS;
2060 RETURN_IF_ERR();
2061 RETURN_NONE();
2062}
2063
2064
2065static PyObject*
2066DB_set_pagesize(DBObject* self, PyObject* args)
2067{
2068 int err, pagesize;
2069
2070 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2071 return NULL;
2072 CHECK_DB_NOT_CLOSED(self);
2073
2074 MYDB_BEGIN_ALLOW_THREADS;
2075 err = self->db->set_pagesize(self->db, pagesize);
2076 MYDB_END_ALLOW_THREADS;
2077 RETURN_IF_ERR();
2078 RETURN_NONE();
2079}
2080
2081
2082static PyObject*
2083DB_set_re_delim(DBObject* self, PyObject* args)
2084{
2085 int err;
2086 char delim;
2087
2088 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2089 PyErr_Clear();
2090 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2091 return NULL;
2092 }
2093
2094 CHECK_DB_NOT_CLOSED(self);
2095
2096 MYDB_BEGIN_ALLOW_THREADS;
2097 err = self->db->set_re_delim(self->db, delim);
2098 MYDB_END_ALLOW_THREADS;
2099 RETURN_IF_ERR();
2100 RETURN_NONE();
2101}
2102
2103static PyObject*
2104DB_set_re_len(DBObject* self, PyObject* args)
2105{
2106 int err, len;
2107
2108 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2109 return NULL;
2110 CHECK_DB_NOT_CLOSED(self);
2111
2112 MYDB_BEGIN_ALLOW_THREADS;
2113 err = self->db->set_re_len(self->db, len);
2114 MYDB_END_ALLOW_THREADS;
2115 RETURN_IF_ERR();
2116 RETURN_NONE();
2117}
2118
2119
2120static PyObject*
2121DB_set_re_pad(DBObject* self, PyObject* args)
2122{
2123 int err;
2124 char pad;
2125
2126 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2127 PyErr_Clear();
2128 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2129 return NULL;
2130 }
2131 CHECK_DB_NOT_CLOSED(self);
2132
2133 MYDB_BEGIN_ALLOW_THREADS;
2134 err = self->db->set_re_pad(self->db, pad);
2135 MYDB_END_ALLOW_THREADS;
2136 RETURN_IF_ERR();
2137 RETURN_NONE();
2138}
2139
2140
2141static PyObject*
2142DB_set_re_source(DBObject* self, PyObject* args)
2143{
2144 int err;
2145 char *re_source;
2146
2147 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2148 return NULL;
2149 CHECK_DB_NOT_CLOSED(self);
2150
2151 MYDB_BEGIN_ALLOW_THREADS;
2152 err = self->db->set_re_source(self->db, re_source);
2153 MYDB_END_ALLOW_THREADS;
2154 RETURN_IF_ERR();
2155 RETURN_NONE();
2156}
2157
2158
2159#if (DBVER >= 32)
2160static PyObject*
2161DB_set_q_extentsize(DBObject* self, PyObject* args)
2162{
2163 int err;
2164 int extentsize;
2165
2166 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2167 return NULL;
2168 CHECK_DB_NOT_CLOSED(self);
2169
2170 MYDB_BEGIN_ALLOW_THREADS;
2171 err = self->db->set_q_extentsize(self->db, extentsize);
2172 MYDB_END_ALLOW_THREADS;
2173 RETURN_IF_ERR();
2174 RETURN_NONE();
2175}
2176#endif
2177
2178static PyObject*
2179DB_stat(DBObject* self, PyObject* args)
2180{
2181 int err, flags = 0, type;
2182 void* sp;
2183 PyObject* d;
2184
2185
2186 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2187 return NULL;
2188 CHECK_DB_NOT_CLOSED(self);
2189
2190 MYDB_BEGIN_ALLOW_THREADS;
2191#if (DBVER >= 33)
2192 err = self->db->stat(self->db, &sp, flags);
2193#else
2194 err = self->db->stat(self->db, &sp, NULL, flags);
2195#endif
2196 MYDB_END_ALLOW_THREADS;
2197 RETURN_IF_ERR();
2198
2199 self->haveStat = 1;
2200
2201 /* Turn the stat structure into a dictionary */
2202 type = _DB_get_type(self);
2203 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2204 free(sp);
2205 return NULL;
2206 }
2207
2208#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2209#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2210#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2211
2212 switch (type) {
2213 case DB_HASH:
2214 MAKE_HASH_ENTRY(magic);
2215 MAKE_HASH_ENTRY(version);
2216 MAKE_HASH_ENTRY(nkeys);
2217 MAKE_HASH_ENTRY(ndata);
2218 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002219#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002220 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002221#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002222 MAKE_HASH_ENTRY(ffactor);
2223 MAKE_HASH_ENTRY(buckets);
2224 MAKE_HASH_ENTRY(free);
2225 MAKE_HASH_ENTRY(bfree);
2226 MAKE_HASH_ENTRY(bigpages);
2227 MAKE_HASH_ENTRY(big_bfree);
2228 MAKE_HASH_ENTRY(overflows);
2229 MAKE_HASH_ENTRY(ovfl_free);
2230 MAKE_HASH_ENTRY(dup);
2231 MAKE_HASH_ENTRY(dup_free);
2232 break;
2233
2234 case DB_BTREE:
2235 case DB_RECNO:
2236 MAKE_BT_ENTRY(magic);
2237 MAKE_BT_ENTRY(version);
2238 MAKE_BT_ENTRY(nkeys);
2239 MAKE_BT_ENTRY(ndata);
2240 MAKE_BT_ENTRY(pagesize);
2241 MAKE_BT_ENTRY(minkey);
2242 MAKE_BT_ENTRY(re_len);
2243 MAKE_BT_ENTRY(re_pad);
2244 MAKE_BT_ENTRY(levels);
2245 MAKE_BT_ENTRY(int_pg);
2246 MAKE_BT_ENTRY(leaf_pg);
2247 MAKE_BT_ENTRY(dup_pg);
2248 MAKE_BT_ENTRY(over_pg);
2249 MAKE_BT_ENTRY(free);
2250 MAKE_BT_ENTRY(int_pgfree);
2251 MAKE_BT_ENTRY(leaf_pgfree);
2252 MAKE_BT_ENTRY(dup_pgfree);
2253 MAKE_BT_ENTRY(over_pgfree);
2254 break;
2255
2256 case DB_QUEUE:
2257 MAKE_QUEUE_ENTRY(magic);
2258 MAKE_QUEUE_ENTRY(version);
2259 MAKE_QUEUE_ENTRY(nkeys);
2260 MAKE_QUEUE_ENTRY(ndata);
2261 MAKE_QUEUE_ENTRY(pagesize);
2262 MAKE_QUEUE_ENTRY(pages);
2263 MAKE_QUEUE_ENTRY(re_len);
2264 MAKE_QUEUE_ENTRY(re_pad);
2265 MAKE_QUEUE_ENTRY(pgfree);
2266#if (DBVER == 31)
2267 MAKE_QUEUE_ENTRY(start);
2268#endif
2269 MAKE_QUEUE_ENTRY(first_recno);
2270 MAKE_QUEUE_ENTRY(cur_recno);
2271 break;
2272
2273 default:
2274 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2275 Py_DECREF(d);
2276 d = NULL;
2277 }
2278
2279#undef MAKE_HASH_ENTRY
2280#undef MAKE_BT_ENTRY
2281#undef MAKE_QUEUE_ENTRY
2282
2283 free(sp);
2284 return d;
2285}
2286
2287static PyObject*
2288DB_sync(DBObject* self, PyObject* args)
2289{
2290 int err;
2291 int flags = 0;
2292
2293 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2294 return NULL;
2295 CHECK_DB_NOT_CLOSED(self);
2296
2297 MYDB_BEGIN_ALLOW_THREADS;
2298 err = self->db->sync(self->db, flags);
2299 MYDB_END_ALLOW_THREADS;
2300 RETURN_IF_ERR();
2301 RETURN_NONE();
2302}
2303
2304
2305#if (DBVER >= 33)
2306static PyObject*
2307DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2308{
2309 int err, flags=0;
2310 u_int32_t count=0;
2311 PyObject* txnobj = NULL;
2312 DB_TXN *txn = NULL;
2313 char* kwnames[] = { "txn", "flags", NULL };
2314
2315 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2316 &txnobj, &flags))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319 if (!checkTxnObj(txnobj, &txn))
2320 return NULL;
2321
2322 MYDB_BEGIN_ALLOW_THREADS;
2323 err = self->db->truncate(self->db, txn, &count, flags);
2324 MYDB_END_ALLOW_THREADS;
2325 RETURN_IF_ERR();
2326 return PyInt_FromLong(count);
2327}
2328#endif
2329
2330
2331static PyObject*
2332DB_upgrade(DBObject* self, PyObject* args)
2333{
2334 int err, flags=0;
2335 char *filename;
2336
2337 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2338 return NULL;
2339 CHECK_DB_NOT_CLOSED(self);
2340
2341 MYDB_BEGIN_ALLOW_THREADS;
2342 err = self->db->upgrade(self->db, filename, flags);
2343 MYDB_END_ALLOW_THREADS;
2344 RETURN_IF_ERR();
2345 RETURN_NONE();
2346}
2347
2348
2349static PyObject*
2350DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2351{
2352 int err, flags=0;
2353 char* fileName;
2354 char* dbName=NULL;
2355 char* outFileName=NULL;
2356 FILE* outFile=NULL;
2357 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2358
2359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2360 &fileName, &dbName, &outFileName, &flags))
2361 return NULL;
2362
2363 CHECK_DB_NOT_CLOSED(self);
2364 if (outFileName)
2365 outFile = fopen(outFileName, "w");
2366
2367 MYDB_BEGIN_ALLOW_THREADS;
2368 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2369 MYDB_END_ALLOW_THREADS;
2370 if (outFileName)
2371 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002372
2373 /* DB.verify acts as a DB handle destructor (like close); this was
2374 * documented in BerkeleyDB 4.2 but had the undocumented effect
2375 * of not being safe in prior versions while still requiring an explicit
2376 * DB.close call afterwards. Lets call close for the user to emulate
2377 * the safe 4.2 behaviour. */
2378#if (DBVER <= 41)
2379 self->db->close(self->db, 0);
2380#endif
2381 self->db = NULL;
2382
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002383 RETURN_IF_ERR();
2384 RETURN_NONE();
2385}
2386
2387
2388static PyObject*
2389DB_set_get_returns_none(DBObject* self, PyObject* args)
2390{
2391 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002392 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002393
2394 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2395 return NULL;
2396 CHECK_DB_NOT_CLOSED(self);
2397
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002398 if (self->moduleFlags.getReturnsNone)
2399 ++oldValue;
2400 if (self->moduleFlags.cursorSetReturnsNone)
2401 ++oldValue;
2402 self->moduleFlags.getReturnsNone = (flags >= 1);
2403 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002404 return PyInt_FromLong(oldValue);
2405}
2406
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002407#if (DBVER >= 41)
2408static PyObject*
2409DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2410{
2411 int err;
2412 u_int32_t flags=0;
2413 char *passwd = NULL;
2414 char* kwnames[] = { "passwd", "flags", NULL };
2415
2416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2417 &passwd, &flags)) {
2418 return NULL;
2419 }
2420
2421 MYDB_BEGIN_ALLOW_THREADS;
2422 err = self->db->set_encrypt(self->db, passwd, flags);
2423 MYDB_END_ALLOW_THREADS;
2424
2425 RETURN_IF_ERR();
2426 RETURN_NONE();
2427}
2428#endif /* DBVER >= 41 */
2429
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002430
2431/*-------------------------------------------------------------- */
2432/* Mapping and Dictionary-like access routines */
2433
2434int DB_length(DBObject* self)
2435{
2436 int err;
2437 long size = 0;
2438 int flags = 0;
2439 void* sp;
2440
2441 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002442 PyErr_SetObject(DBError,
2443 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 return -1;
2445 }
2446
2447 if (self->haveStat) { /* Has the stat function been called recently? If
2448 so, we can use the cached value. */
2449 flags = DB_CACHED_COUNTS;
2450 }
2451
2452 MYDB_BEGIN_ALLOW_THREADS;
2453#if (DBVER >= 33)
2454 err = self->db->stat(self->db, &sp, flags);
2455#else
2456 err = self->db->stat(self->db, &sp, NULL, flags);
2457#endif
2458 MYDB_END_ALLOW_THREADS;
2459
2460 if (err)
2461 return -1;
2462
2463 self->haveStat = 1;
2464
2465 /* All the stat structures have matching fields upto the ndata field,
2466 so we can use any of them for the type cast */
2467 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2468 free(sp);
2469 return size;
2470}
2471
2472
2473PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2474{
2475 int err;
2476 PyObject* retval;
2477 DBT key;
2478 DBT data;
2479
2480 CHECK_DB_NOT_CLOSED(self);
2481 if (!make_key_dbt(self, keyobj, &key, NULL))
2482 return NULL;
2483
2484 CLEAR_DBT(data);
2485 if (CHECK_DBFLAG(self, DB_THREAD)) {
2486 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2487 data.flags = DB_DBT_MALLOC;
2488 }
2489 MYDB_BEGIN_ALLOW_THREADS;
2490 err = self->db->get(self->db, NULL, &key, &data, 0);
2491 MYDB_END_ALLOW_THREADS;
2492 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2493 PyErr_SetObject(PyExc_KeyError, keyobj);
2494 retval = NULL;
2495 }
2496 else if (makeDBError(err)) {
2497 retval = NULL;
2498 }
2499 else {
2500 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2501 FREE_DBT(data);
2502 }
2503
2504 FREE_DBT(key);
2505 return retval;
2506}
2507
2508
2509static int
2510DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2511{
2512 DBT key, data;
2513 int retval;
2514 int flags = 0;
2515
2516 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002517 PyErr_SetObject(DBError,
2518 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002519 return -1;
2520 }
2521
2522 if (!make_key_dbt(self, keyobj, &key, NULL))
2523 return -1;
2524
2525 if (dataobj != NULL) {
2526 if (!make_dbt(dataobj, &data))
2527 retval = -1;
2528 else {
2529 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002530 /* dictionaries shouldn't have duplicate keys */
2531 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002532 retval = _DB_put(self, NULL, &key, &data, flags);
2533
2534 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002535 /* try deleting any old record that matches and then PUT it
2536 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002537 _DB_delete(self, NULL, &key, 0);
2538 PyErr_Clear();
2539 retval = _DB_put(self, NULL, &key, &data, flags);
2540 }
2541 }
2542 }
2543 else {
2544 /* dataobj == NULL, so delete the key */
2545 retval = _DB_delete(self, NULL, &key, 0);
2546 }
2547 FREE_DBT(key);
2548 return retval;
2549}
2550
2551
2552static PyObject*
2553DB_has_key(DBObject* self, PyObject* args)
2554{
2555 int err;
2556 PyObject* keyobj;
2557 DBT key, data;
2558 PyObject* txnobj = NULL;
2559 DB_TXN *txn = NULL;
2560
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002561 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002562 return NULL;
2563 CHECK_DB_NOT_CLOSED(self);
2564 if (!make_key_dbt(self, keyobj, &key, NULL))
2565 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002566 if (!checkTxnObj(txnobj, &txn)) {
2567 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002568 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002569 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002570
2571 /* This causes ENOMEM to be returned when the db has the key because
2572 it has a record but can't allocate a buffer for the data. This saves
2573 having to deal with data we won't be using.
2574 */
2575 CLEAR_DBT(data);
2576 data.flags = DB_DBT_USERMEM;
2577
2578 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002579 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002580 MYDB_END_ALLOW_THREADS;
2581 FREE_DBT(key);
2582 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2583}
2584
2585
2586#define _KEYS_LIST 1
2587#define _VALUES_LIST 2
2588#define _ITEMS_LIST 3
2589
2590static PyObject*
2591_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2592{
2593 int err, dbtype;
2594 DBT key;
2595 DBT data;
2596 DBC *cursor;
2597 PyObject* list;
2598 PyObject* item = NULL;
2599
2600 CHECK_DB_NOT_CLOSED(self);
2601 CLEAR_DBT(key);
2602 CLEAR_DBT(data);
2603
2604 dbtype = _DB_get_type(self);
2605 if (dbtype == -1)
2606 return NULL;
2607
2608 list = PyList_New(0);
2609 if (list == NULL) {
2610 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2611 return NULL;
2612 }
2613
2614 /* get a cursor */
2615 MYDB_BEGIN_ALLOW_THREADS;
2616 err = self->db->cursor(self->db, NULL, &cursor, 0);
2617 MYDB_END_ALLOW_THREADS;
2618 RETURN_IF_ERR();
2619
2620 if (CHECK_DBFLAG(self, DB_THREAD)) {
2621 key.flags = DB_DBT_REALLOC;
2622 data.flags = DB_DBT_REALLOC;
2623 }
2624
2625 while (1) { /* use the cursor to traverse the DB, collecting items */
2626 MYDB_BEGIN_ALLOW_THREADS;
2627 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2628 MYDB_END_ALLOW_THREADS;
2629
2630 if (err) {
2631 /* for any error, break out of the loop */
2632 break;
2633 }
2634
2635 switch (type) {
2636 case _KEYS_LIST:
2637 switch(dbtype) {
2638 case DB_BTREE:
2639 case DB_HASH:
2640 default:
2641 item = PyString_FromStringAndSize((char*)key.data, key.size);
2642 break;
2643 case DB_RECNO:
2644 case DB_QUEUE:
2645 item = PyInt_FromLong(*((db_recno_t*)key.data));
2646 break;
2647 }
2648 break;
2649
2650 case _VALUES_LIST:
2651 item = PyString_FromStringAndSize((char*)data.data, data.size);
2652 break;
2653
2654 case _ITEMS_LIST:
2655 switch(dbtype) {
2656 case DB_BTREE:
2657 case DB_HASH:
2658 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002659 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2660 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002661 break;
2662 case DB_RECNO:
2663 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002664 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2665 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002666 break;
2667 }
2668 break;
2669 }
2670 if (item == NULL) {
2671 Py_DECREF(list);
2672 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2673 list = NULL;
2674 goto done;
2675 }
2676 PyList_Append(list, item);
2677 Py_DECREF(item);
2678 }
2679
2680 /* DB_NOTFOUND is okay, it just means we got to the end */
2681 if (err != DB_NOTFOUND && makeDBError(err)) {
2682 Py_DECREF(list);
2683 list = NULL;
2684 }
2685
2686 done:
2687 FREE_DBT(key);
2688 FREE_DBT(data);
2689 MYDB_BEGIN_ALLOW_THREADS;
2690 cursor->c_close(cursor);
2691 MYDB_END_ALLOW_THREADS;
2692 return list;
2693}
2694
2695
2696static PyObject*
2697DB_keys(DBObject* self, PyObject* args)
2698{
2699 PyObject* txnobj = NULL;
2700 DB_TXN *txn = NULL;
2701
2702 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2703 return NULL;
2704 if (!checkTxnObj(txnobj, &txn))
2705 return NULL;
2706 return _DB_make_list(self, txn, _KEYS_LIST);
2707}
2708
2709
2710static PyObject*
2711DB_items(DBObject* self, PyObject* args)
2712{
2713 PyObject* txnobj = NULL;
2714 DB_TXN *txn = NULL;
2715
2716 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2717 return NULL;
2718 if (!checkTxnObj(txnobj, &txn))
2719 return NULL;
2720 return _DB_make_list(self, txn, _ITEMS_LIST);
2721}
2722
2723
2724static PyObject*
2725DB_values(DBObject* self, PyObject* args)
2726{
2727 PyObject* txnobj = NULL;
2728 DB_TXN *txn = NULL;
2729
2730 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2731 return NULL;
2732 if (!checkTxnObj(txnobj, &txn))
2733 return NULL;
2734 return _DB_make_list(self, txn, _VALUES_LIST);
2735}
2736
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737/* --------------------------------------------------------------------- */
2738/* DBCursor methods */
2739
2740
2741static PyObject*
2742DBC_close(DBCursorObject* self, PyObject* args)
2743{
2744 int err = 0;
2745
2746 if (!PyArg_ParseTuple(args, ":close"))
2747 return NULL;
2748
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002749 if (self->dbc != NULL) {
2750 MYDB_BEGIN_ALLOW_THREADS;
2751 err = self->dbc->c_close(self->dbc);
2752 self->dbc = NULL;
2753 MYDB_END_ALLOW_THREADS;
2754 }
2755 RETURN_IF_ERR();
2756 RETURN_NONE();
2757}
2758
2759
2760static PyObject*
2761DBC_count(DBCursorObject* self, PyObject* args)
2762{
2763 int err = 0;
2764 db_recno_t count;
2765 int flags = 0;
2766
2767 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2768 return NULL;
2769
2770 CHECK_CURSOR_NOT_CLOSED(self);
2771
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->dbc->c_count(self->dbc, &count, flags);
2774 MYDB_END_ALLOW_THREADS;
2775 RETURN_IF_ERR();
2776
2777 return PyInt_FromLong(count);
2778}
2779
2780
2781static PyObject*
2782DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2783{
2784 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2785}
2786
2787
2788static PyObject*
2789DBC_delete(DBCursorObject* self, PyObject* args)
2790{
2791 int err, flags=0;
2792
2793 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2794 return NULL;
2795
2796 CHECK_CURSOR_NOT_CLOSED(self);
2797
2798 MYDB_BEGIN_ALLOW_THREADS;
2799 err = self->dbc->c_del(self->dbc, flags);
2800 MYDB_END_ALLOW_THREADS;
2801 RETURN_IF_ERR();
2802
2803 self->mydb->haveStat = 0;
2804 RETURN_NONE();
2805}
2806
2807
2808static PyObject*
2809DBC_dup(DBCursorObject* self, PyObject* args)
2810{
2811 int err, flags =0;
2812 DBC* dbc = NULL;
2813
2814 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2815 return NULL;
2816
2817 CHECK_CURSOR_NOT_CLOSED(self);
2818
2819 MYDB_BEGIN_ALLOW_THREADS;
2820 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2821 MYDB_END_ALLOW_THREADS;
2822 RETURN_IF_ERR();
2823
2824 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2825}
2826
2827static PyObject*
2828DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2829{
2830 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2831}
2832
2833
2834static PyObject*
2835DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2836{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002837 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 PyObject* keyobj = NULL;
2839 PyObject* dataobj = NULL;
2840 PyObject* retval = NULL;
2841 int dlen = -1;
2842 int doff = -1;
2843 DBT key, data;
2844 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2845
2846 CLEAR_DBT(key);
2847 CLEAR_DBT(data);
2848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002849 &flags, &dlen, &doff))
2850 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002851 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2853 &kwnames[1],
2854 &keyobj, &flags, &dlen, &doff))
2855 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002856 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2858 kwnames, &keyobj, &dataobj,
2859 &flags, &dlen, &doff))
2860 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 return NULL;
2862 }
2863 }
2864 }
2865
2866 CHECK_CURSOR_NOT_CLOSED(self);
2867
2868 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2869 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002870 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2871 (!add_partial_dbt(&data, dlen, doff)) )
2872 {
2873 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002874 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002875 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002876
2877 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2878 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002879 if (!(key.flags & DB_DBT_REALLOC)) {
2880 key.flags |= DB_DBT_MALLOC;
2881 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002882 }
2883
2884 MYDB_BEGIN_ALLOW_THREADS;
2885 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2886 MYDB_END_ALLOW_THREADS;
2887
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002888 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002889 Py_INCREF(Py_None);
2890 retval = Py_None;
2891 }
2892 else if (makeDBError(err)) {
2893 retval = NULL;
2894 }
2895 else {
2896 switch (_DB_get_type(self->mydb)) {
2897 case -1:
2898 retval = NULL;
2899 break;
2900 case DB_BTREE:
2901 case DB_HASH:
2902 default:
2903 retval = Py_BuildValue("s#s#", key.data, key.size,
2904 data.data, data.size);
2905 break;
2906 case DB_RECNO:
2907 case DB_QUEUE:
2908 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2909 data.data, data.size);
2910 break;
2911 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002912 FREE_DBT(data);
2913 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002914 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915 return retval;
2916}
2917
Gregory P. Smith19699a92004-06-28 04:06:49 +00002918static PyObject*
2919DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2920{
2921 int err, flags=0;
2922 PyObject* keyobj = NULL;
2923 PyObject* dataobj = NULL;
2924 PyObject* retval = NULL;
2925 int dlen = -1;
2926 int doff = -1;
2927 DBT key, pkey, data;
2928 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2929
2930 CLEAR_DBT(key);
2931 CLEAR_DBT(data);
2932 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
2933 &flags, &dlen, &doff))
2934 {
2935 PyErr_Clear();
2936 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
2937 &kwnames[1],
2938 &keyobj, &flags, &dlen, &doff))
2939 {
2940 PyErr_Clear();
2941 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
2942 kwnames, &keyobj, &dataobj,
2943 &flags, &dlen, &doff))
2944 {
2945 return NULL;
2946 }
2947 }
2948 }
2949
2950 CHECK_CURSOR_NOT_CLOSED(self);
2951
2952 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2953 return NULL;
2954 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2955 (!add_partial_dbt(&data, dlen, doff)) ) {
2956 FREE_DBT(key);
2957 return NULL;
2958 }
2959
2960 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2961 data.flags = DB_DBT_MALLOC;
2962 if (!(key.flags & DB_DBT_REALLOC)) {
2963 key.flags |= DB_DBT_MALLOC;
2964 }
2965 }
2966
2967 CLEAR_DBT(pkey);
2968 pkey.flags = DB_DBT_MALLOC;
2969
2970 MYDB_BEGIN_ALLOW_THREADS;
2971 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
2972 MYDB_END_ALLOW_THREADS;
2973
2974 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2975 Py_INCREF(Py_None);
2976 retval = Py_None;
2977 }
2978 else if (makeDBError(err)) {
2979 retval = NULL;
2980 }
2981 else {
2982 PyObject *pkeyObj;
2983 PyObject *dataObj;
2984 dataObj = PyString_FromStringAndSize(data.data, data.size);
2985
2986 if (self->mydb->primaryDBType == DB_RECNO ||
2987 self->mydb->primaryDBType == DB_QUEUE)
2988 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
2989 else
2990 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
2991
2992 if (flags & DB_SET_RECNO) /* return key, pkey and data */
2993 {
2994 PyObject *keyObj;
2995 int type = _DB_get_type(self->mydb);
2996 if (type == DB_RECNO || type == DB_QUEUE)
2997 keyObj = PyInt_FromLong(*(long *)key.data);
2998 else
2999 keyObj = PyString_FromStringAndSize(key.data, key.size);
3000 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3001 FREE_DBT(key);
3002 }
3003 else /* return just the pkey and data */
3004 {
3005 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3006 }
3007 FREE_DBT(pkey);
3008 FREE_DBT(data);
3009 }
3010 /* the only time REALLOC should be set is if we used an integer
3011 * key that make_key_dbt malloc'd for us. always free these. */
3012 if (key.flags & DB_DBT_REALLOC) {
3013 FREE_DBT(key);
3014 }
3015 return retval;
3016}
3017
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003018
3019static PyObject*
3020DBC_get_recno(DBCursorObject* self, PyObject* args)
3021{
3022 int err;
3023 db_recno_t recno;
3024 DBT key;
3025 DBT data;
3026
3027 if (!PyArg_ParseTuple(args, ":get_recno"))
3028 return NULL;
3029
3030 CHECK_CURSOR_NOT_CLOSED(self);
3031
3032 CLEAR_DBT(key);
3033 CLEAR_DBT(data);
3034 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3035 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3036 data.flags = DB_DBT_MALLOC;
3037 key.flags = DB_DBT_MALLOC;
3038 }
3039
3040 MYDB_BEGIN_ALLOW_THREADS;
3041 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3042 MYDB_END_ALLOW_THREADS;
3043 RETURN_IF_ERR();
3044
3045 recno = *((db_recno_t*)data.data);
3046 FREE_DBT(key);
3047 FREE_DBT(data);
3048 return PyInt_FromLong(recno);
3049}
3050
3051
3052static PyObject*
3053DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3054{
3055 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3056}
3057
3058
3059static PyObject*
3060DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3061{
3062 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3063}
3064
3065
3066static PyObject*
3067DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3068{
3069 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3070}
3071
3072
3073static PyObject*
3074DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3075{
3076 int err, flags = 0;
3077 PyObject* keyobj, *dataobj;
3078 DBT key, data;
3079 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3080 int dlen = -1;
3081 int doff = -1;
3082
3083 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3084 &keyobj, &dataobj, &flags, &dlen, &doff))
3085 return NULL;
3086
3087 CHECK_CURSOR_NOT_CLOSED(self);
3088
3089 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3090 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003091 if (!make_dbt(dataobj, &data) ||
3092 !add_partial_dbt(&data, dlen, doff) )
3093 {
3094 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003095 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003096 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003097
3098 MYDB_BEGIN_ALLOW_THREADS;
3099 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3100 MYDB_END_ALLOW_THREADS;
3101 FREE_DBT(key);
3102 RETURN_IF_ERR();
3103 self->mydb->haveStat = 0;
3104 RETURN_NONE();
3105}
3106
3107
3108static PyObject*
3109DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3110{
3111 int err, flags = 0;
3112 DBT key, data;
3113 PyObject* retval, *keyobj;
3114 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3115 int dlen = -1;
3116 int doff = -1;
3117
3118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3119 &keyobj, &flags, &dlen, &doff))
3120 return NULL;
3121
3122 CHECK_CURSOR_NOT_CLOSED(self);
3123
3124 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3125 return NULL;
3126
3127 CLEAR_DBT(data);
3128 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3129 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3130 data.flags = DB_DBT_MALLOC;
3131 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003132 if (!add_partial_dbt(&data, dlen, doff)) {
3133 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003134 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003135 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136
3137 MYDB_BEGIN_ALLOW_THREADS;
3138 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3139 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003140 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3141 Py_INCREF(Py_None);
3142 retval = Py_None;
3143 }
3144 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145 retval = NULL;
3146 }
3147 else {
3148 switch (_DB_get_type(self->mydb)) {
3149 case -1:
3150 retval = NULL;
3151 break;
3152 case DB_BTREE:
3153 case DB_HASH:
3154 default:
3155 retval = Py_BuildValue("s#s#", key.data, key.size,
3156 data.data, data.size);
3157 break;
3158 case DB_RECNO:
3159 case DB_QUEUE:
3160 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3161 data.data, data.size);
3162 break;
3163 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003164 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003165 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003166 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003167 /* the only time REALLOC should be set is if we used an integer
3168 * key that make_key_dbt malloc'd for us. always free these. */
3169 if (key.flags & DB_DBT_REALLOC) {
3170 FREE_DBT(key);
3171 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172
3173 return retval;
3174}
3175
3176
3177static PyObject*
3178DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3179{
3180 int err, flags = 0;
3181 DBT key, data;
3182 PyObject* retval, *keyobj;
3183 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3184 int dlen = -1;
3185 int doff = -1;
3186
3187 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3188 &keyobj, &flags, &dlen, &doff))
3189 return NULL;
3190
3191 CHECK_CURSOR_NOT_CLOSED(self);
3192
3193 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3194 return NULL;
3195
3196 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003197 if (!add_partial_dbt(&data, dlen, doff)) {
3198 FREE_DBT(key);
3199 return NULL;
3200 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003201 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3202 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003203 data.flags |= DB_DBT_MALLOC;
3204 /* only BTREE databases will return anything in the key */
3205 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3206 key.flags |= DB_DBT_MALLOC;
3207 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003209 MYDB_BEGIN_ALLOW_THREADS;
3210 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3211 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003212 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3213 Py_INCREF(Py_None);
3214 retval = Py_None;
3215 }
3216 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003217 retval = NULL;
3218 }
3219 else {
3220 switch (_DB_get_type(self->mydb)) {
3221 case -1:
3222 retval = NULL;
3223 break;
3224 case DB_BTREE:
3225 case DB_HASH:
3226 default:
3227 retval = Py_BuildValue("s#s#", key.data, key.size,
3228 data.data, data.size);
3229 break;
3230 case DB_RECNO:
3231 case DB_QUEUE:
3232 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3233 data.data, data.size);
3234 break;
3235 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003236 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003237 FREE_DBT(data);
3238 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003239 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003240 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003241 if (key.flags & DB_DBT_REALLOC) {
3242 FREE_DBT(key);
3243 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003244
3245 return retval;
3246}
3247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003248static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003249_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3250 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003251{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003252 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003253 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003254 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003255
Gregory P. Smith7441e652003-11-03 21:35:31 +00003256 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003257 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3258 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003259 if (!make_dbt(dataobj, &data)) {
3260 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003261 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003262 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003263
3264 MYDB_BEGIN_ALLOW_THREADS;
3265 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3266 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003267 if ((err == DB_NOTFOUND) && returnsNone) {
3268 Py_INCREF(Py_None);
3269 retval = Py_None;
3270 }
3271 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003272 retval = NULL;
3273 }
3274 else {
3275 switch (_DB_get_type(self->mydb)) {
3276 case -1:
3277 retval = NULL;
3278 break;
3279 case DB_BTREE:
3280 case DB_HASH:
3281 default:
3282 retval = Py_BuildValue("s#s#", key.data, key.size,
3283 data.data, data.size);
3284 break;
3285 case DB_RECNO:
3286 case DB_QUEUE:
3287 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3288 data.data, data.size);
3289 break;
3290 }
3291 }
3292
3293 FREE_DBT(key);
3294 return retval;
3295}
3296
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003297static PyObject*
3298DBC_get_both(DBCursorObject* self, PyObject* args)
3299{
3300 int flags=0;
3301 PyObject *keyobj, *dataobj;
3302
3303 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3304 return NULL;
3305
Gregory P. Smith7441e652003-11-03 21:35:31 +00003306 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003307 CHECK_CURSOR_NOT_CLOSED(self);
3308
3309 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3310 self->mydb->moduleFlags.getReturnsNone);
3311}
3312
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003313/* Return size of entry */
3314static PyObject*
3315DBC_get_current_size(DBCursorObject* self, PyObject* args)
3316{
3317 int err, flags=DB_CURRENT;
3318 PyObject* retval = NULL;
3319 DBT key, data;
3320
3321 if (!PyArg_ParseTuple(args, ":get_current_size"))
3322 return NULL;
3323 CHECK_CURSOR_NOT_CLOSED(self);
3324 CLEAR_DBT(key);
3325 CLEAR_DBT(data);
3326
3327 /* We don't allocate any memory, forcing a ENOMEM error and thus
3328 getting the record size. */
3329 data.flags = DB_DBT_USERMEM;
3330 data.ulen = 0;
3331 MYDB_BEGIN_ALLOW_THREADS;
3332 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3333 MYDB_END_ALLOW_THREADS;
3334 if (err == ENOMEM || !err) {
3335 /* ENOMEM means positive size, !err means zero length value */
3336 retval = PyInt_FromLong((long)data.size);
3337 err = 0;
3338 }
3339
3340 FREE_DBT(key);
3341 FREE_DBT(data);
3342 RETURN_IF_ERR();
3343 return retval;
3344}
3345
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003346static PyObject*
3347DBC_set_both(DBCursorObject* self, PyObject* args)
3348{
3349 int flags=0;
3350 PyObject *keyobj, *dataobj;
3351
3352 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3353 return NULL;
3354
Gregory P. Smith7441e652003-11-03 21:35:31 +00003355 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003356 CHECK_CURSOR_NOT_CLOSED(self);
3357
3358 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3359 self->mydb->moduleFlags.cursorSetReturnsNone);
3360}
3361
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362
3363static PyObject*
3364DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3365{
3366 int err, irecno, flags=0;
3367 db_recno_t recno;
3368 DBT key, data;
3369 PyObject* retval;
3370 int dlen = -1;
3371 int doff = -1;
3372 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3373
3374 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3375 &irecno, &flags, &dlen, &doff))
3376 return NULL;
3377
3378 CHECK_CURSOR_NOT_CLOSED(self);
3379
3380 CLEAR_DBT(key);
3381 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003382 /* use allocated space so DB will be able to realloc room for the real
3383 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003384 key.data = malloc(sizeof(db_recno_t));
3385 if (key.data == NULL) {
3386 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3387 return NULL;
3388 }
3389 key.size = sizeof(db_recno_t);
3390 key.ulen = key.size;
3391 memcpy(key.data, &recno, sizeof(db_recno_t));
3392 key.flags = DB_DBT_REALLOC;
3393
3394 CLEAR_DBT(data);
3395 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3396 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3397 data.flags = DB_DBT_MALLOC;
3398 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003399 if (!add_partial_dbt(&data, dlen, doff)) {
3400 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003401 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003402 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003403
3404 MYDB_BEGIN_ALLOW_THREADS;
3405 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3406 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003407 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3408 Py_INCREF(Py_None);
3409 retval = Py_None;
3410 }
3411 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 retval = NULL;
3413 }
3414 else { /* Can only be used for BTrees, so no need to return int key */
3415 retval = Py_BuildValue("s#s#", key.data, key.size,
3416 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417 FREE_DBT(data);
3418 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003419 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003420
3421 return retval;
3422}
3423
3424
3425static PyObject*
3426DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3427{
3428 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3429}
3430
3431
3432static PyObject*
3433DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3434{
3435 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3436}
3437
3438
3439static PyObject*
3440DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3441{
3442 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3443}
3444
3445
3446static PyObject*
3447DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3448{
3449 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3450}
3451
3452
3453static PyObject*
3454DBC_join_item(DBCursorObject* self, PyObject* args)
3455{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003456 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457 DBT key, data;
3458 PyObject* retval;
3459
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003460 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 return NULL;
3462
3463 CHECK_CURSOR_NOT_CLOSED(self);
3464
3465 CLEAR_DBT(key);
3466 CLEAR_DBT(data);
3467 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3468 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3469 key.flags = DB_DBT_MALLOC;
3470 }
3471
3472 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003473 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003474 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003475 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3476 Py_INCREF(Py_None);
3477 retval = Py_None;
3478 }
3479 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003480 retval = NULL;
3481 }
3482 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003483 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 FREE_DBT(key);
3485 }
3486
3487 return retval;
3488}
3489
3490
3491
3492/* --------------------------------------------------------------------- */
3493/* DBEnv methods */
3494
3495
3496static PyObject*
3497DBEnv_close(DBEnvObject* self, PyObject* args)
3498{
3499 int err, flags = 0;
3500
3501 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3502 return NULL;
3503 if (!self->closed) { /* Don't close more than once */
3504 MYDB_BEGIN_ALLOW_THREADS;
3505 err = self->db_env->close(self->db_env, flags);
3506 MYDB_END_ALLOW_THREADS;
3507 /* after calling DBEnv->close, regardless of error, this DBEnv
3508 * may not be accessed again (BerkeleyDB docs). */
3509 self->closed = 1;
3510 self->db_env = NULL;
3511 RETURN_IF_ERR();
3512 }
3513 RETURN_NONE();
3514}
3515
3516
3517static PyObject*
3518DBEnv_open(DBEnvObject* self, PyObject* args)
3519{
3520 int err, flags=0, mode=0660;
3521 char *db_home;
3522
3523 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3524 return NULL;
3525
3526 CHECK_ENV_NOT_CLOSED(self);
3527
3528 MYDB_BEGIN_ALLOW_THREADS;
3529 err = self->db_env->open(self->db_env, db_home, flags, mode);
3530 MYDB_END_ALLOW_THREADS;
3531 RETURN_IF_ERR();
3532 self->closed = 0;
3533 self->flags = flags;
3534 RETURN_NONE();
3535}
3536
3537
3538static PyObject*
3539DBEnv_remove(DBEnvObject* self, PyObject* args)
3540{
3541 int err, flags=0;
3542 char *db_home;
3543
3544 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3545 return NULL;
3546 CHECK_ENV_NOT_CLOSED(self);
3547 MYDB_BEGIN_ALLOW_THREADS;
3548 err = self->db_env->remove(self->db_env, db_home, flags);
3549 MYDB_END_ALLOW_THREADS;
3550 RETURN_IF_ERR();
3551 RETURN_NONE();
3552}
3553
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003554#if (DBVER >= 41)
3555static PyObject*
3556DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3557{
3558 int err;
3559 u_int32_t flags=0;
3560 char *file = NULL;
3561 char *database = NULL;
3562 PyObject *txnobj = NULL;
3563 DB_TXN *txn = NULL;
3564 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3565
3566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3567 &file, &database, &txnobj, &flags)) {
3568 return NULL;
3569 }
3570 if (!checkTxnObj(txnobj, &txn)) {
3571 return NULL;
3572 }
3573 CHECK_ENV_NOT_CLOSED(self);
3574 MYDB_BEGIN_ALLOW_THREADS;
3575 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3576 MYDB_END_ALLOW_THREADS;
3577 RETURN_IF_ERR();
3578 RETURN_NONE();
3579}
3580
3581static PyObject*
3582DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3583{
3584 int err;
3585 u_int32_t flags=0;
3586 char *file = NULL;
3587 char *database = NULL;
3588 char *newname = NULL;
3589 PyObject *txnobj = NULL;
3590 DB_TXN *txn = NULL;
3591 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3592
3593 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3594 &file, &database, &newname, &txnobj, &flags)) {
3595 return NULL;
3596 }
3597 if (!checkTxnObj(txnobj, &txn)) {
3598 return NULL;
3599 }
3600 CHECK_ENV_NOT_CLOSED(self);
3601 MYDB_BEGIN_ALLOW_THREADS;
3602 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3603 flags);
3604 MYDB_END_ALLOW_THREADS;
3605 RETURN_IF_ERR();
3606 RETURN_NONE();
3607}
3608
3609static PyObject*
3610DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3611{
3612 int err;
3613 u_int32_t flags=0;
3614 char *passwd = NULL;
3615 char* kwnames[] = { "passwd", "flags", NULL };
3616
3617 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3618 &passwd, &flags)) {
3619 return NULL;
3620 }
3621
3622 MYDB_BEGIN_ALLOW_THREADS;
3623 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3624 MYDB_END_ALLOW_THREADS;
3625
3626 RETURN_IF_ERR();
3627 RETURN_NONE();
3628}
3629#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003630
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003631#if (DBVER >= 40)
3632static PyObject*
3633DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3634{
3635 int err;
3636 u_int32_t flags=0;
3637 u_int32_t timeout = 0;
3638 char* kwnames[] = { "timeout", "flags", NULL };
3639
3640 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3641 &timeout, &flags)) {
3642 return NULL;
3643 }
3644
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3647 MYDB_END_ALLOW_THREADS;
3648
3649 RETURN_IF_ERR();
3650 RETURN_NONE();
3651}
3652#endif /* DBVER >= 40 */
3653
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003654static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003655DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3656{
3657 int err;
3658 long shm_key = 0;
3659
3660 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3661 return NULL;
3662 CHECK_ENV_NOT_CLOSED(self);
3663
3664 err = self->db_env->set_shm_key(self->db_env, shm_key);
3665 RETURN_IF_ERR();
3666 RETURN_NONE();
3667}
3668
3669static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3671{
3672 int err, gbytes=0, bytes=0, ncache=0;
3673
3674 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3675 &gbytes, &bytes, &ncache))
3676 return NULL;
3677 CHECK_ENV_NOT_CLOSED(self);
3678
3679 MYDB_BEGIN_ALLOW_THREADS;
3680 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3681 MYDB_END_ALLOW_THREADS;
3682 RETURN_IF_ERR();
3683 RETURN_NONE();
3684}
3685
3686
3687#if (DBVER >= 32)
3688static PyObject*
3689DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3690{
3691 int err, flags=0, onoff=0;
3692
3693 if (!PyArg_ParseTuple(args, "ii:set_flags",
3694 &flags, &onoff))
3695 return NULL;
3696 CHECK_ENV_NOT_CLOSED(self);
3697
3698 MYDB_BEGIN_ALLOW_THREADS;
3699 err = self->db_env->set_flags(self->db_env, flags, onoff);
3700 MYDB_END_ALLOW_THREADS;
3701 RETURN_IF_ERR();
3702 RETURN_NONE();
3703}
3704#endif
3705
3706
3707static PyObject*
3708DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3709{
3710 int err;
3711 char *dir;
3712
3713 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3714 return NULL;
3715 CHECK_ENV_NOT_CLOSED(self);
3716
3717 MYDB_BEGIN_ALLOW_THREADS;
3718 err = self->db_env->set_data_dir(self->db_env, dir);
3719 MYDB_END_ALLOW_THREADS;
3720 RETURN_IF_ERR();
3721 RETURN_NONE();
3722}
3723
3724
3725static PyObject*
3726DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3727{
3728 int err, lg_bsize;
3729
3730 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3731 return NULL;
3732 CHECK_ENV_NOT_CLOSED(self);
3733
3734 MYDB_BEGIN_ALLOW_THREADS;
3735 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3736 MYDB_END_ALLOW_THREADS;
3737 RETURN_IF_ERR();
3738 RETURN_NONE();
3739}
3740
3741
3742static PyObject*
3743DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3744{
3745 int err;
3746 char *dir;
3747
3748 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3749 return NULL;
3750 CHECK_ENV_NOT_CLOSED(self);
3751
3752 MYDB_BEGIN_ALLOW_THREADS;
3753 err = self->db_env->set_lg_dir(self->db_env, dir);
3754 MYDB_END_ALLOW_THREADS;
3755 RETURN_IF_ERR();
3756 RETURN_NONE();
3757}
3758
3759static PyObject*
3760DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3761{
3762 int err, lg_max;
3763
3764 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3765 return NULL;
3766 CHECK_ENV_NOT_CLOSED(self);
3767
3768 MYDB_BEGIN_ALLOW_THREADS;
3769 err = self->db_env->set_lg_max(self->db_env, lg_max);
3770 MYDB_END_ALLOW_THREADS;
3771 RETURN_IF_ERR();
3772 RETURN_NONE();
3773}
3774
3775
3776static PyObject*
3777DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3778{
3779 int err, lk_detect;
3780
3781 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3782 return NULL;
3783 CHECK_ENV_NOT_CLOSED(self);
3784
3785 MYDB_BEGIN_ALLOW_THREADS;
3786 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3790}
3791
3792
3793static PyObject*
3794DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3795{
3796 int err, max;
3797
3798 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3799 return NULL;
3800 CHECK_ENV_NOT_CLOSED(self);
3801
3802 MYDB_BEGIN_ALLOW_THREADS;
3803 err = self->db_env->set_lk_max(self->db_env, max);
3804 MYDB_END_ALLOW_THREADS;
3805 RETURN_IF_ERR();
3806 RETURN_NONE();
3807}
3808
3809
3810#if (DBVER >= 32)
3811
3812static PyObject*
3813DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3814{
3815 int err, max;
3816
3817 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3818 return NULL;
3819 CHECK_ENV_NOT_CLOSED(self);
3820
3821 MYDB_BEGIN_ALLOW_THREADS;
3822 err = self->db_env->set_lk_max_locks(self->db_env, max);
3823 MYDB_END_ALLOW_THREADS;
3824 RETURN_IF_ERR();
3825 RETURN_NONE();
3826}
3827
3828
3829static PyObject*
3830DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3831{
3832 int err, max;
3833
3834 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3835 return NULL;
3836 CHECK_ENV_NOT_CLOSED(self);
3837
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3840 MYDB_END_ALLOW_THREADS;
3841 RETURN_IF_ERR();
3842 RETURN_NONE();
3843}
3844
3845
3846static PyObject*
3847DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3848{
3849 int err, max;
3850
3851 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3852 return NULL;
3853 CHECK_ENV_NOT_CLOSED(self);
3854
3855 MYDB_BEGIN_ALLOW_THREADS;
3856 err = self->db_env->set_lk_max_objects(self->db_env, max);
3857 MYDB_END_ALLOW_THREADS;
3858 RETURN_IF_ERR();
3859 RETURN_NONE();
3860}
3861
3862#endif
3863
3864
3865static PyObject*
3866DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3867{
3868 int err, mp_mmapsize;
3869
3870 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3871 return NULL;
3872 CHECK_ENV_NOT_CLOSED(self);
3873
3874 MYDB_BEGIN_ALLOW_THREADS;
3875 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3876 MYDB_END_ALLOW_THREADS;
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3879}
3880
3881
3882static PyObject*
3883DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3884{
3885 int err;
3886 char *dir;
3887
3888 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3889 return NULL;
3890 CHECK_ENV_NOT_CLOSED(self);
3891
3892 MYDB_BEGIN_ALLOW_THREADS;
3893 err = self->db_env->set_tmp_dir(self->db_env, dir);
3894 MYDB_END_ALLOW_THREADS;
3895 RETURN_IF_ERR();
3896 RETURN_NONE();
3897}
3898
3899
3900static PyObject*
3901DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3902{
3903 int flags = 0;
3904 PyObject* txnobj = NULL;
3905 DB_TXN *txn = NULL;
3906 char* kwnames[] = { "parent", "flags", NULL };
3907
3908 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3909 &txnobj, &flags))
3910 return NULL;
3911
3912 if (!checkTxnObj(txnobj, &txn))
3913 return NULL;
3914 CHECK_ENV_NOT_CLOSED(self);
3915
3916 return (PyObject*)newDBTxnObject(self, txn, flags);
3917}
3918
3919
3920static PyObject*
3921DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3922{
3923 int err, kbyte=0, min=0, flags=0;
3924
3925 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3926 return NULL;
3927 CHECK_ENV_NOT_CLOSED(self);
3928
3929 MYDB_BEGIN_ALLOW_THREADS;
3930#if (DBVER >= 40)
3931 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3932#else
3933 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3934#endif
3935 MYDB_END_ALLOW_THREADS;
3936 RETURN_IF_ERR();
3937 RETURN_NONE();
3938}
3939
3940
3941static PyObject*
3942DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3943{
3944 int err, max;
3945
3946 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3947 return NULL;
3948 CHECK_ENV_NOT_CLOSED(self);
3949
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_tx_max(self->db_env, max);
3952 MYDB_END_ALLOW_THREADS;
3953 RETURN_IF_ERR();
3954 RETURN_NONE();
3955}
3956
3957
3958static PyObject*
3959DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3960{
3961 int err, atype, flags=0;
3962 int aborted = 0;
3963
3964 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3965 return NULL;
3966 CHECK_ENV_NOT_CLOSED(self);
3967
3968 MYDB_BEGIN_ALLOW_THREADS;
3969#if (DBVER >= 40)
3970 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3971#else
3972 err = lock_detect(self->db_env, flags, atype, &aborted);
3973#endif
3974 MYDB_END_ALLOW_THREADS;
3975 RETURN_IF_ERR();
3976 return PyInt_FromLong(aborted);
3977}
3978
3979
3980static PyObject*
3981DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3982{
3983 int flags=0;
3984 int locker, lock_mode;
3985 DBT obj;
3986 PyObject* objobj;
3987
3988 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3989 return NULL;
3990
3991
3992 if (!make_dbt(objobj, &obj))
3993 return NULL;
3994
3995 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3996}
3997
3998
3999static PyObject*
4000DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4001{
4002 int err;
4003 u_int32_t theID;
4004
4005 if (!PyArg_ParseTuple(args, ":lock_id"))
4006 return NULL;
4007
4008 CHECK_ENV_NOT_CLOSED(self);
4009 MYDB_BEGIN_ALLOW_THREADS;
4010#if (DBVER >= 40)
4011 err = self->db_env->lock_id(self->db_env, &theID);
4012#else
4013 err = lock_id(self->db_env, &theID);
4014#endif
4015 MYDB_END_ALLOW_THREADS;
4016 RETURN_IF_ERR();
4017
4018 return PyInt_FromLong((long)theID);
4019}
4020
4021
4022static PyObject*
4023DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4024{
4025 int err;
4026 DBLockObject* dblockobj;
4027
4028 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4029 return NULL;
4030
4031 CHECK_ENV_NOT_CLOSED(self);
4032 MYDB_BEGIN_ALLOW_THREADS;
4033#if (DBVER >= 40)
4034 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4035#else
4036 err = lock_put(self->db_env, &dblockobj->lock);
4037#endif
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4041}
4042
4043
4044static PyObject*
4045DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4046{
4047 int err;
4048 DB_LOCK_STAT* sp;
4049 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004050 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004051
4052 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4053 return NULL;
4054 CHECK_ENV_NOT_CLOSED(self);
4055
4056 MYDB_BEGIN_ALLOW_THREADS;
4057#if (DBVER >= 40)
4058 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4059#else
4060#if (DBVER >= 33)
4061 err = lock_stat(self->db_env, &sp);
4062#else
4063 err = lock_stat(self->db_env, &sp, NULL);
4064#endif
4065#endif
4066 MYDB_END_ALLOW_THREADS;
4067 RETURN_IF_ERR();
4068
4069 /* Turn the stat structure into a dictionary */
4070 d = PyDict_New();
4071 if (d == NULL) {
4072 free(sp);
4073 return NULL;
4074 }
4075
4076#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4077
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004078#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004079 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004080#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004081 MAKE_ENTRY(nmodes);
4082#if (DBVER >= 32)
4083 MAKE_ENTRY(maxlocks);
4084 MAKE_ENTRY(maxlockers);
4085 MAKE_ENTRY(maxobjects);
4086 MAKE_ENTRY(nlocks);
4087 MAKE_ENTRY(maxnlocks);
4088#endif
4089 MAKE_ENTRY(nlockers);
4090 MAKE_ENTRY(maxnlockers);
4091#if (DBVER >= 32)
4092 MAKE_ENTRY(nobjects);
4093 MAKE_ENTRY(maxnobjects);
4094#endif
4095 MAKE_ENTRY(nrequests);
4096 MAKE_ENTRY(nreleases);
4097 MAKE_ENTRY(nnowaits);
4098 MAKE_ENTRY(nconflicts);
4099 MAKE_ENTRY(ndeadlocks);
4100 MAKE_ENTRY(regsize);
4101 MAKE_ENTRY(region_wait);
4102 MAKE_ENTRY(region_nowait);
4103
4104#undef MAKE_ENTRY
4105 free(sp);
4106 return d;
4107}
4108
4109
4110static PyObject*
4111DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4112{
4113 int flags=0;
4114 int err;
4115 char **log_list_start, **log_list;
4116 PyObject* list;
4117 PyObject* item = NULL;
4118
4119 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4120 return NULL;
4121
4122 CHECK_ENV_NOT_CLOSED(self);
4123 MYDB_BEGIN_ALLOW_THREADS;
4124#if (DBVER >= 40)
4125 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4126#elif (DBVER == 33)
4127 err = log_archive(self->db_env, &log_list, flags);
4128#else
4129 err = log_archive(self->db_env, &log_list, flags, NULL);
4130#endif
4131 MYDB_END_ALLOW_THREADS;
4132 RETURN_IF_ERR();
4133
4134 list = PyList_New(0);
4135 if (list == NULL) {
4136 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4137 return NULL;
4138 }
4139
4140 if (log_list) {
4141 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4142 item = PyString_FromString (*log_list);
4143 if (item == NULL) {
4144 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004145 PyErr_SetString(PyExc_MemoryError,
4146 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004147 list = NULL;
4148 break;
4149 }
4150 PyList_Append(list, item);
4151 Py_DECREF(item);
4152 }
4153 free(log_list_start);
4154 }
4155 return list;
4156}
4157
4158
4159static PyObject*
4160DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4161{
4162 int err;
4163 DB_TXN_STAT* sp;
4164 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004165 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004166
4167 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4168 return NULL;
4169 CHECK_ENV_NOT_CLOSED(self);
4170
4171 MYDB_BEGIN_ALLOW_THREADS;
4172#if (DBVER >= 40)
4173 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4174#elif (DBVER == 33)
4175 err = txn_stat(self->db_env, &sp);
4176#else
4177 err = txn_stat(self->db_env, &sp, NULL);
4178#endif
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181
4182 /* Turn the stat structure into a dictionary */
4183 d = PyDict_New();
4184 if (d == NULL) {
4185 free(sp);
4186 return NULL;
4187 }
4188
4189#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4190
4191 MAKE_ENTRY(time_ckp);
4192 MAKE_ENTRY(last_txnid);
4193 MAKE_ENTRY(maxtxns);
4194 MAKE_ENTRY(nactive);
4195 MAKE_ENTRY(maxnactive);
4196 MAKE_ENTRY(nbegins);
4197 MAKE_ENTRY(naborts);
4198 MAKE_ENTRY(ncommits);
4199 MAKE_ENTRY(regsize);
4200 MAKE_ENTRY(region_wait);
4201 MAKE_ENTRY(region_nowait);
4202
4203#undef MAKE_ENTRY
4204 free(sp);
4205 return d;
4206}
4207
4208
4209static PyObject*
4210DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4211{
4212 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004213 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004214
4215 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4216 return NULL;
4217 CHECK_ENV_NOT_CLOSED(self);
4218
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004219 if (self->moduleFlags.getReturnsNone)
4220 ++oldValue;
4221 if (self->moduleFlags.cursorSetReturnsNone)
4222 ++oldValue;
4223 self->moduleFlags.getReturnsNone = (flags >= 1);
4224 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004225 return PyInt_FromLong(oldValue);
4226}
4227
4228
4229/* --------------------------------------------------------------------- */
4230/* DBTxn methods */
4231
4232
4233static PyObject*
4234DBTxn_commit(DBTxnObject* self, PyObject* args)
4235{
4236 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004237 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004238
4239 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4240 return NULL;
4241
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004242 if (!self->txn) {
4243 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4244 "DBTxn must not be used after txn_commit or txn_abort"));
4245 return NULL;
4246 }
4247 txn = self->txn;
4248 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004249 MYDB_BEGIN_ALLOW_THREADS;
4250#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004251 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004252#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004253 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004254#endif
4255 MYDB_END_ALLOW_THREADS;
4256 RETURN_IF_ERR();
4257 RETURN_NONE();
4258}
4259
4260static PyObject*
4261DBTxn_prepare(DBTxnObject* self, PyObject* args)
4262{
4263#if (DBVER >= 33)
4264 int err;
4265 char* gid=NULL;
4266 int gid_size=0;
4267
4268 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4269 return NULL;
4270
4271 if (gid_size != DB_XIDDATASIZE) {
4272 PyErr_SetString(PyExc_TypeError,
4273 "gid must be DB_XIDDATASIZE bytes long");
4274 return NULL;
4275 }
4276
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004277 if (!self->txn) {
4278 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4279 "DBTxn must not be used after txn_commit or txn_abort"));
4280 return NULL;
4281 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004282 MYDB_BEGIN_ALLOW_THREADS;
4283#if (DBVER >= 40)
4284 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4285#else
4286 err = txn_prepare(self->txn, (u_int8_t*)gid);
4287#endif
4288 MYDB_END_ALLOW_THREADS;
4289 RETURN_IF_ERR();
4290 RETURN_NONE();
4291#else
4292 int err;
4293
4294 if (!PyArg_ParseTuple(args, ":prepare"))
4295 return NULL;
4296
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004297 if (!self->txn) {
4298 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4299 "DBTxn must not be used after txn_commit or txn_abort"));
4300 return NULL;
4301 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004302 MYDB_BEGIN_ALLOW_THREADS;
4303 err = txn_prepare(self->txn);
4304 MYDB_END_ALLOW_THREADS;
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307#endif
4308}
4309
4310
4311static PyObject*
4312DBTxn_abort(DBTxnObject* self, PyObject* args)
4313{
4314 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004315 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004316
4317 if (!PyArg_ParseTuple(args, ":abort"))
4318 return NULL;
4319
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004320 if (!self->txn) {
4321 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4322 "DBTxn must not be used after txn_commit or txn_abort"));
4323 return NULL;
4324 }
4325 txn = self->txn;
4326 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004327 MYDB_BEGIN_ALLOW_THREADS;
4328#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004329 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004330#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004331 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004332#endif
4333 MYDB_END_ALLOW_THREADS;
4334 RETURN_IF_ERR();
4335 RETURN_NONE();
4336}
4337
4338
4339static PyObject*
4340DBTxn_id(DBTxnObject* self, PyObject* args)
4341{
4342 int id;
4343
4344 if (!PyArg_ParseTuple(args, ":id"))
4345 return NULL;
4346
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004347 if (!self->txn) {
4348 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4349 "DBTxn must not be used after txn_commit or txn_abort"));
4350 return NULL;
4351 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004352 MYDB_BEGIN_ALLOW_THREADS;
4353#if (DBVER >= 40)
4354 id = self->txn->id(self->txn);
4355#else
4356 id = txn_id(self->txn);
4357#endif
4358 MYDB_END_ALLOW_THREADS;
4359 return PyInt_FromLong(id);
4360}
4361
4362/* --------------------------------------------------------------------- */
4363/* Method definition tables and type objects */
4364
4365static PyMethodDef DB_methods[] = {
4366 {"append", (PyCFunction)DB_append, METH_VARARGS},
4367#if (DBVER >= 33)
4368 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4369#endif
4370 {"close", (PyCFunction)DB_close, METH_VARARGS},
4371#if (DBVER >= 32)
4372 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4373 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4374#endif
4375 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4376 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4377 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4378 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00004379 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004380 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4381 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4382 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4383 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4384 {"join", (PyCFunction)DB_join, METH_VARARGS},
4385 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4386 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4387 {"items", (PyCFunction)DB_items, METH_VARARGS},
4388 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4389 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4390 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4391 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4392 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4393 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4394 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004395#if (DBVER >= 41)
4396 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4397#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004398 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4399 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4400 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4401 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4402 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4403 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4404 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4405 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4406 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4407#if (DBVER >= 32)
4408 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4409#endif
4410 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4411 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4412#if (DBVER >= 33)
4413 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4414#endif
4415 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4416 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4417 {"values", (PyCFunction)DB_values, METH_VARARGS},
4418 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4419 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4420 {NULL, NULL} /* sentinel */
4421};
4422
4423
4424static PyMappingMethods DB_mapping = {
4425 (inquiry)DB_length, /*mp_length*/
4426 (binaryfunc)DB_subscript, /*mp_subscript*/
4427 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4428};
4429
4430
4431static PyMethodDef DBCursor_methods[] = {
4432 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4433 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4434 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4435 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4436 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4437 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4438 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00004439 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004440 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4441 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4442 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4443 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4444 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4445 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4446 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4447 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004448 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004449 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004450 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4451 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4452 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4453 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4454 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4455 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4456 {NULL, NULL} /* sentinel */
4457};
4458
4459
4460static PyMethodDef DBEnv_methods[] = {
4461 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4462 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4463 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004464#if (DBVER >= 41)
4465 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4466 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4467 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4468#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004469#if (DBVER >= 40)
4470 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4471#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004472 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004473 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4474 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4475#if (DBVER >= 32)
4476 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4477#endif
4478 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4479 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4480 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4481 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4482 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4483#if (DBVER >= 32)
4484 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4485 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4486 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4487#endif
4488 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4489 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4490 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4491 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4492 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4493 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4494 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4495 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4496 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4497 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4498 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4499 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4500 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4501 {NULL, NULL} /* sentinel */
4502};
4503
4504
4505static PyMethodDef DBTxn_methods[] = {
4506 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4507 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4508 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4509 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4510 {NULL, NULL} /* sentinel */
4511};
4512
4513
4514static PyObject*
4515DB_getattr(DBObject* self, char *name)
4516{
4517 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4518}
4519
4520
4521static PyObject*
4522DBEnv_getattr(DBEnvObject* self, char *name)
4523{
4524 if (!strcmp(name, "db_home")) {
4525 CHECK_ENV_NOT_CLOSED(self);
4526 if (self->db_env->db_home == NULL) {
4527 RETURN_NONE();
4528 }
4529 return PyString_FromString(self->db_env->db_home);
4530 }
4531
4532 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4533}
4534
4535
4536static PyObject*
4537DBCursor_getattr(DBCursorObject* self, char *name)
4538{
4539 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4540}
4541
4542static PyObject*
4543DBTxn_getattr(DBTxnObject* self, char *name)
4544{
4545 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4546}
4547
4548static PyObject*
4549DBLock_getattr(DBLockObject* self, char *name)
4550{
4551 return NULL;
4552}
4553
4554statichere PyTypeObject DB_Type = {
4555 PyObject_HEAD_INIT(NULL)
4556 0, /*ob_size*/
4557 "DB", /*tp_name*/
4558 sizeof(DBObject), /*tp_basicsize*/
4559 0, /*tp_itemsize*/
4560 /* methods */
4561 (destructor)DB_dealloc, /*tp_dealloc*/
4562 0, /*tp_print*/
4563 (getattrfunc)DB_getattr, /*tp_getattr*/
4564 0, /*tp_setattr*/
4565 0, /*tp_compare*/
4566 0, /*tp_repr*/
4567 0, /*tp_as_number*/
4568 0, /*tp_as_sequence*/
4569 &DB_mapping,/*tp_as_mapping*/
4570 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004571#ifdef HAVE_WEAKREF
4572 0, /* tp_call */
4573 0, /* tp_str */
4574 0, /* tp_getattro */
4575 0, /* tp_setattro */
4576 0, /* tp_as_buffer */
4577 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4578 0, /* tp_doc */
4579 0, /* tp_traverse */
4580 0, /* tp_clear */
4581 0, /* tp_richcompare */
4582 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4583#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584};
4585
4586
4587statichere PyTypeObject DBCursor_Type = {
4588 PyObject_HEAD_INIT(NULL)
4589 0, /*ob_size*/
4590 "DBCursor", /*tp_name*/
4591 sizeof(DBCursorObject), /*tp_basicsize*/
4592 0, /*tp_itemsize*/
4593 /* methods */
4594 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4595 0, /*tp_print*/
4596 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4597 0, /*tp_setattr*/
4598 0, /*tp_compare*/
4599 0, /*tp_repr*/
4600 0, /*tp_as_number*/
4601 0, /*tp_as_sequence*/
4602 0, /*tp_as_mapping*/
4603 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004604#ifdef HAVE_WEAKREF
4605 0, /* tp_call */
4606 0, /* tp_str */
4607 0, /* tp_getattro */
4608 0, /* tp_setattro */
4609 0, /* tp_as_buffer */
4610 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4611 0, /* tp_doc */
4612 0, /* tp_traverse */
4613 0, /* tp_clear */
4614 0, /* tp_richcompare */
4615 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4616#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004617};
4618
4619
4620statichere PyTypeObject DBEnv_Type = {
4621 PyObject_HEAD_INIT(NULL)
4622 0, /*ob_size*/
4623 "DBEnv", /*tp_name*/
4624 sizeof(DBEnvObject), /*tp_basicsize*/
4625 0, /*tp_itemsize*/
4626 /* methods */
4627 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4628 0, /*tp_print*/
4629 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4630 0, /*tp_setattr*/
4631 0, /*tp_compare*/
4632 0, /*tp_repr*/
4633 0, /*tp_as_number*/
4634 0, /*tp_as_sequence*/
4635 0, /*tp_as_mapping*/
4636 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004637#ifdef HAVE_WEAKREF
4638 0, /* tp_call */
4639 0, /* tp_str */
4640 0, /* tp_getattro */
4641 0, /* tp_setattro */
4642 0, /* tp_as_buffer */
4643 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4644 0, /* tp_doc */
4645 0, /* tp_traverse */
4646 0, /* tp_clear */
4647 0, /* tp_richcompare */
4648 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4649#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004650};
4651
4652statichere PyTypeObject DBTxn_Type = {
4653 PyObject_HEAD_INIT(NULL)
4654 0, /*ob_size*/
4655 "DBTxn", /*tp_name*/
4656 sizeof(DBTxnObject), /*tp_basicsize*/
4657 0, /*tp_itemsize*/
4658 /* methods */
4659 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4660 0, /*tp_print*/
4661 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4662 0, /*tp_setattr*/
4663 0, /*tp_compare*/
4664 0, /*tp_repr*/
4665 0, /*tp_as_number*/
4666 0, /*tp_as_sequence*/
4667 0, /*tp_as_mapping*/
4668 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004669#ifdef HAVE_WEAKREF
4670 0, /* tp_call */
4671 0, /* tp_str */
4672 0, /* tp_getattro */
4673 0, /* tp_setattro */
4674 0, /* tp_as_buffer */
4675 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4676 0, /* tp_doc */
4677 0, /* tp_traverse */
4678 0, /* tp_clear */
4679 0, /* tp_richcompare */
4680 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4681#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682};
4683
4684
4685statichere PyTypeObject DBLock_Type = {
4686 PyObject_HEAD_INIT(NULL)
4687 0, /*ob_size*/
4688 "DBLock", /*tp_name*/
4689 sizeof(DBLockObject), /*tp_basicsize*/
4690 0, /*tp_itemsize*/
4691 /* methods */
4692 (destructor)DBLock_dealloc, /*tp_dealloc*/
4693 0, /*tp_print*/
4694 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4695 0, /*tp_setattr*/
4696 0, /*tp_compare*/
4697 0, /*tp_repr*/
4698 0, /*tp_as_number*/
4699 0, /*tp_as_sequence*/
4700 0, /*tp_as_mapping*/
4701 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004702#ifdef HAVE_WEAKREF
4703 0, /* tp_call */
4704 0, /* tp_str */
4705 0, /* tp_getattro */
4706 0, /* tp_setattro */
4707 0, /* tp_as_buffer */
4708 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4709 0, /* tp_doc */
4710 0, /* tp_traverse */
4711 0, /* tp_clear */
4712 0, /* tp_richcompare */
4713 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4714#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004715};
4716
4717
4718/* --------------------------------------------------------------------- */
4719/* Module-level functions */
4720
4721static PyObject*
4722DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4723{
4724 PyObject* dbenvobj = NULL;
4725 int flags = 0;
4726 char* kwnames[] = { "dbEnv", "flags", NULL};
4727
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004728 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4729 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730 return NULL;
4731 if (dbenvobj == Py_None)
4732 dbenvobj = NULL;
4733 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4734 makeTypeError("DBEnv", dbenvobj);
4735 return NULL;
4736 }
4737
4738 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4739}
4740
4741
4742static PyObject*
4743DBEnv_construct(PyObject* self, PyObject* args)
4744{
4745 int flags = 0;
4746 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4747 return (PyObject* )newDBEnvObject(flags);
4748}
4749
4750
4751static char bsddb_version_doc[] =
4752"Returns a tuple of major, minor, and patch release numbers of the\n\
4753underlying DB library.";
4754
4755static PyObject*
4756bsddb_version(PyObject* self, PyObject* args)
4757{
4758 int major, minor, patch;
4759
4760 if (!PyArg_ParseTuple(args, ":version"))
4761 return NULL;
4762 db_version(&major, &minor, &patch);
4763 return Py_BuildValue("(iii)", major, minor, patch);
4764}
4765
4766
4767/* List of functions defined in the module */
4768
4769static PyMethodDef bsddb_methods[] = {
4770 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4771 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4772 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4773 {NULL, NULL} /* sentinel */
4774};
4775
4776
4777/* --------------------------------------------------------------------- */
4778/* Module initialization */
4779
4780
4781/* Convenience routine to export an integer value.
4782 * Errors are silently ignored, for better or for worse...
4783 */
4784#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4785
Gregory P. Smith41631e82003-09-21 00:08:14 +00004786#define MODULE_NAME_MAX_LEN 11
4787static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004788
4789DL_EXPORT(void) init_bsddb(void)
4790{
4791 PyObject* m;
4792 PyObject* d;
4793 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4794 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4795 PyObject* cvsid_s = PyString_FromString( rcs_id );
4796
4797 /* Initialize the type of the new type objects here; doing it here
4798 is required for portability to Windows without requiring C++. */
4799 DB_Type.ob_type = &PyType_Type;
4800 DBCursor_Type.ob_type = &PyType_Type;
4801 DBEnv_Type.ob_type = &PyType_Type;
4802 DBTxn_Type.ob_type = &PyType_Type;
4803 DBLock_Type.ob_type = &PyType_Type;
4804
4805
Mark Hammonda69d4092003-04-22 23:13:27 +00004806#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004808 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809#endif
4810
4811 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004812 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813
4814 /* Add some symbolic constants to the module */
4815 d = PyModule_GetDict(m);
4816 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4817 PyDict_SetItemString(d, "cvsid", cvsid_s);
4818 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4819 Py_DECREF(pybsddb_version_s);
4820 pybsddb_version_s = NULL;
4821 Py_DECREF(cvsid_s);
4822 cvsid_s = NULL;
4823 Py_DECREF(db_version_s);
4824 db_version_s = NULL;
4825
4826 ADD_INT(d, DB_VERSION_MAJOR);
4827 ADD_INT(d, DB_VERSION_MINOR);
4828 ADD_INT(d, DB_VERSION_PATCH);
4829
4830 ADD_INT(d, DB_MAX_PAGES);
4831 ADD_INT(d, DB_MAX_RECORDS);
4832
Gregory P. Smith41631e82003-09-21 00:08:14 +00004833#if (DBVER >= 42)
4834 ADD_INT(d, DB_RPCCLIENT);
4835#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004836 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004837 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4838 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4839#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004840 ADD_INT(d, DB_XA_CREATE);
4841
4842 ADD_INT(d, DB_CREATE);
4843 ADD_INT(d, DB_NOMMAP);
4844 ADD_INT(d, DB_THREAD);
4845
4846 ADD_INT(d, DB_FORCE);
4847 ADD_INT(d, DB_INIT_CDB);
4848 ADD_INT(d, DB_INIT_LOCK);
4849 ADD_INT(d, DB_INIT_LOG);
4850 ADD_INT(d, DB_INIT_MPOOL);
4851 ADD_INT(d, DB_INIT_TXN);
4852#if (DBVER >= 32)
4853 ADD_INT(d, DB_JOINENV);
4854#endif
4855
4856 ADD_INT(d, DB_RECOVER);
4857 ADD_INT(d, DB_RECOVER_FATAL);
4858 ADD_INT(d, DB_TXN_NOSYNC);
4859 ADD_INT(d, DB_USE_ENVIRON);
4860 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4861
4862 ADD_INT(d, DB_LOCKDOWN);
4863 ADD_INT(d, DB_PRIVATE);
4864 ADD_INT(d, DB_SYSTEM_MEM);
4865
4866 ADD_INT(d, DB_TXN_SYNC);
4867 ADD_INT(d, DB_TXN_NOWAIT);
4868
4869 ADD_INT(d, DB_EXCL);
4870 ADD_INT(d, DB_FCNTL_LOCKING);
4871 ADD_INT(d, DB_ODDFILESIZE);
4872 ADD_INT(d, DB_RDWRMASTER);
4873 ADD_INT(d, DB_RDONLY);
4874 ADD_INT(d, DB_TRUNCATE);
4875#if (DBVER >= 32)
4876 ADD_INT(d, DB_EXTENT);
4877 ADD_INT(d, DB_CDB_ALLDB);
4878 ADD_INT(d, DB_VERIFY);
4879#endif
4880 ADD_INT(d, DB_UPGRADE);
4881
4882 ADD_INT(d, DB_AGGRESSIVE);
4883 ADD_INT(d, DB_NOORDERCHK);
4884 ADD_INT(d, DB_ORDERCHKONLY);
4885 ADD_INT(d, DB_PR_PAGE);
4886#if ! (DBVER >= 33)
4887 ADD_INT(d, DB_VRFY_FLAGMASK);
4888 ADD_INT(d, DB_PR_HEADERS);
4889#endif
4890 ADD_INT(d, DB_PR_RECOVERYTEST);
4891 ADD_INT(d, DB_SALVAGE);
4892
4893 ADD_INT(d, DB_LOCK_NORUN);
4894 ADD_INT(d, DB_LOCK_DEFAULT);
4895 ADD_INT(d, DB_LOCK_OLDEST);
4896 ADD_INT(d, DB_LOCK_RANDOM);
4897 ADD_INT(d, DB_LOCK_YOUNGEST);
4898#if (DBVER >= 33)
4899 ADD_INT(d, DB_LOCK_MAXLOCKS);
4900 ADD_INT(d, DB_LOCK_MINLOCKS);
4901 ADD_INT(d, DB_LOCK_MINWRITE);
4902#endif
4903
4904
4905#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004906 /* docs say to use zero instead */
4907 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004908#else
4909 ADD_INT(d, DB_LOCK_CONFLICT);
4910#endif
4911
4912 ADD_INT(d, DB_LOCK_DUMP);
4913 ADD_INT(d, DB_LOCK_GET);
4914 ADD_INT(d, DB_LOCK_INHERIT);
4915 ADD_INT(d, DB_LOCK_PUT);
4916 ADD_INT(d, DB_LOCK_PUT_ALL);
4917 ADD_INT(d, DB_LOCK_PUT_OBJ);
4918
4919 ADD_INT(d, DB_LOCK_NG);
4920 ADD_INT(d, DB_LOCK_READ);
4921 ADD_INT(d, DB_LOCK_WRITE);
4922 ADD_INT(d, DB_LOCK_NOWAIT);
4923#if (DBVER >= 32)
4924 ADD_INT(d, DB_LOCK_WAIT);
4925#endif
4926 ADD_INT(d, DB_LOCK_IWRITE);
4927 ADD_INT(d, DB_LOCK_IREAD);
4928 ADD_INT(d, DB_LOCK_IWR);
4929#if (DBVER >= 33)
4930 ADD_INT(d, DB_LOCK_DIRTY);
4931 ADD_INT(d, DB_LOCK_WWRITE);
4932#endif
4933
4934 ADD_INT(d, DB_LOCK_RECORD);
4935 ADD_INT(d, DB_LOCK_UPGRADE);
4936#if (DBVER >= 32)
4937 ADD_INT(d, DB_LOCK_SWITCH);
4938#endif
4939#if (DBVER >= 33)
4940 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4941#endif
4942
4943 ADD_INT(d, DB_LOCK_NOWAIT);
4944 ADD_INT(d, DB_LOCK_RECORD);
4945 ADD_INT(d, DB_LOCK_UPGRADE);
4946
4947#if (DBVER >= 33)
4948 ADD_INT(d, DB_LSTAT_ABORTED);
4949 ADD_INT(d, DB_LSTAT_ERR);
4950 ADD_INT(d, DB_LSTAT_FREE);
4951 ADD_INT(d, DB_LSTAT_HELD);
4952#if (DBVER == 33)
4953 ADD_INT(d, DB_LSTAT_NOGRANT);
4954#endif
4955 ADD_INT(d, DB_LSTAT_PENDING);
4956 ADD_INT(d, DB_LSTAT_WAITING);
4957#endif
4958
4959 ADD_INT(d, DB_ARCH_ABS);
4960 ADD_INT(d, DB_ARCH_DATA);
4961 ADD_INT(d, DB_ARCH_LOG);
4962
4963 ADD_INT(d, DB_BTREE);
4964 ADD_INT(d, DB_HASH);
4965 ADD_INT(d, DB_RECNO);
4966 ADD_INT(d, DB_QUEUE);
4967 ADD_INT(d, DB_UNKNOWN);
4968
4969 ADD_INT(d, DB_DUP);
4970 ADD_INT(d, DB_DUPSORT);
4971 ADD_INT(d, DB_RECNUM);
4972 ADD_INT(d, DB_RENUMBER);
4973 ADD_INT(d, DB_REVSPLITOFF);
4974 ADD_INT(d, DB_SNAPSHOT);
4975
4976 ADD_INT(d, DB_JOIN_NOSORT);
4977
4978 ADD_INT(d, DB_AFTER);
4979 ADD_INT(d, DB_APPEND);
4980 ADD_INT(d, DB_BEFORE);
4981 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004982#if (DBVER >= 41)
4983 _addIntToDict(d, "DB_CHECKPOINT", 0);
4984#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004985 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004986 ADD_INT(d, DB_CURLSN);
4987#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004988#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004989 ADD_INT(d, DB_COMMIT);
4990#endif
4991 ADD_INT(d, DB_CONSUME);
4992#if (DBVER >= 32)
4993 ADD_INT(d, DB_CONSUME_WAIT);
4994#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004995 ADD_INT(d, DB_CURRENT);
4996#if (DBVER >= 33)
4997 ADD_INT(d, DB_FAST_STAT);
4998#endif
4999 ADD_INT(d, DB_FIRST);
5000 ADD_INT(d, DB_FLUSH);
5001 ADD_INT(d, DB_GET_BOTH);
5002 ADD_INT(d, DB_GET_RECNO);
5003 ADD_INT(d, DB_JOIN_ITEM);
5004 ADD_INT(d, DB_KEYFIRST);
5005 ADD_INT(d, DB_KEYLAST);
5006 ADD_INT(d, DB_LAST);
5007 ADD_INT(d, DB_NEXT);
5008 ADD_INT(d, DB_NEXT_DUP);
5009 ADD_INT(d, DB_NEXT_NODUP);
5010 ADD_INT(d, DB_NODUPDATA);
5011 ADD_INT(d, DB_NOOVERWRITE);
5012 ADD_INT(d, DB_NOSYNC);
5013 ADD_INT(d, DB_POSITION);
5014 ADD_INT(d, DB_PREV);
5015 ADD_INT(d, DB_PREV_NODUP);
5016 ADD_INT(d, DB_RECORDCOUNT);
5017 ADD_INT(d, DB_SET);
5018 ADD_INT(d, DB_SET_RANGE);
5019 ADD_INT(d, DB_SET_RECNO);
5020 ADD_INT(d, DB_WRITECURSOR);
5021
5022 ADD_INT(d, DB_OPFLAGS_MASK);
5023 ADD_INT(d, DB_RMW);
5024#if (DBVER >= 33)
5025 ADD_INT(d, DB_DIRTY_READ);
5026 ADD_INT(d, DB_MULTIPLE);
5027 ADD_INT(d, DB_MULTIPLE_KEY);
5028#endif
5029
5030#if (DBVER >= 33)
5031 ADD_INT(d, DB_DONOTINDEX);
5032#endif
5033
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005034#if (DBVER >= 41)
5035 _addIntToDict(d, "DB_INCOMPLETE", 0);
5036#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005037 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005038#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005039 ADD_INT(d, DB_KEYEMPTY);
5040 ADD_INT(d, DB_KEYEXIST);
5041 ADD_INT(d, DB_LOCK_DEADLOCK);
5042 ADD_INT(d, DB_LOCK_NOTGRANTED);
5043 ADD_INT(d, DB_NOSERVER);
5044 ADD_INT(d, DB_NOSERVER_HOME);
5045 ADD_INT(d, DB_NOSERVER_ID);
5046 ADD_INT(d, DB_NOTFOUND);
5047 ADD_INT(d, DB_OLD_VERSION);
5048 ADD_INT(d, DB_RUNRECOVERY);
5049 ADD_INT(d, DB_VERIFY_BAD);
5050#if (DBVER >= 33)
5051 ADD_INT(d, DB_PAGE_NOTFOUND);
5052 ADD_INT(d, DB_SECONDARY_BAD);
5053#endif
5054#if (DBVER >= 40)
5055 ADD_INT(d, DB_STAT_CLEAR);
5056 ADD_INT(d, DB_REGION_INIT);
5057 ADD_INT(d, DB_NOLOCKING);
5058 ADD_INT(d, DB_YIELDCPU);
5059 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5060 ADD_INT(d, DB_NOPANIC);
5061#endif
5062
Gregory P. Smith41631e82003-09-21 00:08:14 +00005063#if (DBVER >= 42)
5064 ADD_INT(d, DB_TIME_NOTGRANTED);
5065 ADD_INT(d, DB_TXN_NOT_DURABLE);
5066 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5067 ADD_INT(d, DB_LOG_AUTOREMOVE);
5068 ADD_INT(d, DB_DIRECT_LOG);
5069 ADD_INT(d, DB_DIRECT_DB);
5070 ADD_INT(d, DB_INIT_REP);
5071 ADD_INT(d, DB_ENCRYPT);
5072 ADD_INT(d, DB_CHKSUM);
5073#endif
5074
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005075#if (DBVER >= 41)
5076 ADD_INT(d, DB_ENCRYPT_AES);
5077 ADD_INT(d, DB_AUTO_COMMIT);
5078#else
5079 /* allow berkeleydb 4.1 aware apps to run on older versions */
5080 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5081#endif
5082
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005083 ADD_INT(d, EINVAL);
5084 ADD_INT(d, EACCES);
5085 ADD_INT(d, ENOSPC);
5086 ADD_INT(d, ENOMEM);
5087 ADD_INT(d, EAGAIN);
5088 ADD_INT(d, EBUSY);
5089 ADD_INT(d, EEXIST);
5090 ADD_INT(d, ENOENT);
5091 ADD_INT(d, EPERM);
5092
Barry Warsaw1baa9822003-03-31 19:51:29 +00005093#if (DBVER >= 40)
5094 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5095 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5096#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005097
5098 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005099 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005100 PyDict_SetItemString(d, "DBError", DBError);
5101
5102 /* Some magic to make DBNotFoundError derive from both DBError and
5103 KeyError, since the API only supports using one base class. */
5104 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5105 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
5106 Py_file_input, d, d);
5107 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5108 PyDict_DelItemString(d, "KeyError");
5109
5110
5111 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005112#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005113 PyDict_SetItemString(d, #name, name)
5114
5115#if !INCOMPLETE_IS_WARNING
5116 MAKE_EX(DBIncompleteError);
5117#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005118 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005119 MAKE_EX(DBKeyEmptyError);
5120 MAKE_EX(DBKeyExistError);
5121 MAKE_EX(DBLockDeadlockError);
5122 MAKE_EX(DBLockNotGrantedError);
5123 MAKE_EX(DBOldVersionError);
5124 MAKE_EX(DBRunRecoveryError);
5125 MAKE_EX(DBVerifyBadError);
5126 MAKE_EX(DBNoServerError);
5127 MAKE_EX(DBNoServerHomeError);
5128 MAKE_EX(DBNoServerIDError);
5129#if (DBVER >= 33)
5130 MAKE_EX(DBPageNotFoundError);
5131 MAKE_EX(DBSecondaryBadError);
5132#endif
5133
5134 MAKE_EX(DBInvalidArgError);
5135 MAKE_EX(DBAccessError);
5136 MAKE_EX(DBNoSpaceError);
5137 MAKE_EX(DBNoMemoryError);
5138 MAKE_EX(DBAgainError);
5139 MAKE_EX(DBBusyError);
5140 MAKE_EX(DBFileExistsError);
5141 MAKE_EX(DBNoSuchFileError);
5142 MAKE_EX(DBPermissionsError);
5143
5144#undef MAKE_EX
5145
5146 /* Check for errors */
5147 if (PyErr_Occurred()) {
5148 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005149 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005150 }
5151}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005152
5153/* allow this module to be named _pybsddb so that it can be installed
5154 * and imported on top of python >= 2.3 that includes its own older
5155 * copy of the library named _bsddb without importing the old version. */
5156DL_EXPORT(void) init_pybsddb(void)
5157{
5158 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5159 init_bsddb();
5160}