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