blob: b86cd7823186a99b6f30754850432a56846af38c [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. Smitha703a212003-11-03 01:04:41 +0000100#define PY_BSDDB_VERSION "4.2.4"
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. Smith455d46f2003-07-09 04:45:59 +0000197struct behaviourFlags {
198 /* What is the default behaviour when DB->get or DBCursor->get returns a
199 DB_NOTFOUND error? Return None or raise an exception? */
200 unsigned int getReturnsNone : 1;
201 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
202 * returns a DB_NOTFOUND error? Return None or raise an exception? */
203 unsigned int cursorSetReturnsNone : 1;
204};
205
206#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000207#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000208
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000209typedef struct {
210 PyObject_HEAD
211 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000212 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000213 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000214 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000215} DBEnvObject;
216
217
218typedef struct {
219 PyObject_HEAD
220 DB* db;
221 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000222 u_int32_t flags; /* saved flags from open() */
223 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000224 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000225 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000226#if (DBVER >= 33)
227 PyObject* associateCallback;
228 int primaryDBType;
229#endif
230} DBObject;
231
232
233typedef struct {
234 PyObject_HEAD
235 DBC* dbc;
236 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000237#ifdef HAVE_WEAKREF
238 PyObject *in_weakreflist; /* List of weak references */
239#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240} DBCursorObject;
241
242
243typedef struct {
244 PyObject_HEAD
245 DB_TXN* txn;
246} DBTxnObject;
247
248
249typedef struct {
250 PyObject_HEAD
251 DB_LOCK lock;
252} DBLockObject;
253
254
255
256staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
257
258#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
259#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
260#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
261#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
262#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
263
264
265/* --------------------------------------------------------------------- */
266/* Utility macros and functions */
267
268#define RETURN_IF_ERR() \
269 if (makeDBError(err)) { \
270 return NULL; \
271 }
272
273#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
274
Gregory P. Smithe2767172003-11-02 08:06:29 +0000275#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
276 if ((nonNull) == NULL) { \
277 PyObject *errTuple = NULL; \
278 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
279 PyErr_SetObject((pyErrObj), errTuple); \
280 Py_DECREF(errTuple); \
281 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000282 }
283
Gregory P. Smithe2767172003-11-02 08:06:29 +0000284#define CHECK_DB_NOT_CLOSED(dbobj) \
285 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
286
287#define CHECK_ENV_NOT_CLOSED(env) \
288 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000289
290#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000291 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000292
293
294#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
295 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
296
297#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
298
299#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
300 dbt.data != NULL) { free(dbt.data); }
301
302
303static int makeDBError(int err);
304
305
306/* Return the access method type of the DBObject */
307static int _DB_get_type(DBObject* self)
308{
309#if (DBVER >= 33)
310 DBTYPE type;
311 int err;
312 err = self->db->get_type(self->db, &type);
313 if (makeDBError(err)) {
314 return -1;
315 }
316 return type;
317#else
318 return self->db->get_type(self->db);
319#endif
320}
321
322
323/* Create a DBT structure (containing key and data values) from Python
324 strings. Returns 1 on success, 0 on an error. */
325static int make_dbt(PyObject* obj, DBT* dbt)
326{
327 CLEAR_DBT(*dbt);
328 if (obj == Py_None) {
329 /* no need to do anything, the structure has already been zeroed */
330 }
331 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
332 PyErr_SetString(PyExc_TypeError,
333 "Key and Data values must be of type string or None.");
334 return 0;
335 }
336 return 1;
337}
338
339
340/* Recno and Queue DBs can have integer keys. This function figures out
341 what's been given, verifies that it's allowed, and then makes the DBT.
342
343 Caller should call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000344static int
345make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346{
347 db_recno_t recno;
348 int type;
349
350 CLEAR_DBT(*key);
351 if (keyobj == Py_None) { /* TODO: is None really okay for keys? */
352 /* no need to do anything, the structure has already been zeroed */
353 }
354
355 else if (PyString_Check(keyobj)) {
356 /* verify access method type */
357 type = _DB_get_type(self);
358 if (type == -1)
359 return 0;
360 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000361 PyErr_SetString(
362 PyExc_TypeError,
363 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000364 return 0;
365 }
366
367 key->data = PyString_AS_STRING(keyobj);
368 key->size = PyString_GET_SIZE(keyobj);
369 }
370
371 else if (PyInt_Check(keyobj)) {
372 /* verify access method type */
373 type = _DB_get_type(self);
374 if (type == -1)
375 return 0;
376 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000377 /* if BTREE then an Integer key is allowed with the
378 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000379 *pflags |= DB_SET_RECNO;
380 }
381 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000382 PyErr_SetString(
383 PyExc_TypeError,
384 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000385 return 0;
386 }
387
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000388 /* Make a key out of the requested recno, use allocated space so DB
389 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000390 recno = PyInt_AS_LONG(keyobj);
391 key->data = malloc(sizeof(db_recno_t));
392 if (key->data == NULL) {
393 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
394 return 0;
395 }
396 key->ulen = key->size = sizeof(db_recno_t);
397 memcpy(key->data, &recno, sizeof(db_recno_t));
398 key->flags = DB_DBT_REALLOC;
399 }
400 else {
401 PyErr_Format(PyExc_TypeError,
402 "String or Integer object expected for key, %s found",
403 keyobj->ob_type->tp_name);
404 return 0;
405 }
406
407 return 1;
408}
409
410
411/* Add partial record access to an existing DBT data struct.
412 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
413 and the data storage/retrieval will be done using dlen and doff. */
414static int add_partial_dbt(DBT* d, int dlen, int doff) {
415 /* if neither were set we do nothing (-1 is the default value) */
416 if ((dlen == -1) && (doff == -1)) {
417 return 1;
418 }
419
420 if ((dlen < 0) || (doff < 0)) {
421 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
422 return 0;
423 }
424
425 d->flags = d->flags | DB_DBT_PARTIAL;
426 d->dlen = (unsigned int) dlen;
427 d->doff = (unsigned int) doff;
428 return 1;
429}
430
431
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000432/* Callback used to save away more information about errors from the DB
433 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000434static char _db_errmsg[1024];
435static void _db_errorCallback(const char* prefix, char* msg)
436{
437 strcpy(_db_errmsg, msg);
438}
439
440
441/* make a nice exception object to raise for errors. */
442static int makeDBError(int err)
443{
444 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000445 PyObject *errObj = NULL;
446 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 int exceptionRaised = 0;
448
449 switch (err) {
450 case 0: /* successful, no error */ break;
451
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000452#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000453 case DB_INCOMPLETE:
454#if INCOMPLETE_IS_WARNING
455 strcpy(errTxt, db_strerror(err));
456 if (_db_errmsg[0]) {
457 strcat(errTxt, " -- ");
458 strcat(errTxt, _db_errmsg);
459 _db_errmsg[0] = 0;
460 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000461/* if Python 2.1 or better use warning framework */
462#if PYTHON_API_VERSION >= 1010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000463 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
464#else
465 fprintf(stderr, errTxt);
466 fprintf(stderr, "\n");
467#endif
468
469#else /* do an exception instead */
470 errObj = DBIncompleteError;
471#endif
472 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000473#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000474
475 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
476 case DB_KEYEXIST: errObj = DBKeyExistError; break;
477 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
478 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
479 case DB_NOTFOUND: errObj = DBNotFoundError; break;
480 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
481 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
482 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
483 case DB_NOSERVER: errObj = DBNoServerError; break;
484 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
485 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
486#if (DBVER >= 33)
487 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
488 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
489#endif
490
491 case EINVAL: errObj = DBInvalidArgError; break;
492 case EACCES: errObj = DBAccessError; break;
493 case ENOSPC: errObj = DBNoSpaceError; break;
494 case ENOMEM: errObj = DBNoMemoryError; break;
495 case EAGAIN: errObj = DBAgainError; break;
496 case EBUSY : errObj = DBBusyError; break;
497 case EEXIST: errObj = DBFileExistsError; break;
498 case ENOENT: errObj = DBNoSuchFileError; break;
499 case EPERM : errObj = DBPermissionsError; break;
500
501 default: errObj = DBError; break;
502 }
503
504 if (errObj != NULL) {
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +0000505 /* FIXME this needs proper bounds checking on errTxt */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000506 strcpy(errTxt, db_strerror(err));
507 if (_db_errmsg[0]) {
508 strcat(errTxt, " -- ");
509 strcat(errTxt, _db_errmsg);
510 _db_errmsg[0] = 0;
511 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000512
513 errTuple = Py_BuildValue("(is)", err, errTxt);
514 PyErr_SetObject(errObj, errTuple);
515 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000516 }
517
518 return ((errObj != NULL) || exceptionRaised);
519}
520
521
522
523/* set a type exception */
524static void makeTypeError(char* expected, PyObject* found)
525{
526 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
527 expected, found->ob_type->tp_name);
528}
529
530
531/* verify that an obj is either None or a DBTxn, and set the txn pointer */
532static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
533{
534 if (txnobj == Py_None || txnobj == NULL) {
535 *txn = NULL;
536 return 1;
537 }
538 if (DBTxnObject_Check(txnobj)) {
539 *txn = ((DBTxnObject*)txnobj)->txn;
540 return 1;
541 }
542 else
543 makeTypeError("DBTxn", txnobj);
544 return 0;
545}
546
547
548/* Delete a key from a database
549 Returns 0 on success, -1 on an error. */
550static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
551{
552 int err;
553
554 MYDB_BEGIN_ALLOW_THREADS;
555 err = self->db->del(self->db, txn, key, 0);
556 MYDB_END_ALLOW_THREADS;
557 if (makeDBError(err)) {
558 return -1;
559 }
560 self->haveStat = 0;
561 return 0;
562}
563
564
565/* Store a key into a database
566 Returns 0 on success, -1 on an error. */
567static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
568{
569 int err;
570
571 MYDB_BEGIN_ALLOW_THREADS;
572 err = self->db->put(self->db, txn, key, data, flags);
573 MYDB_END_ALLOW_THREADS;
574 if (makeDBError(err)) {
575 return -1;
576 }
577 self->haveStat = 0;
578 return 0;
579}
580
581/* Get a key/data pair from a cursor */
582static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
583 PyObject *args, PyObject *kwargs, char *format)
584{
585 int err;
586 PyObject* retval = NULL;
587 DBT key, data;
588 int dlen = -1;
589 int doff = -1;
590 int flags = 0;
591 char* kwnames[] = { "flags", "dlen", "doff", NULL };
592
593 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
594 &flags, &dlen, &doff))
595 return NULL;
596
597 CHECK_CURSOR_NOT_CLOSED(self);
598
599 flags |= extra_flags;
600 CLEAR_DBT(key);
601 CLEAR_DBT(data);
602 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
603 /* Tell BerkeleyDB to malloc the return value (thread safe) */
604 data.flags = DB_DBT_MALLOC;
605 key.flags = DB_DBT_MALLOC;
606 }
607 if (!add_partial_dbt(&data, dlen, doff))
608 return NULL;
609
610 MYDB_BEGIN_ALLOW_THREADS;
611 err = self->dbc->c_get(self->dbc, &key, &data, flags);
612 MYDB_END_ALLOW_THREADS;
613
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000614 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000615 Py_INCREF(Py_None);
616 retval = Py_None;
617 }
618 else if (makeDBError(err)) {
619 retval = NULL;
620 }
621 else { /* otherwise, success! */
622
623 /* if Recno or Queue, return the key as an Int */
624 switch (_DB_get_type(self->mydb)) {
625 case -1:
626 retval = NULL;
627 break;
628
629 case DB_RECNO:
630 case DB_QUEUE:
631 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
632 data.data, data.size);
633 break;
634 case DB_HASH:
635 case DB_BTREE:
636 default:
637 retval = Py_BuildValue("s#s#", key.data, key.size,
638 data.data, data.size);
639 break;
640 }
641 }
642 if (!err) {
643 FREE_DBT(key);
644 FREE_DBT(data);
645 }
646 return retval;
647}
648
649
650/* add an integer to a dictionary using the given name as a key */
651static void _addIntToDict(PyObject* dict, char *name, int value)
652{
653 PyObject* v = PyInt_FromLong((long) value);
654 if (!v || PyDict_SetItemString(dict, name, v))
655 PyErr_Clear();
656
657 Py_XDECREF(v);
658}
659
660
661
662
663/* --------------------------------------------------------------------- */
664/* Allocators and deallocators */
665
666static DBObject*
667newDBObject(DBEnvObject* arg, int flags)
668{
669 DBObject* self;
670 DB_ENV* db_env = NULL;
671 int err;
672
673#if PYTHON_API_VERSION <= 1007
674 /* 1.5 compatibility */
675 self = PyObject_NEW(DBObject, &DB_Type);
676#else
677 self = PyObject_New(DBObject, &DB_Type);
678#endif
679
680 if (self == NULL)
681 return NULL;
682
683 self->haveStat = 0;
684 self->flags = 0;
685 self->setflags = 0;
686 self->myenvobj = NULL;
687#if (DBVER >= 33)
688 self->associateCallback = NULL;
689 self->primaryDBType = 0;
690#endif
691
692 /* keep a reference to our python DBEnv object */
693 if (arg) {
694 Py_INCREF(arg);
695 self->myenvobj = arg;
696 db_env = arg->db_env;
697 }
698
699 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000700 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000701 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000702 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
703 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000704
705 MYDB_BEGIN_ALLOW_THREADS;
706 err = db_create(&self->db, db_env, flags);
707 self->db->set_errcall(self->db, _db_errorCallback);
708#if (DBVER >= 33)
709 self->db->app_private = (void*)self;
710#endif
711 MYDB_END_ALLOW_THREADS;
712 if (makeDBError(err)) {
713 if (self->myenvobj) {
714 Py_DECREF(self->myenvobj);
715 self->myenvobj = NULL;
716 }
717 self = NULL;
718 }
719 return self;
720}
721
722
723static void
724DB_dealloc(DBObject* self)
725{
726 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000727 /* avoid closing a DB when its DBEnv has been closed out from under
728 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000729 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000730 (self->myenvobj && self->myenvobj->db_env))
731 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000732 MYDB_BEGIN_ALLOW_THREADS;
733 self->db->close(self->db, 0);
734 MYDB_END_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000735 /* if Python 2.1 or better use warning framework */
736#if PYTHON_API_VERSION >= 1010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 } else {
738 PyErr_Warn(PyExc_RuntimeWarning,
739 "DB could not be closed in destructor: DBEnv already closed");
740#endif
741 }
742 self->db = NULL;
743 }
744 if (self->myenvobj) {
745 Py_DECREF(self->myenvobj);
746 self->myenvobj = NULL;
747 }
748#if (DBVER >= 33)
749 if (self->associateCallback != NULL) {
750 Py_DECREF(self->associateCallback);
751 self->associateCallback = NULL;
752 }
753#endif
754#if PYTHON_API_VERSION <= 1007
755 PyMem_DEL(self);
756#else
757 PyObject_Del(self);
758#endif
759}
760
761
762static DBCursorObject*
763newDBCursorObject(DBC* dbc, DBObject* db)
764{
765 DBCursorObject* self;
766#if PYTHON_API_VERSION <= 1007
767 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
768#else
769 self = PyObject_New(DBCursorObject, &DBCursor_Type);
770#endif
771 if (self == NULL)
772 return NULL;
773
774 self->dbc = dbc;
775 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000776#ifdef HAVE_WEAKREF
777 self->in_weakreflist = NULL;
778#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000779 Py_INCREF(self->mydb);
780 return self;
781}
782
783
784static void
785DBCursor_dealloc(DBCursorObject* self)
786{
787 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000788
789#ifdef HAVE_WEAKREF
790 if (self->in_weakreflist != NULL) {
791 PyObject_ClearWeakRefs((PyObject *) self);
792 }
793#endif
794
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 if (self->dbc != NULL) {
796 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000797 /* If the underlying database has been closed, we don't
798 need to do anything. If the environment has been closed
799 we need to leak, as BerkeleyDB will crash trying to access
800 the environment. There was an exception when the
801 user closed the environment even though there still was
802 a database open. */
803 if (self->mydb->db && self->mydb->myenvobj &&
804 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000805 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000806 self->dbc = NULL;
807 MYDB_END_ALLOW_THREADS;
808 }
809 Py_XDECREF( self->mydb );
810#if PYTHON_API_VERSION <= 1007
811 PyMem_DEL(self);
812#else
813 PyObject_Del(self);
814#endif
815}
816
817
818static DBEnvObject*
819newDBEnvObject(int flags)
820{
821 int err;
822 DBEnvObject* self;
823#if PYTHON_API_VERSION <= 1007
824 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
825#else
826 self = PyObject_New(DBEnvObject, &DBEnv_Type);
827#endif
828
829 if (self == NULL)
830 return NULL;
831
832 self->closed = 1;
833 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000834 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
835 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000836
837 MYDB_BEGIN_ALLOW_THREADS;
838 err = db_env_create(&self->db_env, flags);
839 MYDB_END_ALLOW_THREADS;
840 if (makeDBError(err)) {
841 self = NULL;
842 }
843 else {
844 self->db_env->set_errcall(self->db_env, _db_errorCallback);
845 }
846 return self;
847}
848
849
850static void
851DBEnv_dealloc(DBEnvObject* self)
852{
853 if (!self->closed) {
854 MYDB_BEGIN_ALLOW_THREADS;
855 self->db_env->close(self->db_env, 0);
856 MYDB_END_ALLOW_THREADS;
857 }
858#if PYTHON_API_VERSION <= 1007
859 PyMem_DEL(self);
860#else
861 PyObject_Del(self);
862#endif
863}
864
865
866static DBTxnObject*
867newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
868{
869 int err;
870 DBTxnObject* self;
871
872#if PYTHON_API_VERSION <= 1007
873 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
874#else
875 self = PyObject_New(DBTxnObject, &DBTxn_Type);
876#endif
877 if (self == NULL)
878 return NULL;
879
880 MYDB_BEGIN_ALLOW_THREADS;
881#if (DBVER >= 40)
882 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
883#else
884 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
885#endif
886 MYDB_END_ALLOW_THREADS;
887 if (makeDBError(err)) {
888 self = NULL;
889 }
890 return self;
891}
892
893
894static void
895DBTxn_dealloc(DBTxnObject* self)
896{
897 /* XXX nothing to do for transaction objects?!? */
898
899 /* TODO: if it hasn't been commited, should we abort it? */
900
901#if PYTHON_API_VERSION <= 1007
902 PyMem_DEL(self);
903#else
904 PyObject_Del(self);
905#endif
906}
907
908
909static DBLockObject*
910newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
911 db_lockmode_t lock_mode, int flags)
912{
913 int err;
914 DBLockObject* self;
915
916#if PYTHON_API_VERSION <= 1007
917 self = PyObject_NEW(DBLockObject, &DBLock_Type);
918#else
919 self = PyObject_New(DBLockObject, &DBLock_Type);
920#endif
921 if (self == NULL)
922 return NULL;
923
924 MYDB_BEGIN_ALLOW_THREADS;
925#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000926 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
927 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928#else
929 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
930#endif
931 MYDB_END_ALLOW_THREADS;
932 if (makeDBError(err)) {
933 self = NULL;
934 }
935
936 return self;
937}
938
939
940static void
941DBLock_dealloc(DBLockObject* self)
942{
943 /* TODO: if it hasn't been released, should we do it? */
944
945#if PYTHON_API_VERSION <= 1007
946 PyMem_DEL(self);
947#else
948 PyObject_Del(self);
949#endif
950}
951
952
953/* --------------------------------------------------------------------- */
954/* DB methods */
955
956static PyObject*
957DB_append(DBObject* self, PyObject* args)
958{
959 PyObject* txnobj = NULL;
960 PyObject* dataobj;
961 db_recno_t recno;
962 DBT key, data;
963 DB_TXN *txn = NULL;
964
965 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
966 return NULL;
967
968 CHECK_DB_NOT_CLOSED(self);
969
970 /* make a dummy key out of a recno */
971 recno = 0;
972 CLEAR_DBT(key);
973 key.data = &recno;
974 key.size = sizeof(recno);
975 key.ulen = key.size;
976 key.flags = DB_DBT_USERMEM;
977
978 if (!make_dbt(dataobj, &data)) return NULL;
979 if (!checkTxnObj(txnobj, &txn)) return NULL;
980
981 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
982 return NULL;
983
984 return PyInt_FromLong(recno);
985}
986
987
988#if (DBVER >= 33)
989
990static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000991_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
992 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000993{
994 int retval = DB_DONOTINDEX;
995 DBObject* secondaryDB = (DBObject*)db->app_private;
996 PyObject* callback = secondaryDB->associateCallback;
997 int type = secondaryDB->primaryDBType;
998 PyObject* key;
999 PyObject* data;
1000 PyObject* args;
1001 PyObject* result;
1002
1003
1004 if (callback != NULL) {
1005 MYDB_BEGIN_BLOCK_THREADS;
1006
1007 if (type == DB_RECNO || type == DB_QUEUE) {
1008 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1009 }
1010 else {
1011 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1012 }
1013 data = PyString_FromStringAndSize(priData->data, priData->size);
1014 args = PyTuple_New(2);
1015 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1016 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1017
1018 result = PyEval_CallObject(callback, args);
1019
1020 if (result == NULL) {
1021 PyErr_Print();
1022 }
1023 else if (result == Py_None) {
1024 retval = DB_DONOTINDEX;
1025 }
1026 else if (PyInt_Check(result)) {
1027 retval = PyInt_AsLong(result);
1028 }
1029 else if (PyString_Check(result)) {
1030 char* data;
1031 int size;
1032
1033 CLEAR_DBT(*secKey);
1034#if PYTHON_API_VERSION <= 1007
1035 /* 1.5 compatibility */
1036 size = PyString_Size(result);
1037 data = PyString_AsString(result);
1038#else
1039 PyString_AsStringAndSize(result, &data, &size);
1040#endif
1041 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1042 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001043 if (secKey->data) {
1044 memcpy(secKey->data, data, size);
1045 secKey->size = size;
1046 retval = 0;
1047 }
1048 else {
1049 PyErr_SetString(PyExc_MemoryError,
1050 "malloc failed in _db_associateCallback");
1051 PyErr_Print();
1052 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001053 }
1054 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001055 PyErr_SetString(
1056 PyExc_TypeError,
1057 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058 PyErr_Print();
1059 }
1060
1061 Py_DECREF(args);
1062 if (result) {
1063 Py_DECREF(result);
1064 }
1065
1066 MYDB_END_BLOCK_THREADS;
1067 }
1068 return retval;
1069}
1070
1071
1072static PyObject*
1073DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1074{
1075 int err, flags=0;
1076 DBObject* secondaryDB;
1077 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001078#if (DBVER >= 41)
1079 PyObject *txnobj = NULL;
1080 DB_TXN *txn = NULL;
1081 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1082#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001083 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001084#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001085
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001086#if (DBVER >= 41)
1087 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1088 &secondaryDB, &callback, &flags,
1089 &txnobj)) {
1090#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001091 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001092 &secondaryDB, &callback, &flags)) {
1093#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001094 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001095 }
1096
1097#if (DBVER >= 41)
1098 if (!checkTxnObj(txnobj, &txn)) return NULL;
1099#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001100
1101 CHECK_DB_NOT_CLOSED(self);
1102 if (!DBObject_Check(secondaryDB)) {
1103 makeTypeError("DB", (PyObject*)secondaryDB);
1104 return NULL;
1105 }
1106 if (callback == Py_None) {
1107 callback = NULL;
1108 }
1109 else if (!PyCallable_Check(callback)) {
1110 makeTypeError("Callable", callback);
1111 return NULL;
1112 }
1113
1114 /* Save a reference to the callback in the secondary DB. */
1115 if (self->associateCallback != NULL) {
1116 Py_DECREF(self->associateCallback);
1117 }
1118 Py_INCREF(callback);
1119 secondaryDB->associateCallback = callback;
1120 secondaryDB->primaryDBType = _DB_get_type(self);
1121
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001122 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1123 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1124 * The global interepreter lock is not initialized until the first
1125 * thread is created using thread.start_new_thread() or fork() is
1126 * called. that would cause the ALLOW_THREADS here to segfault due
1127 * to a null pointer reference if no threads or child processes
1128 * have been created. This works around that and is a no-op if
1129 * threads have already been initialized.
1130 * (see pybsddb-users mailing list post on 2002-08-07)
1131 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001132#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001133 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001134#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001135 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001136#if (DBVER >= 41)
1137 err = self->db->associate(self->db,
1138 txn,
1139 secondaryDB->db,
1140 _db_associateCallback,
1141 flags);
1142#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001143 err = self->db->associate(self->db,
1144 secondaryDB->db,
1145 _db_associateCallback,
1146 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001147#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001148 MYDB_END_ALLOW_THREADS;
1149
1150 if (err) {
1151 Py_DECREF(self->associateCallback);
1152 self->associateCallback = NULL;
1153 secondaryDB->primaryDBType = 0;
1154 }
1155
1156 RETURN_IF_ERR();
1157 RETURN_NONE();
1158}
1159
1160
1161#endif
1162
1163
1164static PyObject*
1165DB_close(DBObject* self, PyObject* args)
1166{
1167 int err, flags=0;
1168 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1169 return NULL;
1170 if (self->db != NULL) {
1171 if (self->myenvobj)
1172 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001174 self->db = NULL;
1175 RETURN_IF_ERR();
1176 }
1177 RETURN_NONE();
1178}
1179
1180
1181#if (DBVER >= 32)
1182static PyObject*
1183_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1184{
1185 int err, flags=0, type;
1186 PyObject* txnobj = NULL;
1187 PyObject* retval = NULL;
1188 DBT key, data;
1189 DB_TXN *txn = NULL;
1190 char* kwnames[] = { "txn", "flags", NULL };
1191
1192 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1193 &txnobj, &flags))
1194 return NULL;
1195
1196 CHECK_DB_NOT_CLOSED(self);
1197 type = _DB_get_type(self);
1198 if (type == -1)
1199 return NULL;
1200 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001201 PyErr_SetString(PyExc_TypeError,
1202 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203 return NULL;
1204 }
1205 if (!checkTxnObj(txnobj, &txn))
1206 return NULL;
1207
1208 CLEAR_DBT(key);
1209 CLEAR_DBT(data);
1210 if (CHECK_DBFLAG(self, DB_THREAD)) {
1211 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1212 data.flags = DB_DBT_MALLOC;
1213 key.flags = DB_DBT_MALLOC;
1214 }
1215
1216 MYDB_BEGIN_ALLOW_THREADS;
1217 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1218 MYDB_END_ALLOW_THREADS;
1219
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001220 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001221 err = 0;
1222 Py_INCREF(Py_None);
1223 retval = Py_None;
1224 }
1225 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001226 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1227 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228 FREE_DBT(key);
1229 FREE_DBT(data);
1230 }
1231
1232 RETURN_IF_ERR();
1233 return retval;
1234}
1235
1236static PyObject*
1237DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1238{
1239 return _DB_consume(self, args, kwargs, DB_CONSUME);
1240}
1241
1242static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001243DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1244 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001245{
1246 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1247}
1248#endif
1249
1250
1251
1252static PyObject*
1253DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1254{
1255 int err, flags=0;
1256 DBC* dbc;
1257 PyObject* txnobj = NULL;
1258 DB_TXN *txn = NULL;
1259 char* kwnames[] = { "txn", "flags", NULL };
1260
1261 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1262 &txnobj, &flags))
1263 return NULL;
1264 CHECK_DB_NOT_CLOSED(self);
1265 if (!checkTxnObj(txnobj, &txn))
1266 return NULL;
1267
1268 MYDB_BEGIN_ALLOW_THREADS;
1269 err = self->db->cursor(self->db, txn, &dbc, flags);
1270 MYDB_END_ALLOW_THREADS;
1271 RETURN_IF_ERR();
1272 return (PyObject*) newDBCursorObject(dbc, self);
1273}
1274
1275
1276static PyObject*
1277DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1278{
1279 PyObject* txnobj = NULL;
1280 int flags = 0;
1281 PyObject* keyobj;
1282 DBT key;
1283 DB_TXN *txn = NULL;
1284 char* kwnames[] = { "key", "txn", "flags", NULL };
1285
1286 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1287 &keyobj, &txnobj, &flags))
1288 return NULL;
1289 CHECK_DB_NOT_CLOSED(self);
1290 if (!make_key_dbt(self, keyobj, &key, NULL))
1291 return NULL;
1292 if (!checkTxnObj(txnobj, &txn))
1293 return NULL;
1294
1295 if (-1 == _DB_delete(self, txn, &key, 0))
1296 return NULL;
1297
1298 FREE_DBT(key);
1299 RETURN_NONE();
1300}
1301
1302
1303static PyObject*
1304DB_fd(DBObject* self, PyObject* args)
1305{
1306 int err, the_fd;
1307
1308 if (!PyArg_ParseTuple(args,":fd"))
1309 return NULL;
1310 CHECK_DB_NOT_CLOSED(self);
1311
1312 MYDB_BEGIN_ALLOW_THREADS;
1313 err = self->db->fd(self->db, &the_fd);
1314 MYDB_END_ALLOW_THREADS;
1315 RETURN_IF_ERR();
1316 return PyInt_FromLong(the_fd);
1317}
1318
1319
1320static PyObject*
1321DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1322{
1323 int err, flags=0;
1324 PyObject* txnobj = NULL;
1325 PyObject* keyobj;
1326 PyObject* dfltobj = NULL;
1327 PyObject* retval = NULL;
1328 int dlen = -1;
1329 int doff = -1;
1330 DBT key, data;
1331 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001332 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333
1334 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001335 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1336 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001337 return NULL;
1338
1339 CHECK_DB_NOT_CLOSED(self);
1340 if (!make_key_dbt(self, keyobj, &key, &flags))
1341 return NULL;
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1344
1345 CLEAR_DBT(data);
1346 if (CHECK_DBFLAG(self, DB_THREAD)) {
1347 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1348 data.flags = DB_DBT_MALLOC;
1349 }
1350 if (!add_partial_dbt(&data, dlen, doff))
1351 return NULL;
1352
1353 MYDB_BEGIN_ALLOW_THREADS;
1354 err = self->db->get(self->db, txn, &key, &data, flags);
1355 MYDB_END_ALLOW_THREADS;
1356
1357 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1358 err = 0;
1359 Py_INCREF(dfltobj);
1360 retval = dfltobj;
1361 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001362 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1366 }
1367 else if (!err) {
1368 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1370 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 else /* return just the data */
1372 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1373 FREE_DBT(key);
1374 FREE_DBT(data);
1375 }
1376
1377 RETURN_IF_ERR();
1378 return retval;
1379}
1380
1381
1382/* Return size of entry */
1383static PyObject*
1384DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1385{
1386 int err, flags=0;
1387 PyObject* txnobj = NULL;
1388 PyObject* keyobj;
1389 PyObject* retval = NULL;
1390 DBT key, data;
1391 DB_TXN *txn = NULL;
1392 char* kwnames[] = { "key", "txn", NULL };
1393
1394 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1395 &keyobj, &txnobj))
1396 return NULL;
1397 CHECK_DB_NOT_CLOSED(self);
1398 if (!make_key_dbt(self, keyobj, &key, &flags))
1399 return NULL;
1400 if (!checkTxnObj(txnobj, &txn))
1401 return NULL;
1402 CLEAR_DBT(data);
1403
1404 /* We don't allocate any memory, forcing a ENOMEM error and thus
1405 getting the record size. */
1406 data.flags = DB_DBT_USERMEM;
1407 data.ulen = 0;
1408 MYDB_BEGIN_ALLOW_THREADS;
1409 err = self->db->get(self->db, txn, &key, &data, flags);
1410 MYDB_END_ALLOW_THREADS;
1411 if (err == ENOMEM) {
1412 retval = PyInt_FromLong((long)data.size);
1413 err = 0;
1414 }
1415
1416 FREE_DBT(key);
1417 FREE_DBT(data);
1418 RETURN_IF_ERR();
1419 return retval;
1420}
1421
1422
1423static PyObject*
1424DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1425{
1426 int err, flags=0;
1427 PyObject* txnobj = NULL;
1428 PyObject* keyobj;
1429 PyObject* dataobj;
1430 PyObject* retval = NULL;
1431 DBT key, data;
1432 DB_TXN *txn = NULL;
1433 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1434
1435
1436 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1437 &keyobj, &dataobj, &txnobj, &flags))
1438 return NULL;
1439
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
1443 if (!make_dbt(dataobj, &data))
1444 return NULL;
1445 if (!checkTxnObj(txnobj, &txn))
1446 return NULL;
1447
1448 flags |= DB_GET_BOTH;
1449
1450 if (CHECK_DBFLAG(self, DB_THREAD)) {
1451 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1452 data.flags = DB_DBT_MALLOC;
1453 /* TODO: Is this flag needed? We're passing a data object that should
1454 match what's in the DB, so there should be no need to malloc.
1455 We run the risk of freeing something twice! Check this. */
1456 }
1457
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->get(self->db, txn, &key, &data, flags);
1460 MYDB_END_ALLOW_THREADS;
1461
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001462 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001463 err = 0;
1464 Py_INCREF(Py_None);
1465 retval = Py_None;
1466 }
1467 else if (!err) {
1468 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1469 FREE_DBT(data); /* Only if retrieval was successful */
1470 }
1471
1472 FREE_DBT(key);
1473 RETURN_IF_ERR();
1474 return retval;
1475}
1476
1477
1478static PyObject*
1479DB_get_byteswapped(DBObject* self, PyObject* args)
1480{
1481#if (DBVER >= 33)
1482 int err = 0;
1483#endif
1484 int retval = -1;
1485
1486 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1487 return NULL;
1488 CHECK_DB_NOT_CLOSED(self);
1489
1490#if (DBVER >= 33)
1491 MYDB_BEGIN_ALLOW_THREADS;
1492 err = self->db->get_byteswapped(self->db, &retval);
1493 MYDB_END_ALLOW_THREADS;
1494 RETURN_IF_ERR();
1495#else
1496 MYDB_BEGIN_ALLOW_THREADS;
1497 retval = self->db->get_byteswapped(self->db);
1498 MYDB_END_ALLOW_THREADS;
1499#endif
1500 return PyInt_FromLong(retval);
1501}
1502
1503
1504static PyObject*
1505DB_get_type(DBObject* self, PyObject* args)
1506{
1507 int type;
1508
1509 if (!PyArg_ParseTuple(args,":get_type"))
1510 return NULL;
1511 CHECK_DB_NOT_CLOSED(self);
1512
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 type = _DB_get_type(self);
1515 MYDB_END_ALLOW_THREADS;
1516 if (type == -1)
1517 return NULL;
1518 return PyInt_FromLong(type);
1519}
1520
1521
1522static PyObject*
1523DB_join(DBObject* self, PyObject* args)
1524{
1525 int err, flags=0;
1526 int length, x;
1527 PyObject* cursorsObj;
1528 DBC** cursors;
1529 DBC* dbc;
1530
1531
1532 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1533 return NULL;
1534
1535 CHECK_DB_NOT_CLOSED(self);
1536
1537 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001538 PyErr_SetString(PyExc_TypeError,
1539 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001540 return NULL;
1541 }
1542
1543 length = PyObject_Length(cursorsObj);
1544 cursors = malloc((length+1) * sizeof(DBC*));
1545 cursors[length] = NULL;
1546 for (x=0; x<length; x++) {
1547 PyObject* item = PySequence_GetItem(cursorsObj, x);
1548 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001549 PyErr_SetString(PyExc_TypeError,
1550 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001551 free(cursors);
1552 return NULL;
1553 }
1554 cursors[x] = ((DBCursorObject*)item)->dbc;
1555 }
1556
1557 MYDB_BEGIN_ALLOW_THREADS;
1558 err = self->db->join(self->db, cursors, &dbc, flags);
1559 MYDB_END_ALLOW_THREADS;
1560 free(cursors);
1561 RETURN_IF_ERR();
1562
Gregory P. Smith7441e652003-11-03 21:35:31 +00001563 /* FIXME: this is a buggy interface. The returned cursor
1564 contains internal references to the passed in cursors
1565 but does not hold python references to them or prevent
1566 them from being closed prematurely. This can cause
1567 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001568 return (PyObject*) newDBCursorObject(dbc, self);
1569}
1570
1571
1572static PyObject*
1573DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1574{
1575 int err, flags=0;
1576 PyObject* txnobj = NULL;
1577 PyObject* keyobj;
1578 DBT key;
1579 DB_TXN *txn = NULL;
1580 DB_KEY_RANGE range;
1581 char* kwnames[] = { "key", "txn", "flags", NULL };
1582
1583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1584 &keyobj, &txnobj, &flags))
1585 return NULL;
1586 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001587 if (!make_dbt(keyobj, &key))
1588 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589 return NULL;
1590 if (!checkTxnObj(txnobj, &txn))
1591 return NULL;
1592
1593 MYDB_BEGIN_ALLOW_THREADS;
1594 err = self->db->key_range(self->db, txn, &key, &range, flags);
1595 MYDB_END_ALLOW_THREADS;
1596
1597 RETURN_IF_ERR();
1598 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1599}
1600
1601
1602static PyObject*
1603DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1604{
1605 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1606 char* filename = NULL;
1607 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001608#if (DBVER >= 41)
1609 PyObject *txnobj = NULL;
1610 DB_TXN *txn = NULL;
1611 /* with dbname */
1612 char* kwnames[] = {
1613 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1614 /* without dbname */
1615 char* kwnames_basic[] = {
1616 "filename", "dbtype", "flags", "mode", "txn", NULL};
1617#else
1618 /* with dbname */
1619 char* kwnames[] = {
1620 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1621 /* without dbname */
1622 char* kwnames_basic[] = {
1623 "filename", "dbtype", "flags", "mode", NULL};
1624#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001625
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001626#if (DBVER >= 41)
1627 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1628 &filename, &dbname, &type, &flags, &mode,
1629 &txnobj))
1630#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001632 &filename, &dbname, &type, &flags,
1633 &mode))
1634#endif
1635 {
1636 PyErr_Clear();
1637 type = DB_UNKNOWN; flags = 0; mode = 0660;
1638 filename = NULL; dbname = NULL;
1639#if (DBVER >= 41)
1640 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1641 kwnames_basic,
1642 &filename, &type, &flags, &mode,
1643 &txnobj))
1644 return NULL;
1645#else
1646 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1647 kwnames_basic,
1648 &filename, &type, &flags, &mode))
1649 return NULL;
1650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001651 }
1652
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001653#if (DBVER >= 41)
1654 if (!checkTxnObj(txnobj, &txn)) return NULL;
1655#endif
1656
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 if (NULL == self->db) {
1658 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1659 "Cannot call open() twice for DB object"));
1660 return NULL;
1661 }
1662
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001663#if 0 && (DBVER >= 41)
1664 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1665 && (self->myenvobj->flags & DB_INIT_TXN))
1666 {
1667 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1668 * explicitly passed) but we are in a transaction ready environment:
1669 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1670 * to work on BerkeleyDB 4.1 without needing to modify their
1671 * DBEnv or DB open calls.
1672 * TODO make this behaviour of the library configurable.
1673 */
1674 flags |= DB_AUTO_COMMIT;
1675 }
1676#endif
1677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001679#if (DBVER >= 41)
1680 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1681#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001682 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001683#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001684 MYDB_END_ALLOW_THREADS;
1685 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001686 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001687 self->db = NULL;
1688 return NULL;
1689 }
1690
1691 self->flags = flags;
1692 RETURN_NONE();
1693}
1694
1695
1696static PyObject*
1697DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1698{
1699 int flags=0;
1700 PyObject* txnobj = NULL;
1701 int dlen = -1;
1702 int doff = -1;
1703 PyObject* keyobj, *dataobj, *retval;
1704 DBT key, data;
1705 DB_TXN *txn = NULL;
1706 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1707
1708 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1709 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1710 return NULL;
1711
1712 CHECK_DB_NOT_CLOSED(self);
1713 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1714 if (!make_dbt(dataobj, &data)) return NULL;
1715 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1716 if (!checkTxnObj(txnobj, &txn)) return NULL;
1717
1718 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1719 FREE_DBT(key);
1720 return NULL;
1721 }
1722
1723 if (flags & DB_APPEND)
1724 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1725 else {
1726 retval = Py_None;
1727 Py_INCREF(retval);
1728 }
1729 FREE_DBT(key);
1730 return retval;
1731}
1732
1733
1734
1735static PyObject*
1736DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1737{
1738 char* filename;
1739 char* database = NULL;
1740 int err, flags=0;
1741 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1742
1743 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1744 &filename, &database, &flags))
1745 return NULL;
1746 CHECK_DB_NOT_CLOSED(self);
1747
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001748 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001749 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750 RETURN_IF_ERR();
1751 RETURN_NONE();
1752}
1753
1754
1755
1756static PyObject*
1757DB_rename(DBObject* self, PyObject* args)
1758{
1759 char* filename;
1760 char* database;
1761 char* newname;
1762 int err, flags=0;
1763
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001764 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1765 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001766 return NULL;
1767 CHECK_DB_NOT_CLOSED(self);
1768
1769 MYDB_BEGIN_ALLOW_THREADS;
1770 err = self->db->rename(self->db, filename, database, newname, flags);
1771 MYDB_END_ALLOW_THREADS;
1772 RETURN_IF_ERR();
1773 RETURN_NONE();
1774}
1775
1776
1777static PyObject*
1778DB_set_bt_minkey(DBObject* self, PyObject* args)
1779{
1780 int err, minkey;
1781
1782 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1783 return NULL;
1784 CHECK_DB_NOT_CLOSED(self);
1785
1786 MYDB_BEGIN_ALLOW_THREADS;
1787 err = self->db->set_bt_minkey(self->db, minkey);
1788 MYDB_END_ALLOW_THREADS;
1789 RETURN_IF_ERR();
1790 RETURN_NONE();
1791}
1792
1793
1794static PyObject*
1795DB_set_cachesize(DBObject* self, PyObject* args)
1796{
1797 int err;
1798 int gbytes = 0, bytes = 0, ncache = 0;
1799
1800 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1801 &gbytes,&bytes,&ncache))
1802 return NULL;
1803 CHECK_DB_NOT_CLOSED(self);
1804
1805 MYDB_BEGIN_ALLOW_THREADS;
1806 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1807 MYDB_END_ALLOW_THREADS;
1808 RETURN_IF_ERR();
1809 RETURN_NONE();
1810}
1811
1812
1813static PyObject*
1814DB_set_flags(DBObject* self, PyObject* args)
1815{
1816 int err, flags;
1817
1818 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1819 return NULL;
1820 CHECK_DB_NOT_CLOSED(self);
1821
1822 MYDB_BEGIN_ALLOW_THREADS;
1823 err = self->db->set_flags(self->db, flags);
1824 MYDB_END_ALLOW_THREADS;
1825 RETURN_IF_ERR();
1826
1827 self->setflags |= flags;
1828 RETURN_NONE();
1829}
1830
1831
1832static PyObject*
1833DB_set_h_ffactor(DBObject* self, PyObject* args)
1834{
1835 int err, ffactor;
1836
1837 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1838 return NULL;
1839 CHECK_DB_NOT_CLOSED(self);
1840
1841 MYDB_BEGIN_ALLOW_THREADS;
1842 err = self->db->set_h_ffactor(self->db, ffactor);
1843 MYDB_END_ALLOW_THREADS;
1844 RETURN_IF_ERR();
1845 RETURN_NONE();
1846}
1847
1848
1849static PyObject*
1850DB_set_h_nelem(DBObject* self, PyObject* args)
1851{
1852 int err, nelem;
1853
1854 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1855 return NULL;
1856 CHECK_DB_NOT_CLOSED(self);
1857
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->set_h_nelem(self->db, nelem);
1860 MYDB_END_ALLOW_THREADS;
1861 RETURN_IF_ERR();
1862 RETURN_NONE();
1863}
1864
1865
1866static PyObject*
1867DB_set_lorder(DBObject* self, PyObject* args)
1868{
1869 int err, lorder;
1870
1871 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1872 return NULL;
1873 CHECK_DB_NOT_CLOSED(self);
1874
1875 MYDB_BEGIN_ALLOW_THREADS;
1876 err = self->db->set_lorder(self->db, lorder);
1877 MYDB_END_ALLOW_THREADS;
1878 RETURN_IF_ERR();
1879 RETURN_NONE();
1880}
1881
1882
1883static PyObject*
1884DB_set_pagesize(DBObject* self, PyObject* args)
1885{
1886 int err, pagesize;
1887
1888 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1889 return NULL;
1890 CHECK_DB_NOT_CLOSED(self);
1891
1892 MYDB_BEGIN_ALLOW_THREADS;
1893 err = self->db->set_pagesize(self->db, pagesize);
1894 MYDB_END_ALLOW_THREADS;
1895 RETURN_IF_ERR();
1896 RETURN_NONE();
1897}
1898
1899
1900static PyObject*
1901DB_set_re_delim(DBObject* self, PyObject* args)
1902{
1903 int err;
1904 char delim;
1905
1906 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1907 PyErr_Clear();
1908 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1909 return NULL;
1910 }
1911
1912 CHECK_DB_NOT_CLOSED(self);
1913
1914 MYDB_BEGIN_ALLOW_THREADS;
1915 err = self->db->set_re_delim(self->db, delim);
1916 MYDB_END_ALLOW_THREADS;
1917 RETURN_IF_ERR();
1918 RETURN_NONE();
1919}
1920
1921static PyObject*
1922DB_set_re_len(DBObject* self, PyObject* args)
1923{
1924 int err, len;
1925
1926 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1927 return NULL;
1928 CHECK_DB_NOT_CLOSED(self);
1929
1930 MYDB_BEGIN_ALLOW_THREADS;
1931 err = self->db->set_re_len(self->db, len);
1932 MYDB_END_ALLOW_THREADS;
1933 RETURN_IF_ERR();
1934 RETURN_NONE();
1935}
1936
1937
1938static PyObject*
1939DB_set_re_pad(DBObject* self, PyObject* args)
1940{
1941 int err;
1942 char pad;
1943
1944 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1945 PyErr_Clear();
1946 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1947 return NULL;
1948 }
1949 CHECK_DB_NOT_CLOSED(self);
1950
1951 MYDB_BEGIN_ALLOW_THREADS;
1952 err = self->db->set_re_pad(self->db, pad);
1953 MYDB_END_ALLOW_THREADS;
1954 RETURN_IF_ERR();
1955 RETURN_NONE();
1956}
1957
1958
1959static PyObject*
1960DB_set_re_source(DBObject* self, PyObject* args)
1961{
1962 int err;
1963 char *re_source;
1964
1965 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1966 return NULL;
1967 CHECK_DB_NOT_CLOSED(self);
1968
1969 MYDB_BEGIN_ALLOW_THREADS;
1970 err = self->db->set_re_source(self->db, re_source);
1971 MYDB_END_ALLOW_THREADS;
1972 RETURN_IF_ERR();
1973 RETURN_NONE();
1974}
1975
1976
1977#if (DBVER >= 32)
1978static PyObject*
1979DB_set_q_extentsize(DBObject* self, PyObject* args)
1980{
1981 int err;
1982 int extentsize;
1983
1984 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1985 return NULL;
1986 CHECK_DB_NOT_CLOSED(self);
1987
1988 MYDB_BEGIN_ALLOW_THREADS;
1989 err = self->db->set_q_extentsize(self->db, extentsize);
1990 MYDB_END_ALLOW_THREADS;
1991 RETURN_IF_ERR();
1992 RETURN_NONE();
1993}
1994#endif
1995
1996static PyObject*
1997DB_stat(DBObject* self, PyObject* args)
1998{
1999 int err, flags = 0, type;
2000 void* sp;
2001 PyObject* d;
2002
2003
2004 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2005 return NULL;
2006 CHECK_DB_NOT_CLOSED(self);
2007
2008 MYDB_BEGIN_ALLOW_THREADS;
2009#if (DBVER >= 33)
2010 err = self->db->stat(self->db, &sp, flags);
2011#else
2012 err = self->db->stat(self->db, &sp, NULL, flags);
2013#endif
2014 MYDB_END_ALLOW_THREADS;
2015 RETURN_IF_ERR();
2016
2017 self->haveStat = 1;
2018
2019 /* Turn the stat structure into a dictionary */
2020 type = _DB_get_type(self);
2021 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2022 free(sp);
2023 return NULL;
2024 }
2025
2026#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2027#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2028#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2029
2030 switch (type) {
2031 case DB_HASH:
2032 MAKE_HASH_ENTRY(magic);
2033 MAKE_HASH_ENTRY(version);
2034 MAKE_HASH_ENTRY(nkeys);
2035 MAKE_HASH_ENTRY(ndata);
2036 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002038 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002039#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002040 MAKE_HASH_ENTRY(ffactor);
2041 MAKE_HASH_ENTRY(buckets);
2042 MAKE_HASH_ENTRY(free);
2043 MAKE_HASH_ENTRY(bfree);
2044 MAKE_HASH_ENTRY(bigpages);
2045 MAKE_HASH_ENTRY(big_bfree);
2046 MAKE_HASH_ENTRY(overflows);
2047 MAKE_HASH_ENTRY(ovfl_free);
2048 MAKE_HASH_ENTRY(dup);
2049 MAKE_HASH_ENTRY(dup_free);
2050 break;
2051
2052 case DB_BTREE:
2053 case DB_RECNO:
2054 MAKE_BT_ENTRY(magic);
2055 MAKE_BT_ENTRY(version);
2056 MAKE_BT_ENTRY(nkeys);
2057 MAKE_BT_ENTRY(ndata);
2058 MAKE_BT_ENTRY(pagesize);
2059 MAKE_BT_ENTRY(minkey);
2060 MAKE_BT_ENTRY(re_len);
2061 MAKE_BT_ENTRY(re_pad);
2062 MAKE_BT_ENTRY(levels);
2063 MAKE_BT_ENTRY(int_pg);
2064 MAKE_BT_ENTRY(leaf_pg);
2065 MAKE_BT_ENTRY(dup_pg);
2066 MAKE_BT_ENTRY(over_pg);
2067 MAKE_BT_ENTRY(free);
2068 MAKE_BT_ENTRY(int_pgfree);
2069 MAKE_BT_ENTRY(leaf_pgfree);
2070 MAKE_BT_ENTRY(dup_pgfree);
2071 MAKE_BT_ENTRY(over_pgfree);
2072 break;
2073
2074 case DB_QUEUE:
2075 MAKE_QUEUE_ENTRY(magic);
2076 MAKE_QUEUE_ENTRY(version);
2077 MAKE_QUEUE_ENTRY(nkeys);
2078 MAKE_QUEUE_ENTRY(ndata);
2079 MAKE_QUEUE_ENTRY(pagesize);
2080 MAKE_QUEUE_ENTRY(pages);
2081 MAKE_QUEUE_ENTRY(re_len);
2082 MAKE_QUEUE_ENTRY(re_pad);
2083 MAKE_QUEUE_ENTRY(pgfree);
2084#if (DBVER == 31)
2085 MAKE_QUEUE_ENTRY(start);
2086#endif
2087 MAKE_QUEUE_ENTRY(first_recno);
2088 MAKE_QUEUE_ENTRY(cur_recno);
2089 break;
2090
2091 default:
2092 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2093 Py_DECREF(d);
2094 d = NULL;
2095 }
2096
2097#undef MAKE_HASH_ENTRY
2098#undef MAKE_BT_ENTRY
2099#undef MAKE_QUEUE_ENTRY
2100
2101 free(sp);
2102 return d;
2103}
2104
2105static PyObject*
2106DB_sync(DBObject* self, PyObject* args)
2107{
2108 int err;
2109 int flags = 0;
2110
2111 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2112 return NULL;
2113 CHECK_DB_NOT_CLOSED(self);
2114
2115 MYDB_BEGIN_ALLOW_THREADS;
2116 err = self->db->sync(self->db, flags);
2117 MYDB_END_ALLOW_THREADS;
2118 RETURN_IF_ERR();
2119 RETURN_NONE();
2120}
2121
2122
2123#if (DBVER >= 33)
2124static PyObject*
2125DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2126{
2127 int err, flags=0;
2128 u_int32_t count=0;
2129 PyObject* txnobj = NULL;
2130 DB_TXN *txn = NULL;
2131 char* kwnames[] = { "txn", "flags", NULL };
2132
2133 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2134 &txnobj, &flags))
2135 return NULL;
2136 CHECK_DB_NOT_CLOSED(self);
2137 if (!checkTxnObj(txnobj, &txn))
2138 return NULL;
2139
2140 MYDB_BEGIN_ALLOW_THREADS;
2141 err = self->db->truncate(self->db, txn, &count, flags);
2142 MYDB_END_ALLOW_THREADS;
2143 RETURN_IF_ERR();
2144 return PyInt_FromLong(count);
2145}
2146#endif
2147
2148
2149static PyObject*
2150DB_upgrade(DBObject* self, PyObject* args)
2151{
2152 int err, flags=0;
2153 char *filename;
2154
2155 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2156 return NULL;
2157 CHECK_DB_NOT_CLOSED(self);
2158
2159 MYDB_BEGIN_ALLOW_THREADS;
2160 err = self->db->upgrade(self->db, filename, flags);
2161 MYDB_END_ALLOW_THREADS;
2162 RETURN_IF_ERR();
2163 RETURN_NONE();
2164}
2165
2166
2167static PyObject*
2168DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2169{
2170 int err, flags=0;
2171 char* fileName;
2172 char* dbName=NULL;
2173 char* outFileName=NULL;
2174 FILE* outFile=NULL;
2175 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2176
2177 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2178 &fileName, &dbName, &outFileName, &flags))
2179 return NULL;
2180
2181 CHECK_DB_NOT_CLOSED(self);
2182 if (outFileName)
2183 outFile = fopen(outFileName, "w");
2184
2185 MYDB_BEGIN_ALLOW_THREADS;
2186 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2187 MYDB_END_ALLOW_THREADS;
2188 if (outFileName)
2189 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002190
2191 /* DB.verify acts as a DB handle destructor (like close); this was
2192 * documented in BerkeleyDB 4.2 but had the undocumented effect
2193 * of not being safe in prior versions while still requiring an explicit
2194 * DB.close call afterwards. Lets call close for the user to emulate
2195 * the safe 4.2 behaviour. */
2196#if (DBVER <= 41)
2197 self->db->close(self->db, 0);
2198#endif
2199 self->db = NULL;
2200
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002201 RETURN_IF_ERR();
2202 RETURN_NONE();
2203}
2204
2205
2206static PyObject*
2207DB_set_get_returns_none(DBObject* self, PyObject* args)
2208{
2209 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002210 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002211
2212 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2213 return NULL;
2214 CHECK_DB_NOT_CLOSED(self);
2215
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002216 if (self->moduleFlags.getReturnsNone)
2217 ++oldValue;
2218 if (self->moduleFlags.cursorSetReturnsNone)
2219 ++oldValue;
2220 self->moduleFlags.getReturnsNone = (flags >= 1);
2221 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002222 return PyInt_FromLong(oldValue);
2223}
2224
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002225#if (DBVER >= 41)
2226static PyObject*
2227DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2228{
2229 int err;
2230 u_int32_t flags=0;
2231 char *passwd = NULL;
2232 char* kwnames[] = { "passwd", "flags", NULL };
2233
2234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2235 &passwd, &flags)) {
2236 return NULL;
2237 }
2238
2239 MYDB_BEGIN_ALLOW_THREADS;
2240 err = self->db->set_encrypt(self->db, passwd, flags);
2241 MYDB_END_ALLOW_THREADS;
2242
2243 RETURN_IF_ERR();
2244 RETURN_NONE();
2245}
2246#endif /* DBVER >= 41 */
2247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002248
2249/*-------------------------------------------------------------- */
2250/* Mapping and Dictionary-like access routines */
2251
2252int DB_length(DBObject* self)
2253{
2254 int err;
2255 long size = 0;
2256 int flags = 0;
2257 void* sp;
2258
2259 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002260 PyErr_SetObject(DBError,
2261 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002262 return -1;
2263 }
2264
2265 if (self->haveStat) { /* Has the stat function been called recently? If
2266 so, we can use the cached value. */
2267 flags = DB_CACHED_COUNTS;
2268 }
2269
2270 MYDB_BEGIN_ALLOW_THREADS;
2271#if (DBVER >= 33)
2272 err = self->db->stat(self->db, &sp, flags);
2273#else
2274 err = self->db->stat(self->db, &sp, NULL, flags);
2275#endif
2276 MYDB_END_ALLOW_THREADS;
2277
2278 if (err)
2279 return -1;
2280
2281 self->haveStat = 1;
2282
2283 /* All the stat structures have matching fields upto the ndata field,
2284 so we can use any of them for the type cast */
2285 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2286 free(sp);
2287 return size;
2288}
2289
2290
2291PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2292{
2293 int err;
2294 PyObject* retval;
2295 DBT key;
2296 DBT data;
2297
2298 CHECK_DB_NOT_CLOSED(self);
2299 if (!make_key_dbt(self, keyobj, &key, NULL))
2300 return NULL;
2301
2302 CLEAR_DBT(data);
2303 if (CHECK_DBFLAG(self, DB_THREAD)) {
2304 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2305 data.flags = DB_DBT_MALLOC;
2306 }
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->get(self->db, NULL, &key, &data, 0);
2309 MYDB_END_ALLOW_THREADS;
2310 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2311 PyErr_SetObject(PyExc_KeyError, keyobj);
2312 retval = NULL;
2313 }
2314 else if (makeDBError(err)) {
2315 retval = NULL;
2316 }
2317 else {
2318 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2319 FREE_DBT(data);
2320 }
2321
2322 FREE_DBT(key);
2323 return retval;
2324}
2325
2326
2327static int
2328DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2329{
2330 DBT key, data;
2331 int retval;
2332 int flags = 0;
2333
2334 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002335 PyErr_SetObject(DBError,
2336 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002337 return -1;
2338 }
2339
2340 if (!make_key_dbt(self, keyobj, &key, NULL))
2341 return -1;
2342
2343 if (dataobj != NULL) {
2344 if (!make_dbt(dataobj, &data))
2345 retval = -1;
2346 else {
2347 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002348 /* dictionaries shouldn't have duplicate keys */
2349 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002350 retval = _DB_put(self, NULL, &key, &data, flags);
2351
2352 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002353 /* try deleting any old record that matches and then PUT it
2354 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002355 _DB_delete(self, NULL, &key, 0);
2356 PyErr_Clear();
2357 retval = _DB_put(self, NULL, &key, &data, flags);
2358 }
2359 }
2360 }
2361 else {
2362 /* dataobj == NULL, so delete the key */
2363 retval = _DB_delete(self, NULL, &key, 0);
2364 }
2365 FREE_DBT(key);
2366 return retval;
2367}
2368
2369
2370static PyObject*
2371DB_has_key(DBObject* self, PyObject* args)
2372{
2373 int err;
2374 PyObject* keyobj;
2375 DBT key, data;
2376 PyObject* txnobj = NULL;
2377 DB_TXN *txn = NULL;
2378
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002379 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002380 return NULL;
2381 CHECK_DB_NOT_CLOSED(self);
2382 if (!make_key_dbt(self, keyobj, &key, NULL))
2383 return NULL;
2384 if (!checkTxnObj(txnobj, &txn))
2385 return NULL;
2386
2387 /* This causes ENOMEM to be returned when the db has the key because
2388 it has a record but can't allocate a buffer for the data. This saves
2389 having to deal with data we won't be using.
2390 */
2391 CLEAR_DBT(data);
2392 data.flags = DB_DBT_USERMEM;
2393
2394 MYDB_BEGIN_ALLOW_THREADS;
2395 err = self->db->get(self->db, NULL, &key, &data, 0);
2396 MYDB_END_ALLOW_THREADS;
2397 FREE_DBT(key);
2398 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2399}
2400
2401
2402#define _KEYS_LIST 1
2403#define _VALUES_LIST 2
2404#define _ITEMS_LIST 3
2405
2406static PyObject*
2407_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2408{
2409 int err, dbtype;
2410 DBT key;
2411 DBT data;
2412 DBC *cursor;
2413 PyObject* list;
2414 PyObject* item = NULL;
2415
2416 CHECK_DB_NOT_CLOSED(self);
2417 CLEAR_DBT(key);
2418 CLEAR_DBT(data);
2419
2420 dbtype = _DB_get_type(self);
2421 if (dbtype == -1)
2422 return NULL;
2423
2424 list = PyList_New(0);
2425 if (list == NULL) {
2426 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2427 return NULL;
2428 }
2429
2430 /* get a cursor */
2431 MYDB_BEGIN_ALLOW_THREADS;
2432 err = self->db->cursor(self->db, NULL, &cursor, 0);
2433 MYDB_END_ALLOW_THREADS;
2434 RETURN_IF_ERR();
2435
2436 if (CHECK_DBFLAG(self, DB_THREAD)) {
2437 key.flags = DB_DBT_REALLOC;
2438 data.flags = DB_DBT_REALLOC;
2439 }
2440
2441 while (1) { /* use the cursor to traverse the DB, collecting items */
2442 MYDB_BEGIN_ALLOW_THREADS;
2443 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2444 MYDB_END_ALLOW_THREADS;
2445
2446 if (err) {
2447 /* for any error, break out of the loop */
2448 break;
2449 }
2450
2451 switch (type) {
2452 case _KEYS_LIST:
2453 switch(dbtype) {
2454 case DB_BTREE:
2455 case DB_HASH:
2456 default:
2457 item = PyString_FromStringAndSize((char*)key.data, key.size);
2458 break;
2459 case DB_RECNO:
2460 case DB_QUEUE:
2461 item = PyInt_FromLong(*((db_recno_t*)key.data));
2462 break;
2463 }
2464 break;
2465
2466 case _VALUES_LIST:
2467 item = PyString_FromStringAndSize((char*)data.data, data.size);
2468 break;
2469
2470 case _ITEMS_LIST:
2471 switch(dbtype) {
2472 case DB_BTREE:
2473 case DB_HASH:
2474 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002475 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2476 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002477 break;
2478 case DB_RECNO:
2479 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002480 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2481 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002482 break;
2483 }
2484 break;
2485 }
2486 if (item == NULL) {
2487 Py_DECREF(list);
2488 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2489 list = NULL;
2490 goto done;
2491 }
2492 PyList_Append(list, item);
2493 Py_DECREF(item);
2494 }
2495
2496 /* DB_NOTFOUND is okay, it just means we got to the end */
2497 if (err != DB_NOTFOUND && makeDBError(err)) {
2498 Py_DECREF(list);
2499 list = NULL;
2500 }
2501
2502 done:
2503 FREE_DBT(key);
2504 FREE_DBT(data);
2505 MYDB_BEGIN_ALLOW_THREADS;
2506 cursor->c_close(cursor);
2507 MYDB_END_ALLOW_THREADS;
2508 return list;
2509}
2510
2511
2512static PyObject*
2513DB_keys(DBObject* self, PyObject* args)
2514{
2515 PyObject* txnobj = NULL;
2516 DB_TXN *txn = NULL;
2517
2518 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2519 return NULL;
2520 if (!checkTxnObj(txnobj, &txn))
2521 return NULL;
2522 return _DB_make_list(self, txn, _KEYS_LIST);
2523}
2524
2525
2526static PyObject*
2527DB_items(DBObject* self, PyObject* args)
2528{
2529 PyObject* txnobj = NULL;
2530 DB_TXN *txn = NULL;
2531
2532 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2533 return NULL;
2534 if (!checkTxnObj(txnobj, &txn))
2535 return NULL;
2536 return _DB_make_list(self, txn, _ITEMS_LIST);
2537}
2538
2539
2540static PyObject*
2541DB_values(DBObject* self, PyObject* args)
2542{
2543 PyObject* txnobj = NULL;
2544 DB_TXN *txn = NULL;
2545
2546 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2547 return NULL;
2548 if (!checkTxnObj(txnobj, &txn))
2549 return NULL;
2550 return _DB_make_list(self, txn, _VALUES_LIST);
2551}
2552
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002553/* --------------------------------------------------------------------- */
2554/* DBCursor methods */
2555
2556
2557static PyObject*
2558DBC_close(DBCursorObject* self, PyObject* args)
2559{
2560 int err = 0;
2561
2562 if (!PyArg_ParseTuple(args, ":close"))
2563 return NULL;
2564
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002565 if (self->dbc != NULL) {
2566 MYDB_BEGIN_ALLOW_THREADS;
2567 err = self->dbc->c_close(self->dbc);
2568 self->dbc = NULL;
2569 MYDB_END_ALLOW_THREADS;
2570 }
2571 RETURN_IF_ERR();
2572 RETURN_NONE();
2573}
2574
2575
2576static PyObject*
2577DBC_count(DBCursorObject* self, PyObject* args)
2578{
2579 int err = 0;
2580 db_recno_t count;
2581 int flags = 0;
2582
2583 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2584 return NULL;
2585
2586 CHECK_CURSOR_NOT_CLOSED(self);
2587
2588 MYDB_BEGIN_ALLOW_THREADS;
2589 err = self->dbc->c_count(self->dbc, &count, flags);
2590 MYDB_END_ALLOW_THREADS;
2591 RETURN_IF_ERR();
2592
2593 return PyInt_FromLong(count);
2594}
2595
2596
2597static PyObject*
2598DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2599{
2600 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2601}
2602
2603
2604static PyObject*
2605DBC_delete(DBCursorObject* self, PyObject* args)
2606{
2607 int err, flags=0;
2608
2609 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2610 return NULL;
2611
2612 CHECK_CURSOR_NOT_CLOSED(self);
2613
2614 MYDB_BEGIN_ALLOW_THREADS;
2615 err = self->dbc->c_del(self->dbc, flags);
2616 MYDB_END_ALLOW_THREADS;
2617 RETURN_IF_ERR();
2618
2619 self->mydb->haveStat = 0;
2620 RETURN_NONE();
2621}
2622
2623
2624static PyObject*
2625DBC_dup(DBCursorObject* self, PyObject* args)
2626{
2627 int err, flags =0;
2628 DBC* dbc = NULL;
2629
2630 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2631 return NULL;
2632
2633 CHECK_CURSOR_NOT_CLOSED(self);
2634
2635 MYDB_BEGIN_ALLOW_THREADS;
2636 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2637 MYDB_END_ALLOW_THREADS;
2638 RETURN_IF_ERR();
2639
2640 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2641}
2642
2643static PyObject*
2644DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2645{
2646 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2647}
2648
2649
2650static PyObject*
2651DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2652{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002653 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654 PyObject* keyobj = NULL;
2655 PyObject* dataobj = NULL;
2656 PyObject* retval = NULL;
2657 int dlen = -1;
2658 int doff = -1;
2659 DBT key, data;
2660 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2661
2662 CLEAR_DBT(key);
2663 CLEAR_DBT(data);
2664 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002665 &flags, &dlen, &doff))
2666 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002667 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002668 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2669 &kwnames[1],
2670 &keyobj, &flags, &dlen, &doff))
2671 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002672 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2674 kwnames, &keyobj, &dataobj,
2675 &flags, &dlen, &doff))
2676 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002677 return NULL;
2678 }
2679 }
2680 }
2681
2682 CHECK_CURSOR_NOT_CLOSED(self);
2683
2684 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2685 return NULL;
2686 if (dataobj && !make_dbt(dataobj, &data))
2687 return NULL;
2688 if (!add_partial_dbt(&data, dlen, doff))
2689 return NULL;
2690
2691 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2692 data.flags = DB_DBT_MALLOC;
2693 key.flags = DB_DBT_MALLOC;
2694 }
2695
2696 MYDB_BEGIN_ALLOW_THREADS;
2697 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2698 MYDB_END_ALLOW_THREADS;
2699
2700
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002701 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 Py_INCREF(Py_None);
2703 retval = Py_None;
2704 }
2705 else if (makeDBError(err)) {
2706 retval = NULL;
2707 }
2708 else {
2709 switch (_DB_get_type(self->mydb)) {
2710 case -1:
2711 retval = NULL;
2712 break;
2713 case DB_BTREE:
2714 case DB_HASH:
2715 default:
2716 retval = Py_BuildValue("s#s#", key.data, key.size,
2717 data.data, data.size);
2718 break;
2719 case DB_RECNO:
2720 case DB_QUEUE:
2721 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2722 data.data, data.size);
2723 break;
2724 }
2725 FREE_DBT(key);
2726 FREE_DBT(data);
2727 }
2728 return retval;
2729}
2730
2731
2732static PyObject*
2733DBC_get_recno(DBCursorObject* self, PyObject* args)
2734{
2735 int err;
2736 db_recno_t recno;
2737 DBT key;
2738 DBT data;
2739
2740 if (!PyArg_ParseTuple(args, ":get_recno"))
2741 return NULL;
2742
2743 CHECK_CURSOR_NOT_CLOSED(self);
2744
2745 CLEAR_DBT(key);
2746 CLEAR_DBT(data);
2747 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2748 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2749 data.flags = DB_DBT_MALLOC;
2750 key.flags = DB_DBT_MALLOC;
2751 }
2752
2753 MYDB_BEGIN_ALLOW_THREADS;
2754 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2755 MYDB_END_ALLOW_THREADS;
2756 RETURN_IF_ERR();
2757
2758 recno = *((db_recno_t*)data.data);
2759 FREE_DBT(key);
2760 FREE_DBT(data);
2761 return PyInt_FromLong(recno);
2762}
2763
2764
2765static PyObject*
2766DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2767{
2768 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2769}
2770
2771
2772static PyObject*
2773DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2774{
2775 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2776}
2777
2778
2779static PyObject*
2780DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2781{
2782 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2783}
2784
2785
2786static PyObject*
2787DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2788{
2789 int err, flags = 0;
2790 PyObject* keyobj, *dataobj;
2791 DBT key, data;
2792 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2793 int dlen = -1;
2794 int doff = -1;
2795
2796 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2797 &keyobj, &dataobj, &flags, &dlen, &doff))
2798 return NULL;
2799
2800 CHECK_CURSOR_NOT_CLOSED(self);
2801
2802 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2803 return NULL;
2804 if (!make_dbt(dataobj, &data))
2805 return NULL;
2806 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2807
2808 MYDB_BEGIN_ALLOW_THREADS;
2809 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2810 MYDB_END_ALLOW_THREADS;
2811 FREE_DBT(key);
2812 RETURN_IF_ERR();
2813 self->mydb->haveStat = 0;
2814 RETURN_NONE();
2815}
2816
2817
2818static PyObject*
2819DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2820{
2821 int err, flags = 0;
2822 DBT key, data;
2823 PyObject* retval, *keyobj;
2824 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2825 int dlen = -1;
2826 int doff = -1;
2827
2828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2829 &keyobj, &flags, &dlen, &doff))
2830 return NULL;
2831
2832 CHECK_CURSOR_NOT_CLOSED(self);
2833
2834 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2835 return NULL;
2836
2837 CLEAR_DBT(data);
2838 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2839 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2840 data.flags = DB_DBT_MALLOC;
2841 }
2842 if (!add_partial_dbt(&data, dlen, doff))
2843 return NULL;
2844
2845 MYDB_BEGIN_ALLOW_THREADS;
2846 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2847 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002848 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2849 Py_INCREF(Py_None);
2850 retval = Py_None;
2851 }
2852 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853 retval = NULL;
2854 }
2855 else {
2856 switch (_DB_get_type(self->mydb)) {
2857 case -1:
2858 retval = NULL;
2859 break;
2860 case DB_BTREE:
2861 case DB_HASH:
2862 default:
2863 retval = Py_BuildValue("s#s#", key.data, key.size,
2864 data.data, data.size);
2865 break;
2866 case DB_RECNO:
2867 case DB_QUEUE:
2868 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2869 data.data, data.size);
2870 break;
2871 }
2872 FREE_DBT(key);
2873 FREE_DBT(data);
2874 }
2875
2876 return retval;
2877}
2878
2879
2880static PyObject*
2881DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2882{
2883 int err, flags = 0;
2884 DBT key, data;
2885 PyObject* retval, *keyobj;
2886 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2887 int dlen = -1;
2888 int doff = -1;
2889
2890 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2891 &keyobj, &flags, &dlen, &doff))
2892 return NULL;
2893
2894 CHECK_CURSOR_NOT_CLOSED(self);
2895
2896 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2897 return NULL;
2898
2899 CLEAR_DBT(data);
2900 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2901 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2902 data.flags = DB_DBT_MALLOC;
2903 key.flags = DB_DBT_MALLOC;
2904 }
2905 if (!add_partial_dbt(&data, dlen, doff))
2906 return NULL;
2907 MYDB_BEGIN_ALLOW_THREADS;
2908 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2909 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002910 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2911 Py_INCREF(Py_None);
2912 retval = Py_None;
2913 }
2914 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915 retval = NULL;
2916 }
2917 else {
2918 switch (_DB_get_type(self->mydb)) {
2919 case -1:
2920 retval = NULL;
2921 break;
2922 case DB_BTREE:
2923 case DB_HASH:
2924 default:
2925 retval = Py_BuildValue("s#s#", key.data, key.size,
2926 data.data, data.size);
2927 break;
2928 case DB_RECNO:
2929 case DB_QUEUE:
2930 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2931 data.data, data.size);
2932 break;
2933 }
2934 FREE_DBT(key);
2935 FREE_DBT(data);
2936 }
2937
2938 return retval;
2939}
2940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002941static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002942_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2943 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002944{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002945 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002946 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002947 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948
Gregory P. Smith7441e652003-11-03 21:35:31 +00002949 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002950 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2951 return NULL;
2952 if (!make_dbt(dataobj, &data))
2953 return NULL;
2954
2955 MYDB_BEGIN_ALLOW_THREADS;
2956 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2957 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002958 if ((err == DB_NOTFOUND) && returnsNone) {
2959 Py_INCREF(Py_None);
2960 retval = Py_None;
2961 }
2962 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 retval = NULL;
2964 }
2965 else {
2966 switch (_DB_get_type(self->mydb)) {
2967 case -1:
2968 retval = NULL;
2969 break;
2970 case DB_BTREE:
2971 case DB_HASH:
2972 default:
2973 retval = Py_BuildValue("s#s#", key.data, key.size,
2974 data.data, data.size);
2975 break;
2976 case DB_RECNO:
2977 case DB_QUEUE:
2978 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2979 data.data, data.size);
2980 break;
2981 }
2982 }
2983
2984 FREE_DBT(key);
2985 return retval;
2986}
2987
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002988static PyObject*
2989DBC_get_both(DBCursorObject* self, PyObject* args)
2990{
2991 int flags=0;
2992 PyObject *keyobj, *dataobj;
2993
2994 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2995 return NULL;
2996
Gregory P. Smith7441e652003-11-03 21:35:31 +00002997 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002998 CHECK_CURSOR_NOT_CLOSED(self);
2999
3000 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3001 self->mydb->moduleFlags.getReturnsNone);
3002}
3003
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003004/* Return size of entry */
3005static PyObject*
3006DBC_get_current_size(DBCursorObject* self, PyObject* args)
3007{
3008 int err, flags=DB_CURRENT;
3009 PyObject* retval = NULL;
3010 DBT key, data;
3011
3012 if (!PyArg_ParseTuple(args, ":get_current_size"))
3013 return NULL;
3014 CHECK_CURSOR_NOT_CLOSED(self);
3015 CLEAR_DBT(key);
3016 CLEAR_DBT(data);
3017
3018 /* We don't allocate any memory, forcing a ENOMEM error and thus
3019 getting the record size. */
3020 data.flags = DB_DBT_USERMEM;
3021 data.ulen = 0;
3022 MYDB_BEGIN_ALLOW_THREADS;
3023 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3024 MYDB_END_ALLOW_THREADS;
3025 if (err == ENOMEM || !err) {
3026 /* ENOMEM means positive size, !err means zero length value */
3027 retval = PyInt_FromLong((long)data.size);
3028 err = 0;
3029 }
3030
3031 FREE_DBT(key);
3032 FREE_DBT(data);
3033 RETURN_IF_ERR();
3034 return retval;
3035}
3036
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003037static PyObject*
3038DBC_set_both(DBCursorObject* self, PyObject* args)
3039{
3040 int flags=0;
3041 PyObject *keyobj, *dataobj;
3042
3043 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3044 return NULL;
3045
Gregory P. Smith7441e652003-11-03 21:35:31 +00003046 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003047 CHECK_CURSOR_NOT_CLOSED(self);
3048
3049 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3050 self->mydb->moduleFlags.cursorSetReturnsNone);
3051}
3052
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003053
3054static PyObject*
3055DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3056{
3057 int err, irecno, flags=0;
3058 db_recno_t recno;
3059 DBT key, data;
3060 PyObject* retval;
3061 int dlen = -1;
3062 int doff = -1;
3063 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3064
3065 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3066 &irecno, &flags, &dlen, &doff))
3067 return NULL;
3068
3069 CHECK_CURSOR_NOT_CLOSED(self);
3070
3071 CLEAR_DBT(key);
3072 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003073 /* use allocated space so DB will be able to realloc room for the real
3074 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003075 key.data = malloc(sizeof(db_recno_t));
3076 if (key.data == NULL) {
3077 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3078 return NULL;
3079 }
3080 key.size = sizeof(db_recno_t);
3081 key.ulen = key.size;
3082 memcpy(key.data, &recno, sizeof(db_recno_t));
3083 key.flags = DB_DBT_REALLOC;
3084
3085 CLEAR_DBT(data);
3086 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3087 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3088 data.flags = DB_DBT_MALLOC;
3089 }
3090 if (!add_partial_dbt(&data, dlen, doff))
3091 return NULL;
3092
3093 MYDB_BEGIN_ALLOW_THREADS;
3094 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3095 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003096 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3097 Py_INCREF(Py_None);
3098 retval = Py_None;
3099 }
3100 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003101 retval = NULL;
3102 }
3103 else { /* Can only be used for BTrees, so no need to return int key */
3104 retval = Py_BuildValue("s#s#", key.data, key.size,
3105 data.data, data.size);
3106 FREE_DBT(key);
3107 FREE_DBT(data);
3108 }
3109
3110 return retval;
3111}
3112
3113
3114static PyObject*
3115DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3116{
3117 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3118}
3119
3120
3121static PyObject*
3122DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3123{
3124 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3125}
3126
3127
3128static PyObject*
3129DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3130{
3131 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3132}
3133
3134
3135static PyObject*
3136DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3137{
3138 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3139}
3140
3141
3142static PyObject*
3143DBC_join_item(DBCursorObject* self, PyObject* args)
3144{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003145 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003146 DBT key, data;
3147 PyObject* retval;
3148
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003149 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003150 return NULL;
3151
3152 CHECK_CURSOR_NOT_CLOSED(self);
3153
3154 CLEAR_DBT(key);
3155 CLEAR_DBT(data);
3156 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3157 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3158 key.flags = DB_DBT_MALLOC;
3159 }
3160
3161 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003162 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003164 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3165 Py_INCREF(Py_None);
3166 retval = Py_None;
3167 }
3168 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169 retval = NULL;
3170 }
3171 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003172 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 FREE_DBT(key);
3174 }
3175
3176 return retval;
3177}
3178
3179
3180
3181/* --------------------------------------------------------------------- */
3182/* DBEnv methods */
3183
3184
3185static PyObject*
3186DBEnv_close(DBEnvObject* self, PyObject* args)
3187{
3188 int err, flags = 0;
3189
3190 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3191 return NULL;
3192 if (!self->closed) { /* Don't close more than once */
3193 MYDB_BEGIN_ALLOW_THREADS;
3194 err = self->db_env->close(self->db_env, flags);
3195 MYDB_END_ALLOW_THREADS;
3196 /* after calling DBEnv->close, regardless of error, this DBEnv
3197 * may not be accessed again (BerkeleyDB docs). */
3198 self->closed = 1;
3199 self->db_env = NULL;
3200 RETURN_IF_ERR();
3201 }
3202 RETURN_NONE();
3203}
3204
3205
3206static PyObject*
3207DBEnv_open(DBEnvObject* self, PyObject* args)
3208{
3209 int err, flags=0, mode=0660;
3210 char *db_home;
3211
3212 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3213 return NULL;
3214
3215 CHECK_ENV_NOT_CLOSED(self);
3216
3217 MYDB_BEGIN_ALLOW_THREADS;
3218 err = self->db_env->open(self->db_env, db_home, flags, mode);
3219 MYDB_END_ALLOW_THREADS;
3220 RETURN_IF_ERR();
3221 self->closed = 0;
3222 self->flags = flags;
3223 RETURN_NONE();
3224}
3225
3226
3227static PyObject*
3228DBEnv_remove(DBEnvObject* self, PyObject* args)
3229{
3230 int err, flags=0;
3231 char *db_home;
3232
3233 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3234 return NULL;
3235 CHECK_ENV_NOT_CLOSED(self);
3236 MYDB_BEGIN_ALLOW_THREADS;
3237 err = self->db_env->remove(self->db_env, db_home, flags);
3238 MYDB_END_ALLOW_THREADS;
3239 RETURN_IF_ERR();
3240 RETURN_NONE();
3241}
3242
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003243#if (DBVER >= 41)
3244static PyObject*
3245DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3246{
3247 int err;
3248 u_int32_t flags=0;
3249 char *file = NULL;
3250 char *database = NULL;
3251 PyObject *txnobj = NULL;
3252 DB_TXN *txn = NULL;
3253 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3254
3255 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3256 &file, &database, &txnobj, &flags)) {
3257 return NULL;
3258 }
3259 if (!checkTxnObj(txnobj, &txn)) {
3260 return NULL;
3261 }
3262 CHECK_ENV_NOT_CLOSED(self);
3263 MYDB_BEGIN_ALLOW_THREADS;
3264 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3265 MYDB_END_ALLOW_THREADS;
3266 RETURN_IF_ERR();
3267 RETURN_NONE();
3268}
3269
3270static PyObject*
3271DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3272{
3273 int err;
3274 u_int32_t flags=0;
3275 char *file = NULL;
3276 char *database = NULL;
3277 char *newname = NULL;
3278 PyObject *txnobj = NULL;
3279 DB_TXN *txn = NULL;
3280 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3281
3282 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3283 &file, &database, &newname, &txnobj, &flags)) {
3284 return NULL;
3285 }
3286 if (!checkTxnObj(txnobj, &txn)) {
3287 return NULL;
3288 }
3289 CHECK_ENV_NOT_CLOSED(self);
3290 MYDB_BEGIN_ALLOW_THREADS;
3291 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3292 flags);
3293 MYDB_END_ALLOW_THREADS;
3294 RETURN_IF_ERR();
3295 RETURN_NONE();
3296}
3297
3298static PyObject*
3299DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3300{
3301 int err;
3302 u_int32_t flags=0;
3303 char *passwd = NULL;
3304 char* kwnames[] = { "passwd", "flags", NULL };
3305
3306 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3307 &passwd, &flags)) {
3308 return NULL;
3309 }
3310
3311 MYDB_BEGIN_ALLOW_THREADS;
3312 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3313 MYDB_END_ALLOW_THREADS;
3314
3315 RETURN_IF_ERR();
3316 RETURN_NONE();
3317}
3318#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003320#if (DBVER >= 40)
3321static PyObject*
3322DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3323{
3324 int err;
3325 u_int32_t flags=0;
3326 u_int32_t timeout = 0;
3327 char* kwnames[] = { "timeout", "flags", NULL };
3328
3329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3330 &timeout, &flags)) {
3331 return NULL;
3332 }
3333
3334 MYDB_BEGIN_ALLOW_THREADS;
3335 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3336 MYDB_END_ALLOW_THREADS;
3337
3338 RETURN_IF_ERR();
3339 RETURN_NONE();
3340}
3341#endif /* DBVER >= 40 */
3342
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003343static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003344DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3345{
3346 int err;
3347 long shm_key = 0;
3348
3349 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3350 return NULL;
3351 CHECK_ENV_NOT_CLOSED(self);
3352
3353 err = self->db_env->set_shm_key(self->db_env, shm_key);
3354 RETURN_IF_ERR();
3355 RETURN_NONE();
3356}
3357
3358static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003359DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3360{
3361 int err, gbytes=0, bytes=0, ncache=0;
3362
3363 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3364 &gbytes, &bytes, &ncache))
3365 return NULL;
3366 CHECK_ENV_NOT_CLOSED(self);
3367
3368 MYDB_BEGIN_ALLOW_THREADS;
3369 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3370 MYDB_END_ALLOW_THREADS;
3371 RETURN_IF_ERR();
3372 RETURN_NONE();
3373}
3374
3375
3376#if (DBVER >= 32)
3377static PyObject*
3378DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3379{
3380 int err, flags=0, onoff=0;
3381
3382 if (!PyArg_ParseTuple(args, "ii:set_flags",
3383 &flags, &onoff))
3384 return NULL;
3385 CHECK_ENV_NOT_CLOSED(self);
3386
3387 MYDB_BEGIN_ALLOW_THREADS;
3388 err = self->db_env->set_flags(self->db_env, flags, onoff);
3389 MYDB_END_ALLOW_THREADS;
3390 RETURN_IF_ERR();
3391 RETURN_NONE();
3392}
3393#endif
3394
3395
3396static PyObject*
3397DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3398{
3399 int err;
3400 char *dir;
3401
3402 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3403 return NULL;
3404 CHECK_ENV_NOT_CLOSED(self);
3405
3406 MYDB_BEGIN_ALLOW_THREADS;
3407 err = self->db_env->set_data_dir(self->db_env, dir);
3408 MYDB_END_ALLOW_THREADS;
3409 RETURN_IF_ERR();
3410 RETURN_NONE();
3411}
3412
3413
3414static PyObject*
3415DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3416{
3417 int err, lg_bsize;
3418
3419 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3420 return NULL;
3421 CHECK_ENV_NOT_CLOSED(self);
3422
3423 MYDB_BEGIN_ALLOW_THREADS;
3424 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3425 MYDB_END_ALLOW_THREADS;
3426 RETURN_IF_ERR();
3427 RETURN_NONE();
3428}
3429
3430
3431static PyObject*
3432DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3433{
3434 int err;
3435 char *dir;
3436
3437 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3438 return NULL;
3439 CHECK_ENV_NOT_CLOSED(self);
3440
3441 MYDB_BEGIN_ALLOW_THREADS;
3442 err = self->db_env->set_lg_dir(self->db_env, dir);
3443 MYDB_END_ALLOW_THREADS;
3444 RETURN_IF_ERR();
3445 RETURN_NONE();
3446}
3447
3448static PyObject*
3449DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3450{
3451 int err, lg_max;
3452
3453 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3454 return NULL;
3455 CHECK_ENV_NOT_CLOSED(self);
3456
3457 MYDB_BEGIN_ALLOW_THREADS;
3458 err = self->db_env->set_lg_max(self->db_env, lg_max);
3459 MYDB_END_ALLOW_THREADS;
3460 RETURN_IF_ERR();
3461 RETURN_NONE();
3462}
3463
3464
3465static PyObject*
3466DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3467{
3468 int err, lk_detect;
3469
3470 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3471 return NULL;
3472 CHECK_ENV_NOT_CLOSED(self);
3473
3474 MYDB_BEGIN_ALLOW_THREADS;
3475 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3476 MYDB_END_ALLOW_THREADS;
3477 RETURN_IF_ERR();
3478 RETURN_NONE();
3479}
3480
3481
3482static PyObject*
3483DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3484{
3485 int err, max;
3486
3487 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3488 return NULL;
3489 CHECK_ENV_NOT_CLOSED(self);
3490
3491 MYDB_BEGIN_ALLOW_THREADS;
3492 err = self->db_env->set_lk_max(self->db_env, max);
3493 MYDB_END_ALLOW_THREADS;
3494 RETURN_IF_ERR();
3495 RETURN_NONE();
3496}
3497
3498
3499#if (DBVER >= 32)
3500
3501static PyObject*
3502DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3503{
3504 int err, max;
3505
3506 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3507 return NULL;
3508 CHECK_ENV_NOT_CLOSED(self);
3509
3510 MYDB_BEGIN_ALLOW_THREADS;
3511 err = self->db_env->set_lk_max_locks(self->db_env, max);
3512 MYDB_END_ALLOW_THREADS;
3513 RETURN_IF_ERR();
3514 RETURN_NONE();
3515}
3516
3517
3518static PyObject*
3519DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3520{
3521 int err, max;
3522
3523 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3524 return NULL;
3525 CHECK_ENV_NOT_CLOSED(self);
3526
3527 MYDB_BEGIN_ALLOW_THREADS;
3528 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3529 MYDB_END_ALLOW_THREADS;
3530 RETURN_IF_ERR();
3531 RETURN_NONE();
3532}
3533
3534
3535static PyObject*
3536DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3537{
3538 int err, max;
3539
3540 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3541 return NULL;
3542 CHECK_ENV_NOT_CLOSED(self);
3543
3544 MYDB_BEGIN_ALLOW_THREADS;
3545 err = self->db_env->set_lk_max_objects(self->db_env, max);
3546 MYDB_END_ALLOW_THREADS;
3547 RETURN_IF_ERR();
3548 RETURN_NONE();
3549}
3550
3551#endif
3552
3553
3554static PyObject*
3555DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3556{
3557 int err, mp_mmapsize;
3558
3559 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3560 return NULL;
3561 CHECK_ENV_NOT_CLOSED(self);
3562
3563 MYDB_BEGIN_ALLOW_THREADS;
3564 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3565 MYDB_END_ALLOW_THREADS;
3566 RETURN_IF_ERR();
3567 RETURN_NONE();
3568}
3569
3570
3571static PyObject*
3572DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3573{
3574 int err;
3575 char *dir;
3576
3577 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3578 return NULL;
3579 CHECK_ENV_NOT_CLOSED(self);
3580
3581 MYDB_BEGIN_ALLOW_THREADS;
3582 err = self->db_env->set_tmp_dir(self->db_env, dir);
3583 MYDB_END_ALLOW_THREADS;
3584 RETURN_IF_ERR();
3585 RETURN_NONE();
3586}
3587
3588
3589static PyObject*
3590DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3591{
3592 int flags = 0;
3593 PyObject* txnobj = NULL;
3594 DB_TXN *txn = NULL;
3595 char* kwnames[] = { "parent", "flags", NULL };
3596
3597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3598 &txnobj, &flags))
3599 return NULL;
3600
3601 if (!checkTxnObj(txnobj, &txn))
3602 return NULL;
3603 CHECK_ENV_NOT_CLOSED(self);
3604
3605 return (PyObject*)newDBTxnObject(self, txn, flags);
3606}
3607
3608
3609static PyObject*
3610DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3611{
3612 int err, kbyte=0, min=0, flags=0;
3613
3614 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3615 return NULL;
3616 CHECK_ENV_NOT_CLOSED(self);
3617
3618 MYDB_BEGIN_ALLOW_THREADS;
3619#if (DBVER >= 40)
3620 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3621#else
3622 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3623#endif
3624 MYDB_END_ALLOW_THREADS;
3625 RETURN_IF_ERR();
3626 RETURN_NONE();
3627}
3628
3629
3630static PyObject*
3631DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3632{
3633 int err, max;
3634
3635 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3636 return NULL;
3637 CHECK_ENV_NOT_CLOSED(self);
3638
3639 MYDB_BEGIN_ALLOW_THREADS;
3640 err = self->db_env->set_tx_max(self->db_env, max);
3641 MYDB_END_ALLOW_THREADS;
3642 RETURN_IF_ERR();
3643 RETURN_NONE();
3644}
3645
3646
3647static PyObject*
3648DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3649{
3650 int err, atype, flags=0;
3651 int aborted = 0;
3652
3653 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3654 return NULL;
3655 CHECK_ENV_NOT_CLOSED(self);
3656
3657 MYDB_BEGIN_ALLOW_THREADS;
3658#if (DBVER >= 40)
3659 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3660#else
3661 err = lock_detect(self->db_env, flags, atype, &aborted);
3662#endif
3663 MYDB_END_ALLOW_THREADS;
3664 RETURN_IF_ERR();
3665 return PyInt_FromLong(aborted);
3666}
3667
3668
3669static PyObject*
3670DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3671{
3672 int flags=0;
3673 int locker, lock_mode;
3674 DBT obj;
3675 PyObject* objobj;
3676
3677 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3678 return NULL;
3679
3680
3681 if (!make_dbt(objobj, &obj))
3682 return NULL;
3683
3684 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3685}
3686
3687
3688static PyObject*
3689DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3690{
3691 int err;
3692 u_int32_t theID;
3693
3694 if (!PyArg_ParseTuple(args, ":lock_id"))
3695 return NULL;
3696
3697 CHECK_ENV_NOT_CLOSED(self);
3698 MYDB_BEGIN_ALLOW_THREADS;
3699#if (DBVER >= 40)
3700 err = self->db_env->lock_id(self->db_env, &theID);
3701#else
3702 err = lock_id(self->db_env, &theID);
3703#endif
3704 MYDB_END_ALLOW_THREADS;
3705 RETURN_IF_ERR();
3706
3707 return PyInt_FromLong((long)theID);
3708}
3709
3710
3711static PyObject*
3712DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3713{
3714 int err;
3715 DBLockObject* dblockobj;
3716
3717 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3718 return NULL;
3719
3720 CHECK_ENV_NOT_CLOSED(self);
3721 MYDB_BEGIN_ALLOW_THREADS;
3722#if (DBVER >= 40)
3723 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3724#else
3725 err = lock_put(self->db_env, &dblockobj->lock);
3726#endif
3727 MYDB_END_ALLOW_THREADS;
3728 RETURN_IF_ERR();
3729 RETURN_NONE();
3730}
3731
3732
3733static PyObject*
3734DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3735{
3736 int err;
3737 DB_LOCK_STAT* sp;
3738 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003739 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003740
3741 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3742 return NULL;
3743 CHECK_ENV_NOT_CLOSED(self);
3744
3745 MYDB_BEGIN_ALLOW_THREADS;
3746#if (DBVER >= 40)
3747 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3748#else
3749#if (DBVER >= 33)
3750 err = lock_stat(self->db_env, &sp);
3751#else
3752 err = lock_stat(self->db_env, &sp, NULL);
3753#endif
3754#endif
3755 MYDB_END_ALLOW_THREADS;
3756 RETURN_IF_ERR();
3757
3758 /* Turn the stat structure into a dictionary */
3759 d = PyDict_New();
3760 if (d == NULL) {
3761 free(sp);
3762 return NULL;
3763 }
3764
3765#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3766
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003767#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003768 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003769#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003770 MAKE_ENTRY(nmodes);
3771#if (DBVER >= 32)
3772 MAKE_ENTRY(maxlocks);
3773 MAKE_ENTRY(maxlockers);
3774 MAKE_ENTRY(maxobjects);
3775 MAKE_ENTRY(nlocks);
3776 MAKE_ENTRY(maxnlocks);
3777#endif
3778 MAKE_ENTRY(nlockers);
3779 MAKE_ENTRY(maxnlockers);
3780#if (DBVER >= 32)
3781 MAKE_ENTRY(nobjects);
3782 MAKE_ENTRY(maxnobjects);
3783#endif
3784 MAKE_ENTRY(nrequests);
3785 MAKE_ENTRY(nreleases);
3786 MAKE_ENTRY(nnowaits);
3787 MAKE_ENTRY(nconflicts);
3788 MAKE_ENTRY(ndeadlocks);
3789 MAKE_ENTRY(regsize);
3790 MAKE_ENTRY(region_wait);
3791 MAKE_ENTRY(region_nowait);
3792
3793#undef MAKE_ENTRY
3794 free(sp);
3795 return d;
3796}
3797
3798
3799static PyObject*
3800DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3801{
3802 int flags=0;
3803 int err;
3804 char **log_list_start, **log_list;
3805 PyObject* list;
3806 PyObject* item = NULL;
3807
3808 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3809 return NULL;
3810
3811 CHECK_ENV_NOT_CLOSED(self);
3812 MYDB_BEGIN_ALLOW_THREADS;
3813#if (DBVER >= 40)
3814 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3815#elif (DBVER == 33)
3816 err = log_archive(self->db_env, &log_list, flags);
3817#else
3818 err = log_archive(self->db_env, &log_list, flags, NULL);
3819#endif
3820 MYDB_END_ALLOW_THREADS;
3821 RETURN_IF_ERR();
3822
3823 list = PyList_New(0);
3824 if (list == NULL) {
3825 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3826 return NULL;
3827 }
3828
3829 if (log_list) {
3830 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3831 item = PyString_FromString (*log_list);
3832 if (item == NULL) {
3833 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003834 PyErr_SetString(PyExc_MemoryError,
3835 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003836 list = NULL;
3837 break;
3838 }
3839 PyList_Append(list, item);
3840 Py_DECREF(item);
3841 }
3842 free(log_list_start);
3843 }
3844 return list;
3845}
3846
3847
3848static PyObject*
3849DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3850{
3851 int err;
3852 DB_TXN_STAT* sp;
3853 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003854 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855
3856 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3857 return NULL;
3858 CHECK_ENV_NOT_CLOSED(self);
3859
3860 MYDB_BEGIN_ALLOW_THREADS;
3861#if (DBVER >= 40)
3862 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3863#elif (DBVER == 33)
3864 err = txn_stat(self->db_env, &sp);
3865#else
3866 err = txn_stat(self->db_env, &sp, NULL);
3867#endif
3868 MYDB_END_ALLOW_THREADS;
3869 RETURN_IF_ERR();
3870
3871 /* Turn the stat structure into a dictionary */
3872 d = PyDict_New();
3873 if (d == NULL) {
3874 free(sp);
3875 return NULL;
3876 }
3877
3878#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3879
3880 MAKE_ENTRY(time_ckp);
3881 MAKE_ENTRY(last_txnid);
3882 MAKE_ENTRY(maxtxns);
3883 MAKE_ENTRY(nactive);
3884 MAKE_ENTRY(maxnactive);
3885 MAKE_ENTRY(nbegins);
3886 MAKE_ENTRY(naborts);
3887 MAKE_ENTRY(ncommits);
3888 MAKE_ENTRY(regsize);
3889 MAKE_ENTRY(region_wait);
3890 MAKE_ENTRY(region_nowait);
3891
3892#undef MAKE_ENTRY
3893 free(sp);
3894 return d;
3895}
3896
3897
3898static PyObject*
3899DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3900{
3901 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003902 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003903
3904 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3905 return NULL;
3906 CHECK_ENV_NOT_CLOSED(self);
3907
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003908 if (self->moduleFlags.getReturnsNone)
3909 ++oldValue;
3910 if (self->moduleFlags.cursorSetReturnsNone)
3911 ++oldValue;
3912 self->moduleFlags.getReturnsNone = (flags >= 1);
3913 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003914 return PyInt_FromLong(oldValue);
3915}
3916
3917
3918/* --------------------------------------------------------------------- */
3919/* DBTxn methods */
3920
3921
3922static PyObject*
3923DBTxn_commit(DBTxnObject* self, PyObject* args)
3924{
3925 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003926 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003927
3928 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3929 return NULL;
3930
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003931 if (!self->txn) {
3932 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3933 "DBTxn must not be used after txn_commit or txn_abort"));
3934 return NULL;
3935 }
3936 txn = self->txn;
3937 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003938 MYDB_BEGIN_ALLOW_THREADS;
3939#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003940 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003941#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003942 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003943#endif
3944 MYDB_END_ALLOW_THREADS;
3945 RETURN_IF_ERR();
3946 RETURN_NONE();
3947}
3948
3949static PyObject*
3950DBTxn_prepare(DBTxnObject* self, PyObject* args)
3951{
3952#if (DBVER >= 33)
3953 int err;
3954 char* gid=NULL;
3955 int gid_size=0;
3956
3957 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3958 return NULL;
3959
3960 if (gid_size != DB_XIDDATASIZE) {
3961 PyErr_SetString(PyExc_TypeError,
3962 "gid must be DB_XIDDATASIZE bytes long");
3963 return NULL;
3964 }
3965
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003966 if (!self->txn) {
3967 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3968 "DBTxn must not be used after txn_commit or txn_abort"));
3969 return NULL;
3970 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003971 MYDB_BEGIN_ALLOW_THREADS;
3972#if (DBVER >= 40)
3973 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3974#else
3975 err = txn_prepare(self->txn, (u_int8_t*)gid);
3976#endif
3977 MYDB_END_ALLOW_THREADS;
3978 RETURN_IF_ERR();
3979 RETURN_NONE();
3980#else
3981 int err;
3982
3983 if (!PyArg_ParseTuple(args, ":prepare"))
3984 return NULL;
3985
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003986 if (!self->txn) {
3987 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3988 "DBTxn must not be used after txn_commit or txn_abort"));
3989 return NULL;
3990 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991 MYDB_BEGIN_ALLOW_THREADS;
3992 err = txn_prepare(self->txn);
3993 MYDB_END_ALLOW_THREADS;
3994 RETURN_IF_ERR();
3995 RETURN_NONE();
3996#endif
3997}
3998
3999
4000static PyObject*
4001DBTxn_abort(DBTxnObject* self, PyObject* args)
4002{
4003 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004004 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004005
4006 if (!PyArg_ParseTuple(args, ":abort"))
4007 return NULL;
4008
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004009 if (!self->txn) {
4010 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4011 "DBTxn must not be used after txn_commit or txn_abort"));
4012 return NULL;
4013 }
4014 txn = self->txn;
4015 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004016 MYDB_BEGIN_ALLOW_THREADS;
4017#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004018 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004019#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004020 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004021#endif
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
4026
4027
4028static PyObject*
4029DBTxn_id(DBTxnObject* self, PyObject* args)
4030{
4031 int id;
4032
4033 if (!PyArg_ParseTuple(args, ":id"))
4034 return NULL;
4035
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004036 if (!self->txn) {
4037 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4038 "DBTxn must not be used after txn_commit or txn_abort"));
4039 return NULL;
4040 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004041 MYDB_BEGIN_ALLOW_THREADS;
4042#if (DBVER >= 40)
4043 id = self->txn->id(self->txn);
4044#else
4045 id = txn_id(self->txn);
4046#endif
4047 MYDB_END_ALLOW_THREADS;
4048 return PyInt_FromLong(id);
4049}
4050
4051/* --------------------------------------------------------------------- */
4052/* Method definition tables and type objects */
4053
4054static PyMethodDef DB_methods[] = {
4055 {"append", (PyCFunction)DB_append, METH_VARARGS},
4056#if (DBVER >= 33)
4057 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4058#endif
4059 {"close", (PyCFunction)DB_close, METH_VARARGS},
4060#if (DBVER >= 32)
4061 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4062 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4063#endif
4064 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4065 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4066 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4067 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4068 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4069 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4070 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4071 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4072 {"join", (PyCFunction)DB_join, METH_VARARGS},
4073 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4074 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4075 {"items", (PyCFunction)DB_items, METH_VARARGS},
4076 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4077 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4078 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4079 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4080 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4081 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4082 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004083#if (DBVER >= 41)
4084 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4085#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004086 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4087 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4088 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4089 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4090 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4091 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4092 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4093 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4094 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4095#if (DBVER >= 32)
4096 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4097#endif
4098 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4099 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4100#if (DBVER >= 33)
4101 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4102#endif
4103 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4104 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4105 {"values", (PyCFunction)DB_values, METH_VARARGS},
4106 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4107 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4108 {NULL, NULL} /* sentinel */
4109};
4110
4111
4112static PyMappingMethods DB_mapping = {
4113 (inquiry)DB_length, /*mp_length*/
4114 (binaryfunc)DB_subscript, /*mp_subscript*/
4115 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4116};
4117
4118
4119static PyMethodDef DBCursor_methods[] = {
4120 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4121 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4122 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4123 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4124 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4125 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4126 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4127 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4128 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4129 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4130 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4131 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4132 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4133 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4134 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004135 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004136 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004137 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4138 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4139 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4140 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4141 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4142 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4143 {NULL, NULL} /* sentinel */
4144};
4145
4146
4147static PyMethodDef DBEnv_methods[] = {
4148 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4149 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4150 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004151#if (DBVER >= 41)
4152 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4153 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4154 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4155#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004156#if (DBVER >= 40)
4157 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4158#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004159 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004160 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4161 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4162#if (DBVER >= 32)
4163 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4164#endif
4165 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4166 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4167 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4168 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4169 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4170#if (DBVER >= 32)
4171 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4172 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4173 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4174#endif
4175 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4176 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4177 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4178 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4179 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4180 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4181 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4182 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4183 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4184 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4185 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4186 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4187 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4188 {NULL, NULL} /* sentinel */
4189};
4190
4191
4192static PyMethodDef DBTxn_methods[] = {
4193 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4194 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4195 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4196 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4197 {NULL, NULL} /* sentinel */
4198};
4199
4200
4201static PyObject*
4202DB_getattr(DBObject* self, char *name)
4203{
4204 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4205}
4206
4207
4208static PyObject*
4209DBEnv_getattr(DBEnvObject* self, char *name)
4210{
4211 if (!strcmp(name, "db_home")) {
4212 CHECK_ENV_NOT_CLOSED(self);
4213 if (self->db_env->db_home == NULL) {
4214 RETURN_NONE();
4215 }
4216 return PyString_FromString(self->db_env->db_home);
4217 }
4218
4219 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4220}
4221
4222
4223static PyObject*
4224DBCursor_getattr(DBCursorObject* self, char *name)
4225{
4226 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4227}
4228
4229static PyObject*
4230DBTxn_getattr(DBTxnObject* self, char *name)
4231{
4232 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4233}
4234
4235static PyObject*
4236DBLock_getattr(DBLockObject* self, char *name)
4237{
4238 return NULL;
4239}
4240
4241statichere PyTypeObject DB_Type = {
4242 PyObject_HEAD_INIT(NULL)
4243 0, /*ob_size*/
4244 "DB", /*tp_name*/
4245 sizeof(DBObject), /*tp_basicsize*/
4246 0, /*tp_itemsize*/
4247 /* methods */
4248 (destructor)DB_dealloc, /*tp_dealloc*/
4249 0, /*tp_print*/
4250 (getattrfunc)DB_getattr, /*tp_getattr*/
4251 0, /*tp_setattr*/
4252 0, /*tp_compare*/
4253 0, /*tp_repr*/
4254 0, /*tp_as_number*/
4255 0, /*tp_as_sequence*/
4256 &DB_mapping,/*tp_as_mapping*/
4257 0, /*tp_hash*/
4258};
4259
4260
4261statichere PyTypeObject DBCursor_Type = {
4262 PyObject_HEAD_INIT(NULL)
4263 0, /*ob_size*/
4264 "DBCursor", /*tp_name*/
4265 sizeof(DBCursorObject), /*tp_basicsize*/
4266 0, /*tp_itemsize*/
4267 /* methods */
4268 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4269 0, /*tp_print*/
4270 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4271 0, /*tp_setattr*/
4272 0, /*tp_compare*/
4273 0, /*tp_repr*/
4274 0, /*tp_as_number*/
4275 0, /*tp_as_sequence*/
4276 0, /*tp_as_mapping*/
4277 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004278#ifdef HAVE_WEAKREF
4279 0, /* tp_call */
4280 0, /* tp_str */
4281 0, /* tp_getattro */
4282 0, /* tp_setattro */
4283 0, /* tp_as_buffer */
4284 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4285 0, /* tp_doc */
4286 0, /* tp_traverse */
4287 0, /* tp_clear */
4288 0, /* tp_richcompare */
4289 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4290#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004291};
4292
4293
4294statichere PyTypeObject DBEnv_Type = {
4295 PyObject_HEAD_INIT(NULL)
4296 0, /*ob_size*/
4297 "DBEnv", /*tp_name*/
4298 sizeof(DBEnvObject), /*tp_basicsize*/
4299 0, /*tp_itemsize*/
4300 /* methods */
4301 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4302 0, /*tp_print*/
4303 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4304 0, /*tp_setattr*/
4305 0, /*tp_compare*/
4306 0, /*tp_repr*/
4307 0, /*tp_as_number*/
4308 0, /*tp_as_sequence*/
4309 0, /*tp_as_mapping*/
4310 0, /*tp_hash*/
4311};
4312
4313statichere PyTypeObject DBTxn_Type = {
4314 PyObject_HEAD_INIT(NULL)
4315 0, /*ob_size*/
4316 "DBTxn", /*tp_name*/
4317 sizeof(DBTxnObject), /*tp_basicsize*/
4318 0, /*tp_itemsize*/
4319 /* methods */
4320 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4321 0, /*tp_print*/
4322 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4323 0, /*tp_setattr*/
4324 0, /*tp_compare*/
4325 0, /*tp_repr*/
4326 0, /*tp_as_number*/
4327 0, /*tp_as_sequence*/
4328 0, /*tp_as_mapping*/
4329 0, /*tp_hash*/
4330};
4331
4332
4333statichere PyTypeObject DBLock_Type = {
4334 PyObject_HEAD_INIT(NULL)
4335 0, /*ob_size*/
4336 "DBLock", /*tp_name*/
4337 sizeof(DBLockObject), /*tp_basicsize*/
4338 0, /*tp_itemsize*/
4339 /* methods */
4340 (destructor)DBLock_dealloc, /*tp_dealloc*/
4341 0, /*tp_print*/
4342 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4343 0, /*tp_setattr*/
4344 0, /*tp_compare*/
4345 0, /*tp_repr*/
4346 0, /*tp_as_number*/
4347 0, /*tp_as_sequence*/
4348 0, /*tp_as_mapping*/
4349 0, /*tp_hash*/
4350};
4351
4352
4353/* --------------------------------------------------------------------- */
4354/* Module-level functions */
4355
4356static PyObject*
4357DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4358{
4359 PyObject* dbenvobj = NULL;
4360 int flags = 0;
4361 char* kwnames[] = { "dbEnv", "flags", NULL};
4362
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004363 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4364 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004365 return NULL;
4366 if (dbenvobj == Py_None)
4367 dbenvobj = NULL;
4368 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4369 makeTypeError("DBEnv", dbenvobj);
4370 return NULL;
4371 }
4372
4373 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4374}
4375
4376
4377static PyObject*
4378DBEnv_construct(PyObject* self, PyObject* args)
4379{
4380 int flags = 0;
4381 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4382 return (PyObject* )newDBEnvObject(flags);
4383}
4384
4385
4386static char bsddb_version_doc[] =
4387"Returns a tuple of major, minor, and patch release numbers of the\n\
4388underlying DB library.";
4389
4390static PyObject*
4391bsddb_version(PyObject* self, PyObject* args)
4392{
4393 int major, minor, patch;
4394
4395 if (!PyArg_ParseTuple(args, ":version"))
4396 return NULL;
4397 db_version(&major, &minor, &patch);
4398 return Py_BuildValue("(iii)", major, minor, patch);
4399}
4400
4401
4402/* List of functions defined in the module */
4403
4404static PyMethodDef bsddb_methods[] = {
4405 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4406 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4407 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4408 {NULL, NULL} /* sentinel */
4409};
4410
4411
4412/* --------------------------------------------------------------------- */
4413/* Module initialization */
4414
4415
4416/* Convenience routine to export an integer value.
4417 * Errors are silently ignored, for better or for worse...
4418 */
4419#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4420
Gregory P. Smith41631e82003-09-21 00:08:14 +00004421#define MODULE_NAME_MAX_LEN 11
4422static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004423
4424DL_EXPORT(void) init_bsddb(void)
4425{
4426 PyObject* m;
4427 PyObject* d;
4428 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4429 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4430 PyObject* cvsid_s = PyString_FromString( rcs_id );
4431
4432 /* Initialize the type of the new type objects here; doing it here
4433 is required for portability to Windows without requiring C++. */
4434 DB_Type.ob_type = &PyType_Type;
4435 DBCursor_Type.ob_type = &PyType_Type;
4436 DBEnv_Type.ob_type = &PyType_Type;
4437 DBTxn_Type.ob_type = &PyType_Type;
4438 DBLock_Type.ob_type = &PyType_Type;
4439
4440
Mark Hammonda69d4092003-04-22 23:13:27 +00004441#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004442 /* Save the current interpreter, so callbacks can do the right thing. */
4443 _db_interpreterState = PyThreadState_Get()->interp;
4444#endif
4445
4446 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004447 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004448
4449 /* Add some symbolic constants to the module */
4450 d = PyModule_GetDict(m);
4451 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4452 PyDict_SetItemString(d, "cvsid", cvsid_s);
4453 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4454 Py_DECREF(pybsddb_version_s);
4455 pybsddb_version_s = NULL;
4456 Py_DECREF(cvsid_s);
4457 cvsid_s = NULL;
4458 Py_DECREF(db_version_s);
4459 db_version_s = NULL;
4460
4461 ADD_INT(d, DB_VERSION_MAJOR);
4462 ADD_INT(d, DB_VERSION_MINOR);
4463 ADD_INT(d, DB_VERSION_PATCH);
4464
4465 ADD_INT(d, DB_MAX_PAGES);
4466 ADD_INT(d, DB_MAX_RECORDS);
4467
Gregory P. Smith41631e82003-09-21 00:08:14 +00004468#if (DBVER >= 42)
4469 ADD_INT(d, DB_RPCCLIENT);
4470#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004471 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004472 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4473 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4474#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004475 ADD_INT(d, DB_XA_CREATE);
4476
4477 ADD_INT(d, DB_CREATE);
4478 ADD_INT(d, DB_NOMMAP);
4479 ADD_INT(d, DB_THREAD);
4480
4481 ADD_INT(d, DB_FORCE);
4482 ADD_INT(d, DB_INIT_CDB);
4483 ADD_INT(d, DB_INIT_LOCK);
4484 ADD_INT(d, DB_INIT_LOG);
4485 ADD_INT(d, DB_INIT_MPOOL);
4486 ADD_INT(d, DB_INIT_TXN);
4487#if (DBVER >= 32)
4488 ADD_INT(d, DB_JOINENV);
4489#endif
4490
4491 ADD_INT(d, DB_RECOVER);
4492 ADD_INT(d, DB_RECOVER_FATAL);
4493 ADD_INT(d, DB_TXN_NOSYNC);
4494 ADD_INT(d, DB_USE_ENVIRON);
4495 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4496
4497 ADD_INT(d, DB_LOCKDOWN);
4498 ADD_INT(d, DB_PRIVATE);
4499 ADD_INT(d, DB_SYSTEM_MEM);
4500
4501 ADD_INT(d, DB_TXN_SYNC);
4502 ADD_INT(d, DB_TXN_NOWAIT);
4503
4504 ADD_INT(d, DB_EXCL);
4505 ADD_INT(d, DB_FCNTL_LOCKING);
4506 ADD_INT(d, DB_ODDFILESIZE);
4507 ADD_INT(d, DB_RDWRMASTER);
4508 ADD_INT(d, DB_RDONLY);
4509 ADD_INT(d, DB_TRUNCATE);
4510#if (DBVER >= 32)
4511 ADD_INT(d, DB_EXTENT);
4512 ADD_INT(d, DB_CDB_ALLDB);
4513 ADD_INT(d, DB_VERIFY);
4514#endif
4515 ADD_INT(d, DB_UPGRADE);
4516
4517 ADD_INT(d, DB_AGGRESSIVE);
4518 ADD_INT(d, DB_NOORDERCHK);
4519 ADD_INT(d, DB_ORDERCHKONLY);
4520 ADD_INT(d, DB_PR_PAGE);
4521#if ! (DBVER >= 33)
4522 ADD_INT(d, DB_VRFY_FLAGMASK);
4523 ADD_INT(d, DB_PR_HEADERS);
4524#endif
4525 ADD_INT(d, DB_PR_RECOVERYTEST);
4526 ADD_INT(d, DB_SALVAGE);
4527
4528 ADD_INT(d, DB_LOCK_NORUN);
4529 ADD_INT(d, DB_LOCK_DEFAULT);
4530 ADD_INT(d, DB_LOCK_OLDEST);
4531 ADD_INT(d, DB_LOCK_RANDOM);
4532 ADD_INT(d, DB_LOCK_YOUNGEST);
4533#if (DBVER >= 33)
4534 ADD_INT(d, DB_LOCK_MAXLOCKS);
4535 ADD_INT(d, DB_LOCK_MINLOCKS);
4536 ADD_INT(d, DB_LOCK_MINWRITE);
4537#endif
4538
4539
4540#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004541 /* docs say to use zero instead */
4542 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004543#else
4544 ADD_INT(d, DB_LOCK_CONFLICT);
4545#endif
4546
4547 ADD_INT(d, DB_LOCK_DUMP);
4548 ADD_INT(d, DB_LOCK_GET);
4549 ADD_INT(d, DB_LOCK_INHERIT);
4550 ADD_INT(d, DB_LOCK_PUT);
4551 ADD_INT(d, DB_LOCK_PUT_ALL);
4552 ADD_INT(d, DB_LOCK_PUT_OBJ);
4553
4554 ADD_INT(d, DB_LOCK_NG);
4555 ADD_INT(d, DB_LOCK_READ);
4556 ADD_INT(d, DB_LOCK_WRITE);
4557 ADD_INT(d, DB_LOCK_NOWAIT);
4558#if (DBVER >= 32)
4559 ADD_INT(d, DB_LOCK_WAIT);
4560#endif
4561 ADD_INT(d, DB_LOCK_IWRITE);
4562 ADD_INT(d, DB_LOCK_IREAD);
4563 ADD_INT(d, DB_LOCK_IWR);
4564#if (DBVER >= 33)
4565 ADD_INT(d, DB_LOCK_DIRTY);
4566 ADD_INT(d, DB_LOCK_WWRITE);
4567#endif
4568
4569 ADD_INT(d, DB_LOCK_RECORD);
4570 ADD_INT(d, DB_LOCK_UPGRADE);
4571#if (DBVER >= 32)
4572 ADD_INT(d, DB_LOCK_SWITCH);
4573#endif
4574#if (DBVER >= 33)
4575 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4576#endif
4577
4578 ADD_INT(d, DB_LOCK_NOWAIT);
4579 ADD_INT(d, DB_LOCK_RECORD);
4580 ADD_INT(d, DB_LOCK_UPGRADE);
4581
4582#if (DBVER >= 33)
4583 ADD_INT(d, DB_LSTAT_ABORTED);
4584 ADD_INT(d, DB_LSTAT_ERR);
4585 ADD_INT(d, DB_LSTAT_FREE);
4586 ADD_INT(d, DB_LSTAT_HELD);
4587#if (DBVER == 33)
4588 ADD_INT(d, DB_LSTAT_NOGRANT);
4589#endif
4590 ADD_INT(d, DB_LSTAT_PENDING);
4591 ADD_INT(d, DB_LSTAT_WAITING);
4592#endif
4593
4594 ADD_INT(d, DB_ARCH_ABS);
4595 ADD_INT(d, DB_ARCH_DATA);
4596 ADD_INT(d, DB_ARCH_LOG);
4597
4598 ADD_INT(d, DB_BTREE);
4599 ADD_INT(d, DB_HASH);
4600 ADD_INT(d, DB_RECNO);
4601 ADD_INT(d, DB_QUEUE);
4602 ADD_INT(d, DB_UNKNOWN);
4603
4604 ADD_INT(d, DB_DUP);
4605 ADD_INT(d, DB_DUPSORT);
4606 ADD_INT(d, DB_RECNUM);
4607 ADD_INT(d, DB_RENUMBER);
4608 ADD_INT(d, DB_REVSPLITOFF);
4609 ADD_INT(d, DB_SNAPSHOT);
4610
4611 ADD_INT(d, DB_JOIN_NOSORT);
4612
4613 ADD_INT(d, DB_AFTER);
4614 ADD_INT(d, DB_APPEND);
4615 ADD_INT(d, DB_BEFORE);
4616 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004617#if (DBVER >= 41)
4618 _addIntToDict(d, "DB_CHECKPOINT", 0);
4619#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004620 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004621 ADD_INT(d, DB_CURLSN);
4622#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004623#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004624 ADD_INT(d, DB_COMMIT);
4625#endif
4626 ADD_INT(d, DB_CONSUME);
4627#if (DBVER >= 32)
4628 ADD_INT(d, DB_CONSUME_WAIT);
4629#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630 ADD_INT(d, DB_CURRENT);
4631#if (DBVER >= 33)
4632 ADD_INT(d, DB_FAST_STAT);
4633#endif
4634 ADD_INT(d, DB_FIRST);
4635 ADD_INT(d, DB_FLUSH);
4636 ADD_INT(d, DB_GET_BOTH);
4637 ADD_INT(d, DB_GET_RECNO);
4638 ADD_INT(d, DB_JOIN_ITEM);
4639 ADD_INT(d, DB_KEYFIRST);
4640 ADD_INT(d, DB_KEYLAST);
4641 ADD_INT(d, DB_LAST);
4642 ADD_INT(d, DB_NEXT);
4643 ADD_INT(d, DB_NEXT_DUP);
4644 ADD_INT(d, DB_NEXT_NODUP);
4645 ADD_INT(d, DB_NODUPDATA);
4646 ADD_INT(d, DB_NOOVERWRITE);
4647 ADD_INT(d, DB_NOSYNC);
4648 ADD_INT(d, DB_POSITION);
4649 ADD_INT(d, DB_PREV);
4650 ADD_INT(d, DB_PREV_NODUP);
4651 ADD_INT(d, DB_RECORDCOUNT);
4652 ADD_INT(d, DB_SET);
4653 ADD_INT(d, DB_SET_RANGE);
4654 ADD_INT(d, DB_SET_RECNO);
4655 ADD_INT(d, DB_WRITECURSOR);
4656
4657 ADD_INT(d, DB_OPFLAGS_MASK);
4658 ADD_INT(d, DB_RMW);
4659#if (DBVER >= 33)
4660 ADD_INT(d, DB_DIRTY_READ);
4661 ADD_INT(d, DB_MULTIPLE);
4662 ADD_INT(d, DB_MULTIPLE_KEY);
4663#endif
4664
4665#if (DBVER >= 33)
4666 ADD_INT(d, DB_DONOTINDEX);
4667#endif
4668
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004669#if (DBVER >= 41)
4670 _addIntToDict(d, "DB_INCOMPLETE", 0);
4671#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004672 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004673#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004674 ADD_INT(d, DB_KEYEMPTY);
4675 ADD_INT(d, DB_KEYEXIST);
4676 ADD_INT(d, DB_LOCK_DEADLOCK);
4677 ADD_INT(d, DB_LOCK_NOTGRANTED);
4678 ADD_INT(d, DB_NOSERVER);
4679 ADD_INT(d, DB_NOSERVER_HOME);
4680 ADD_INT(d, DB_NOSERVER_ID);
4681 ADD_INT(d, DB_NOTFOUND);
4682 ADD_INT(d, DB_OLD_VERSION);
4683 ADD_INT(d, DB_RUNRECOVERY);
4684 ADD_INT(d, DB_VERIFY_BAD);
4685#if (DBVER >= 33)
4686 ADD_INT(d, DB_PAGE_NOTFOUND);
4687 ADD_INT(d, DB_SECONDARY_BAD);
4688#endif
4689#if (DBVER >= 40)
4690 ADD_INT(d, DB_STAT_CLEAR);
4691 ADD_INT(d, DB_REGION_INIT);
4692 ADD_INT(d, DB_NOLOCKING);
4693 ADD_INT(d, DB_YIELDCPU);
4694 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4695 ADD_INT(d, DB_NOPANIC);
4696#endif
4697
Gregory P. Smith41631e82003-09-21 00:08:14 +00004698#if (DBVER >= 42)
4699 ADD_INT(d, DB_TIME_NOTGRANTED);
4700 ADD_INT(d, DB_TXN_NOT_DURABLE);
4701 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4702 ADD_INT(d, DB_LOG_AUTOREMOVE);
4703 ADD_INT(d, DB_DIRECT_LOG);
4704 ADD_INT(d, DB_DIRECT_DB);
4705 ADD_INT(d, DB_INIT_REP);
4706 ADD_INT(d, DB_ENCRYPT);
4707 ADD_INT(d, DB_CHKSUM);
4708#endif
4709
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004710#if (DBVER >= 41)
4711 ADD_INT(d, DB_ENCRYPT_AES);
4712 ADD_INT(d, DB_AUTO_COMMIT);
4713#else
4714 /* allow berkeleydb 4.1 aware apps to run on older versions */
4715 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4716#endif
4717
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 ADD_INT(d, EINVAL);
4719 ADD_INT(d, EACCES);
4720 ADD_INT(d, ENOSPC);
4721 ADD_INT(d, ENOMEM);
4722 ADD_INT(d, EAGAIN);
4723 ADD_INT(d, EBUSY);
4724 ADD_INT(d, EEXIST);
4725 ADD_INT(d, ENOENT);
4726 ADD_INT(d, EPERM);
4727
Barry Warsaw1baa9822003-03-31 19:51:29 +00004728#if (DBVER >= 40)
4729 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4730 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4731#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004732
4733 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004734 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004735 PyDict_SetItemString(d, "DBError", DBError);
4736
4737 /* Some magic to make DBNotFoundError derive from both DBError and
4738 KeyError, since the API only supports using one base class. */
4739 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4740 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4741 Py_file_input, d, d);
4742 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4743 PyDict_DelItemString(d, "KeyError");
4744
4745
4746 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004747#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004748 PyDict_SetItemString(d, #name, name)
4749
4750#if !INCOMPLETE_IS_WARNING
4751 MAKE_EX(DBIncompleteError);
4752#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00004753 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004754 MAKE_EX(DBKeyEmptyError);
4755 MAKE_EX(DBKeyExistError);
4756 MAKE_EX(DBLockDeadlockError);
4757 MAKE_EX(DBLockNotGrantedError);
4758 MAKE_EX(DBOldVersionError);
4759 MAKE_EX(DBRunRecoveryError);
4760 MAKE_EX(DBVerifyBadError);
4761 MAKE_EX(DBNoServerError);
4762 MAKE_EX(DBNoServerHomeError);
4763 MAKE_EX(DBNoServerIDError);
4764#if (DBVER >= 33)
4765 MAKE_EX(DBPageNotFoundError);
4766 MAKE_EX(DBSecondaryBadError);
4767#endif
4768
4769 MAKE_EX(DBInvalidArgError);
4770 MAKE_EX(DBAccessError);
4771 MAKE_EX(DBNoSpaceError);
4772 MAKE_EX(DBNoMemoryError);
4773 MAKE_EX(DBAgainError);
4774 MAKE_EX(DBBusyError);
4775 MAKE_EX(DBFileExistsError);
4776 MAKE_EX(DBNoSuchFileError);
4777 MAKE_EX(DBPermissionsError);
4778
4779#undef MAKE_EX
4780
4781 /* Check for errors */
4782 if (PyErr_Occurred()) {
4783 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004784 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 }
4786}
Gregory P. Smith41631e82003-09-21 00:08:14 +00004787
4788/* allow this module to be named _pybsddb so that it can be installed
4789 * and imported on top of python >= 2.3 that includes its own older
4790 * copy of the library named _bsddb without importing the old version. */
4791DL_EXPORT(void) init_pybsddb(void)
4792{
4793 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
4794 init_bsddb();
4795}