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