blob: 6eb48664fe51a28ec71813c82f090cd17dd4449a [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. Smith0c657712004-03-16 06:56:58 +0000100#define PY_BSDDB_VERSION "4.2.6"
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;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002404 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002405 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 }
Gregory P. Smitha7befda2004-02-26 10:07:14 +00002943 if (_DB_get_type(self->mydb) == DB_BTREE) {
2944 /* the only time a malloced key is returned is when we
2945 * call this on a BTree database because it performs
2946 * partial matching and needs to return the real key.
2947 * All others leave key untouched [where calling free()
2948 * on it would often segfault].
2949 */
2950 FREE_DBT(key);
2951 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002952 FREE_DBT(data);
2953 }
2954
2955 return retval;
2956}
2957
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002958static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002959_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2960 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002962 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002964 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965
Gregory P. Smith7441e652003-11-03 21:35:31 +00002966 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2968 return NULL;
2969 if (!make_dbt(dataobj, &data))
2970 return NULL;
2971
2972 MYDB_BEGIN_ALLOW_THREADS;
2973 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2974 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002975 if ((err == DB_NOTFOUND) && returnsNone) {
2976 Py_INCREF(Py_None);
2977 retval = Py_None;
2978 }
2979 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 retval = NULL;
2981 }
2982 else {
2983 switch (_DB_get_type(self->mydb)) {
2984 case -1:
2985 retval = NULL;
2986 break;
2987 case DB_BTREE:
2988 case DB_HASH:
2989 default:
2990 retval = Py_BuildValue("s#s#", key.data, key.size,
2991 data.data, data.size);
2992 break;
2993 case DB_RECNO:
2994 case DB_QUEUE:
2995 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2996 data.data, data.size);
2997 break;
2998 }
2999 }
3000
3001 FREE_DBT(key);
3002 return retval;
3003}
3004
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003005static PyObject*
3006DBC_get_both(DBCursorObject* self, PyObject* args)
3007{
3008 int flags=0;
3009 PyObject *keyobj, *dataobj;
3010
3011 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3012 return NULL;
3013
Gregory P. Smith7441e652003-11-03 21:35:31 +00003014 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003015 CHECK_CURSOR_NOT_CLOSED(self);
3016
3017 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3018 self->mydb->moduleFlags.getReturnsNone);
3019}
3020
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003021/* Return size of entry */
3022static PyObject*
3023DBC_get_current_size(DBCursorObject* self, PyObject* args)
3024{
3025 int err, flags=DB_CURRENT;
3026 PyObject* retval = NULL;
3027 DBT key, data;
3028
3029 if (!PyArg_ParseTuple(args, ":get_current_size"))
3030 return NULL;
3031 CHECK_CURSOR_NOT_CLOSED(self);
3032 CLEAR_DBT(key);
3033 CLEAR_DBT(data);
3034
3035 /* We don't allocate any memory, forcing a ENOMEM error and thus
3036 getting the record size. */
3037 data.flags = DB_DBT_USERMEM;
3038 data.ulen = 0;
3039 MYDB_BEGIN_ALLOW_THREADS;
3040 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3041 MYDB_END_ALLOW_THREADS;
3042 if (err == ENOMEM || !err) {
3043 /* ENOMEM means positive size, !err means zero length value */
3044 retval = PyInt_FromLong((long)data.size);
3045 err = 0;
3046 }
3047
3048 FREE_DBT(key);
3049 FREE_DBT(data);
3050 RETURN_IF_ERR();
3051 return retval;
3052}
3053
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003054static PyObject*
3055DBC_set_both(DBCursorObject* self, PyObject* args)
3056{
3057 int flags=0;
3058 PyObject *keyobj, *dataobj;
3059
3060 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3061 return NULL;
3062
Gregory P. Smith7441e652003-11-03 21:35:31 +00003063 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003064 CHECK_CURSOR_NOT_CLOSED(self);
3065
3066 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3067 self->mydb->moduleFlags.cursorSetReturnsNone);
3068}
3069
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003070
3071static PyObject*
3072DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3073{
3074 int err, irecno, flags=0;
3075 db_recno_t recno;
3076 DBT key, data;
3077 PyObject* retval;
3078 int dlen = -1;
3079 int doff = -1;
3080 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3081
3082 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3083 &irecno, &flags, &dlen, &doff))
3084 return NULL;
3085
3086 CHECK_CURSOR_NOT_CLOSED(self);
3087
3088 CLEAR_DBT(key);
3089 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003090 /* use allocated space so DB will be able to realloc room for the real
3091 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003092 key.data = malloc(sizeof(db_recno_t));
3093 if (key.data == NULL) {
3094 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3095 return NULL;
3096 }
3097 key.size = sizeof(db_recno_t);
3098 key.ulen = key.size;
3099 memcpy(key.data, &recno, sizeof(db_recno_t));
3100 key.flags = DB_DBT_REALLOC;
3101
3102 CLEAR_DBT(data);
3103 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3104 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3105 data.flags = DB_DBT_MALLOC;
3106 }
3107 if (!add_partial_dbt(&data, dlen, doff))
3108 return NULL;
3109
3110 MYDB_BEGIN_ALLOW_THREADS;
3111 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3112 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003113 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3114 Py_INCREF(Py_None);
3115 retval = Py_None;
3116 }
3117 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118 retval = NULL;
3119 }
3120 else { /* Can only be used for BTrees, so no need to return int key */
3121 retval = Py_BuildValue("s#s#", key.data, key.size,
3122 data.data, data.size);
3123 FREE_DBT(key);
3124 FREE_DBT(data);
3125 }
3126
3127 return retval;
3128}
3129
3130
3131static PyObject*
3132DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3133{
3134 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3135}
3136
3137
3138static PyObject*
3139DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3140{
3141 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3142}
3143
3144
3145static PyObject*
3146DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3147{
3148 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3149}
3150
3151
3152static PyObject*
3153DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3154{
3155 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3156}
3157
3158
3159static PyObject*
3160DBC_join_item(DBCursorObject* self, PyObject* args)
3161{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003162 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 DBT key, data;
3164 PyObject* retval;
3165
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003166 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167 return NULL;
3168
3169 CHECK_CURSOR_NOT_CLOSED(self);
3170
3171 CLEAR_DBT(key);
3172 CLEAR_DBT(data);
3173 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3174 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3175 key.flags = DB_DBT_MALLOC;
3176 }
3177
3178 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003179 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003180 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003181 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3182 Py_INCREF(Py_None);
3183 retval = Py_None;
3184 }
3185 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 retval = NULL;
3187 }
3188 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003189 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003190 FREE_DBT(key);
3191 }
3192
3193 return retval;
3194}
3195
3196
3197
3198/* --------------------------------------------------------------------- */
3199/* DBEnv methods */
3200
3201
3202static PyObject*
3203DBEnv_close(DBEnvObject* self, PyObject* args)
3204{
3205 int err, flags = 0;
3206
3207 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3208 return NULL;
3209 if (!self->closed) { /* Don't close more than once */
3210 MYDB_BEGIN_ALLOW_THREADS;
3211 err = self->db_env->close(self->db_env, flags);
3212 MYDB_END_ALLOW_THREADS;
3213 /* after calling DBEnv->close, regardless of error, this DBEnv
3214 * may not be accessed again (BerkeleyDB docs). */
3215 self->closed = 1;
3216 self->db_env = NULL;
3217 RETURN_IF_ERR();
3218 }
3219 RETURN_NONE();
3220}
3221
3222
3223static PyObject*
3224DBEnv_open(DBEnvObject* self, PyObject* args)
3225{
3226 int err, flags=0, mode=0660;
3227 char *db_home;
3228
3229 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3230 return NULL;
3231
3232 CHECK_ENV_NOT_CLOSED(self);
3233
3234 MYDB_BEGIN_ALLOW_THREADS;
3235 err = self->db_env->open(self->db_env, db_home, flags, mode);
3236 MYDB_END_ALLOW_THREADS;
3237 RETURN_IF_ERR();
3238 self->closed = 0;
3239 self->flags = flags;
3240 RETURN_NONE();
3241}
3242
3243
3244static PyObject*
3245DBEnv_remove(DBEnvObject* self, PyObject* args)
3246{
3247 int err, flags=0;
3248 char *db_home;
3249
3250 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3251 return NULL;
3252 CHECK_ENV_NOT_CLOSED(self);
3253 MYDB_BEGIN_ALLOW_THREADS;
3254 err = self->db_env->remove(self->db_env, db_home, flags);
3255 MYDB_END_ALLOW_THREADS;
3256 RETURN_IF_ERR();
3257 RETURN_NONE();
3258}
3259
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003260#if (DBVER >= 41)
3261static PyObject*
3262DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3263{
3264 int err;
3265 u_int32_t flags=0;
3266 char *file = NULL;
3267 char *database = NULL;
3268 PyObject *txnobj = NULL;
3269 DB_TXN *txn = NULL;
3270 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3271
3272 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3273 &file, &database, &txnobj, &flags)) {
3274 return NULL;
3275 }
3276 if (!checkTxnObj(txnobj, &txn)) {
3277 return NULL;
3278 }
3279 CHECK_ENV_NOT_CLOSED(self);
3280 MYDB_BEGIN_ALLOW_THREADS;
3281 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3282 MYDB_END_ALLOW_THREADS;
3283 RETURN_IF_ERR();
3284 RETURN_NONE();
3285}
3286
3287static PyObject*
3288DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3289{
3290 int err;
3291 u_int32_t flags=0;
3292 char *file = NULL;
3293 char *database = NULL;
3294 char *newname = NULL;
3295 PyObject *txnobj = NULL;
3296 DB_TXN *txn = NULL;
3297 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3298
3299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3300 &file, &database, &newname, &txnobj, &flags)) {
3301 return NULL;
3302 }
3303 if (!checkTxnObj(txnobj, &txn)) {
3304 return NULL;
3305 }
3306 CHECK_ENV_NOT_CLOSED(self);
3307 MYDB_BEGIN_ALLOW_THREADS;
3308 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3309 flags);
3310 MYDB_END_ALLOW_THREADS;
3311 RETURN_IF_ERR();
3312 RETURN_NONE();
3313}
3314
3315static PyObject*
3316DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3317{
3318 int err;
3319 u_int32_t flags=0;
3320 char *passwd = NULL;
3321 char* kwnames[] = { "passwd", "flags", NULL };
3322
3323 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3324 &passwd, &flags)) {
3325 return NULL;
3326 }
3327
3328 MYDB_BEGIN_ALLOW_THREADS;
3329 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3330 MYDB_END_ALLOW_THREADS;
3331
3332 RETURN_IF_ERR();
3333 RETURN_NONE();
3334}
3335#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003336
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003337#if (DBVER >= 40)
3338static PyObject*
3339DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3340{
3341 int err;
3342 u_int32_t flags=0;
3343 u_int32_t timeout = 0;
3344 char* kwnames[] = { "timeout", "flags", NULL };
3345
3346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3347 &timeout, &flags)) {
3348 return NULL;
3349 }
3350
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3353 MYDB_END_ALLOW_THREADS;
3354
3355 RETURN_IF_ERR();
3356 RETURN_NONE();
3357}
3358#endif /* DBVER >= 40 */
3359
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003361DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3362{
3363 int err;
3364 long shm_key = 0;
3365
3366 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3367 return NULL;
3368 CHECK_ENV_NOT_CLOSED(self);
3369
3370 err = self->db_env->set_shm_key(self->db_env, shm_key);
3371 RETURN_IF_ERR();
3372 RETURN_NONE();
3373}
3374
3375static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003376DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3377{
3378 int err, gbytes=0, bytes=0, ncache=0;
3379
3380 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3381 &gbytes, &bytes, &ncache))
3382 return NULL;
3383 CHECK_ENV_NOT_CLOSED(self);
3384
3385 MYDB_BEGIN_ALLOW_THREADS;
3386 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3387 MYDB_END_ALLOW_THREADS;
3388 RETURN_IF_ERR();
3389 RETURN_NONE();
3390}
3391
3392
3393#if (DBVER >= 32)
3394static PyObject*
3395DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3396{
3397 int err, flags=0, onoff=0;
3398
3399 if (!PyArg_ParseTuple(args, "ii:set_flags",
3400 &flags, &onoff))
3401 return NULL;
3402 CHECK_ENV_NOT_CLOSED(self);
3403
3404 MYDB_BEGIN_ALLOW_THREADS;
3405 err = self->db_env->set_flags(self->db_env, flags, onoff);
3406 MYDB_END_ALLOW_THREADS;
3407 RETURN_IF_ERR();
3408 RETURN_NONE();
3409}
3410#endif
3411
3412
3413static PyObject*
3414DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3415{
3416 int err;
3417 char *dir;
3418
3419 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3420 return NULL;
3421 CHECK_ENV_NOT_CLOSED(self);
3422
3423 MYDB_BEGIN_ALLOW_THREADS;
3424 err = self->db_env->set_data_dir(self->db_env, dir);
3425 MYDB_END_ALLOW_THREADS;
3426 RETURN_IF_ERR();
3427 RETURN_NONE();
3428}
3429
3430
3431static PyObject*
3432DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3433{
3434 int err, lg_bsize;
3435
3436 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3437 return NULL;
3438 CHECK_ENV_NOT_CLOSED(self);
3439
3440 MYDB_BEGIN_ALLOW_THREADS;
3441 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3442 MYDB_END_ALLOW_THREADS;
3443 RETURN_IF_ERR();
3444 RETURN_NONE();
3445}
3446
3447
3448static PyObject*
3449DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3450{
3451 int err;
3452 char *dir;
3453
3454 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3455 return NULL;
3456 CHECK_ENV_NOT_CLOSED(self);
3457
3458 MYDB_BEGIN_ALLOW_THREADS;
3459 err = self->db_env->set_lg_dir(self->db_env, dir);
3460 MYDB_END_ALLOW_THREADS;
3461 RETURN_IF_ERR();
3462 RETURN_NONE();
3463}
3464
3465static PyObject*
3466DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3467{
3468 int err, lg_max;
3469
3470 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3471 return NULL;
3472 CHECK_ENV_NOT_CLOSED(self);
3473
3474 MYDB_BEGIN_ALLOW_THREADS;
3475 err = self->db_env->set_lg_max(self->db_env, lg_max);
3476 MYDB_END_ALLOW_THREADS;
3477 RETURN_IF_ERR();
3478 RETURN_NONE();
3479}
3480
3481
3482static PyObject*
3483DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3484{
3485 int err, lk_detect;
3486
3487 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3488 return NULL;
3489 CHECK_ENV_NOT_CLOSED(self);
3490
3491 MYDB_BEGIN_ALLOW_THREADS;
3492 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3493 MYDB_END_ALLOW_THREADS;
3494 RETURN_IF_ERR();
3495 RETURN_NONE();
3496}
3497
3498
3499static PyObject*
3500DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3501{
3502 int err, max;
3503
3504 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3505 return NULL;
3506 CHECK_ENV_NOT_CLOSED(self);
3507
3508 MYDB_BEGIN_ALLOW_THREADS;
3509 err = self->db_env->set_lk_max(self->db_env, max);
3510 MYDB_END_ALLOW_THREADS;
3511 RETURN_IF_ERR();
3512 RETURN_NONE();
3513}
3514
3515
3516#if (DBVER >= 32)
3517
3518static PyObject*
3519DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3520{
3521 int err, max;
3522
3523 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3524 return NULL;
3525 CHECK_ENV_NOT_CLOSED(self);
3526
3527 MYDB_BEGIN_ALLOW_THREADS;
3528 err = self->db_env->set_lk_max_locks(self->db_env, max);
3529 MYDB_END_ALLOW_THREADS;
3530 RETURN_IF_ERR();
3531 RETURN_NONE();
3532}
3533
3534
3535static PyObject*
3536DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3537{
3538 int err, max;
3539
3540 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3541 return NULL;
3542 CHECK_ENV_NOT_CLOSED(self);
3543
3544 MYDB_BEGIN_ALLOW_THREADS;
3545 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3546 MYDB_END_ALLOW_THREADS;
3547 RETURN_IF_ERR();
3548 RETURN_NONE();
3549}
3550
3551
3552static PyObject*
3553DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3554{
3555 int err, max;
3556
3557 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3558 return NULL;
3559 CHECK_ENV_NOT_CLOSED(self);
3560
3561 MYDB_BEGIN_ALLOW_THREADS;
3562 err = self->db_env->set_lk_max_objects(self->db_env, max);
3563 MYDB_END_ALLOW_THREADS;
3564 RETURN_IF_ERR();
3565 RETURN_NONE();
3566}
3567
3568#endif
3569
3570
3571static PyObject*
3572DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3573{
3574 int err, mp_mmapsize;
3575
3576 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3577 return NULL;
3578 CHECK_ENV_NOT_CLOSED(self);
3579
3580 MYDB_BEGIN_ALLOW_THREADS;
3581 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3582 MYDB_END_ALLOW_THREADS;
3583 RETURN_IF_ERR();
3584 RETURN_NONE();
3585}
3586
3587
3588static PyObject*
3589DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3590{
3591 int err;
3592 char *dir;
3593
3594 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3595 return NULL;
3596 CHECK_ENV_NOT_CLOSED(self);
3597
3598 MYDB_BEGIN_ALLOW_THREADS;
3599 err = self->db_env->set_tmp_dir(self->db_env, dir);
3600 MYDB_END_ALLOW_THREADS;
3601 RETURN_IF_ERR();
3602 RETURN_NONE();
3603}
3604
3605
3606static PyObject*
3607DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3608{
3609 int flags = 0;
3610 PyObject* txnobj = NULL;
3611 DB_TXN *txn = NULL;
3612 char* kwnames[] = { "parent", "flags", NULL };
3613
3614 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3615 &txnobj, &flags))
3616 return NULL;
3617
3618 if (!checkTxnObj(txnobj, &txn))
3619 return NULL;
3620 CHECK_ENV_NOT_CLOSED(self);
3621
3622 return (PyObject*)newDBTxnObject(self, txn, flags);
3623}
3624
3625
3626static PyObject*
3627DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3628{
3629 int err, kbyte=0, min=0, flags=0;
3630
3631 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3632 return NULL;
3633 CHECK_ENV_NOT_CLOSED(self);
3634
3635 MYDB_BEGIN_ALLOW_THREADS;
3636#if (DBVER >= 40)
3637 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3638#else
3639 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3640#endif
3641 MYDB_END_ALLOW_THREADS;
3642 RETURN_IF_ERR();
3643 RETURN_NONE();
3644}
3645
3646
3647static PyObject*
3648DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3649{
3650 int err, max;
3651
3652 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3653 return NULL;
3654 CHECK_ENV_NOT_CLOSED(self);
3655
3656 MYDB_BEGIN_ALLOW_THREADS;
3657 err = self->db_env->set_tx_max(self->db_env, max);
3658 MYDB_END_ALLOW_THREADS;
3659 RETURN_IF_ERR();
3660 RETURN_NONE();
3661}
3662
3663
3664static PyObject*
3665DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3666{
3667 int err, atype, flags=0;
3668 int aborted = 0;
3669
3670 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3671 return NULL;
3672 CHECK_ENV_NOT_CLOSED(self);
3673
3674 MYDB_BEGIN_ALLOW_THREADS;
3675#if (DBVER >= 40)
3676 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3677#else
3678 err = lock_detect(self->db_env, flags, atype, &aborted);
3679#endif
3680 MYDB_END_ALLOW_THREADS;
3681 RETURN_IF_ERR();
3682 return PyInt_FromLong(aborted);
3683}
3684
3685
3686static PyObject*
3687DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3688{
3689 int flags=0;
3690 int locker, lock_mode;
3691 DBT obj;
3692 PyObject* objobj;
3693
3694 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3695 return NULL;
3696
3697
3698 if (!make_dbt(objobj, &obj))
3699 return NULL;
3700
3701 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3702}
3703
3704
3705static PyObject*
3706DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3707{
3708 int err;
3709 u_int32_t theID;
3710
3711 if (!PyArg_ParseTuple(args, ":lock_id"))
3712 return NULL;
3713
3714 CHECK_ENV_NOT_CLOSED(self);
3715 MYDB_BEGIN_ALLOW_THREADS;
3716#if (DBVER >= 40)
3717 err = self->db_env->lock_id(self->db_env, &theID);
3718#else
3719 err = lock_id(self->db_env, &theID);
3720#endif
3721 MYDB_END_ALLOW_THREADS;
3722 RETURN_IF_ERR();
3723
3724 return PyInt_FromLong((long)theID);
3725}
3726
3727
3728static PyObject*
3729DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3730{
3731 int err;
3732 DBLockObject* dblockobj;
3733
3734 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3735 return NULL;
3736
3737 CHECK_ENV_NOT_CLOSED(self);
3738 MYDB_BEGIN_ALLOW_THREADS;
3739#if (DBVER >= 40)
3740 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3741#else
3742 err = lock_put(self->db_env, &dblockobj->lock);
3743#endif
3744 MYDB_END_ALLOW_THREADS;
3745 RETURN_IF_ERR();
3746 RETURN_NONE();
3747}
3748
3749
3750static PyObject*
3751DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3752{
3753 int err;
3754 DB_LOCK_STAT* sp;
3755 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003756 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757
3758 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3759 return NULL;
3760 CHECK_ENV_NOT_CLOSED(self);
3761
3762 MYDB_BEGIN_ALLOW_THREADS;
3763#if (DBVER >= 40)
3764 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3765#else
3766#if (DBVER >= 33)
3767 err = lock_stat(self->db_env, &sp);
3768#else
3769 err = lock_stat(self->db_env, &sp, NULL);
3770#endif
3771#endif
3772 MYDB_END_ALLOW_THREADS;
3773 RETURN_IF_ERR();
3774
3775 /* Turn the stat structure into a dictionary */
3776 d = PyDict_New();
3777 if (d == NULL) {
3778 free(sp);
3779 return NULL;
3780 }
3781
3782#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3783
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003784#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003785 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003786#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787 MAKE_ENTRY(nmodes);
3788#if (DBVER >= 32)
3789 MAKE_ENTRY(maxlocks);
3790 MAKE_ENTRY(maxlockers);
3791 MAKE_ENTRY(maxobjects);
3792 MAKE_ENTRY(nlocks);
3793 MAKE_ENTRY(maxnlocks);
3794#endif
3795 MAKE_ENTRY(nlockers);
3796 MAKE_ENTRY(maxnlockers);
3797#if (DBVER >= 32)
3798 MAKE_ENTRY(nobjects);
3799 MAKE_ENTRY(maxnobjects);
3800#endif
3801 MAKE_ENTRY(nrequests);
3802 MAKE_ENTRY(nreleases);
3803 MAKE_ENTRY(nnowaits);
3804 MAKE_ENTRY(nconflicts);
3805 MAKE_ENTRY(ndeadlocks);
3806 MAKE_ENTRY(regsize);
3807 MAKE_ENTRY(region_wait);
3808 MAKE_ENTRY(region_nowait);
3809
3810#undef MAKE_ENTRY
3811 free(sp);
3812 return d;
3813}
3814
3815
3816static PyObject*
3817DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3818{
3819 int flags=0;
3820 int err;
3821 char **log_list_start, **log_list;
3822 PyObject* list;
3823 PyObject* item = NULL;
3824
3825 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3826 return NULL;
3827
3828 CHECK_ENV_NOT_CLOSED(self);
3829 MYDB_BEGIN_ALLOW_THREADS;
3830#if (DBVER >= 40)
3831 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3832#elif (DBVER == 33)
3833 err = log_archive(self->db_env, &log_list, flags);
3834#else
3835 err = log_archive(self->db_env, &log_list, flags, NULL);
3836#endif
3837 MYDB_END_ALLOW_THREADS;
3838 RETURN_IF_ERR();
3839
3840 list = PyList_New(0);
3841 if (list == NULL) {
3842 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3843 return NULL;
3844 }
3845
3846 if (log_list) {
3847 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3848 item = PyString_FromString (*log_list);
3849 if (item == NULL) {
3850 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003851 PyErr_SetString(PyExc_MemoryError,
3852 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003853 list = NULL;
3854 break;
3855 }
3856 PyList_Append(list, item);
3857 Py_DECREF(item);
3858 }
3859 free(log_list_start);
3860 }
3861 return list;
3862}
3863
3864
3865static PyObject*
3866DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3867{
3868 int err;
3869 DB_TXN_STAT* sp;
3870 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003871 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003872
3873 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3874 return NULL;
3875 CHECK_ENV_NOT_CLOSED(self);
3876
3877 MYDB_BEGIN_ALLOW_THREADS;
3878#if (DBVER >= 40)
3879 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3880#elif (DBVER == 33)
3881 err = txn_stat(self->db_env, &sp);
3882#else
3883 err = txn_stat(self->db_env, &sp, NULL);
3884#endif
3885 MYDB_END_ALLOW_THREADS;
3886 RETURN_IF_ERR();
3887
3888 /* Turn the stat structure into a dictionary */
3889 d = PyDict_New();
3890 if (d == NULL) {
3891 free(sp);
3892 return NULL;
3893 }
3894
3895#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3896
3897 MAKE_ENTRY(time_ckp);
3898 MAKE_ENTRY(last_txnid);
3899 MAKE_ENTRY(maxtxns);
3900 MAKE_ENTRY(nactive);
3901 MAKE_ENTRY(maxnactive);
3902 MAKE_ENTRY(nbegins);
3903 MAKE_ENTRY(naborts);
3904 MAKE_ENTRY(ncommits);
3905 MAKE_ENTRY(regsize);
3906 MAKE_ENTRY(region_wait);
3907 MAKE_ENTRY(region_nowait);
3908
3909#undef MAKE_ENTRY
3910 free(sp);
3911 return d;
3912}
3913
3914
3915static PyObject*
3916DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3917{
3918 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003919 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003920
3921 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3922 return NULL;
3923 CHECK_ENV_NOT_CLOSED(self);
3924
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003925 if (self->moduleFlags.getReturnsNone)
3926 ++oldValue;
3927 if (self->moduleFlags.cursorSetReturnsNone)
3928 ++oldValue;
3929 self->moduleFlags.getReturnsNone = (flags >= 1);
3930 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003931 return PyInt_FromLong(oldValue);
3932}
3933
3934
3935/* --------------------------------------------------------------------- */
3936/* DBTxn methods */
3937
3938
3939static PyObject*
3940DBTxn_commit(DBTxnObject* self, PyObject* args)
3941{
3942 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003943 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003944
3945 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3946 return NULL;
3947
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003948 if (!self->txn) {
3949 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3950 "DBTxn must not be used after txn_commit or txn_abort"));
3951 return NULL;
3952 }
3953 txn = self->txn;
3954 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003955 MYDB_BEGIN_ALLOW_THREADS;
3956#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003957 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003958#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003959 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003960#endif
3961 MYDB_END_ALLOW_THREADS;
3962 RETURN_IF_ERR();
3963 RETURN_NONE();
3964}
3965
3966static PyObject*
3967DBTxn_prepare(DBTxnObject* self, PyObject* args)
3968{
3969#if (DBVER >= 33)
3970 int err;
3971 char* gid=NULL;
3972 int gid_size=0;
3973
3974 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3975 return NULL;
3976
3977 if (gid_size != DB_XIDDATASIZE) {
3978 PyErr_SetString(PyExc_TypeError,
3979 "gid must be DB_XIDDATASIZE bytes long");
3980 return NULL;
3981 }
3982
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003983 if (!self->txn) {
3984 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3985 "DBTxn must not be used after txn_commit or txn_abort"));
3986 return NULL;
3987 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003988 MYDB_BEGIN_ALLOW_THREADS;
3989#if (DBVER >= 40)
3990 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3991#else
3992 err = txn_prepare(self->txn, (u_int8_t*)gid);
3993#endif
3994 MYDB_END_ALLOW_THREADS;
3995 RETURN_IF_ERR();
3996 RETURN_NONE();
3997#else
3998 int err;
3999
4000 if (!PyArg_ParseTuple(args, ":prepare"))
4001 return NULL;
4002
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004003 if (!self->txn) {
4004 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4005 "DBTxn must not be used after txn_commit or txn_abort"));
4006 return NULL;
4007 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004008 MYDB_BEGIN_ALLOW_THREADS;
4009 err = txn_prepare(self->txn);
4010 MYDB_END_ALLOW_THREADS;
4011 RETURN_IF_ERR();
4012 RETURN_NONE();
4013#endif
4014}
4015
4016
4017static PyObject*
4018DBTxn_abort(DBTxnObject* self, PyObject* args)
4019{
4020 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004021 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004022
4023 if (!PyArg_ParseTuple(args, ":abort"))
4024 return NULL;
4025
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004026 if (!self->txn) {
4027 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4028 "DBTxn must not be used after txn_commit or txn_abort"));
4029 return NULL;
4030 }
4031 txn = self->txn;
4032 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004033 MYDB_BEGIN_ALLOW_THREADS;
4034#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004035 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004036#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004037 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004038#endif
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045static PyObject*
4046DBTxn_id(DBTxnObject* self, PyObject* args)
4047{
4048 int id;
4049
4050 if (!PyArg_ParseTuple(args, ":id"))
4051 return NULL;
4052
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004053 if (!self->txn) {
4054 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4055 "DBTxn must not be used after txn_commit or txn_abort"));
4056 return NULL;
4057 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004058 MYDB_BEGIN_ALLOW_THREADS;
4059#if (DBVER >= 40)
4060 id = self->txn->id(self->txn);
4061#else
4062 id = txn_id(self->txn);
4063#endif
4064 MYDB_END_ALLOW_THREADS;
4065 return PyInt_FromLong(id);
4066}
4067
4068/* --------------------------------------------------------------------- */
4069/* Method definition tables and type objects */
4070
4071static PyMethodDef DB_methods[] = {
4072 {"append", (PyCFunction)DB_append, METH_VARARGS},
4073#if (DBVER >= 33)
4074 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4075#endif
4076 {"close", (PyCFunction)DB_close, METH_VARARGS},
4077#if (DBVER >= 32)
4078 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4079 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4080#endif
4081 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4082 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4083 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4084 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4085 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4086 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4087 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4088 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4089 {"join", (PyCFunction)DB_join, METH_VARARGS},
4090 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4091 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4092 {"items", (PyCFunction)DB_items, METH_VARARGS},
4093 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4094 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4095 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4096 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4097 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4098 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4099 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004100#if (DBVER >= 41)
4101 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4102#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004103 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4104 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4105 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4106 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4107 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4108 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4109 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4110 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4111 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4112#if (DBVER >= 32)
4113 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4114#endif
4115 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4116 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4117#if (DBVER >= 33)
4118 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4119#endif
4120 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4121 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4122 {"values", (PyCFunction)DB_values, METH_VARARGS},
4123 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4124 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4125 {NULL, NULL} /* sentinel */
4126};
4127
4128
4129static PyMappingMethods DB_mapping = {
4130 (inquiry)DB_length, /*mp_length*/
4131 (binaryfunc)DB_subscript, /*mp_subscript*/
4132 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4133};
4134
4135
4136static PyMethodDef DBCursor_methods[] = {
4137 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4138 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4139 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4140 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4141 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4142 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4143 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4144 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4145 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4146 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4147 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4148 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4149 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4150 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4151 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004152 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004153 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004154 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4155 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4156 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4157 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4158 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4159 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4160 {NULL, NULL} /* sentinel */
4161};
4162
4163
4164static PyMethodDef DBEnv_methods[] = {
4165 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4166 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4167 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004168#if (DBVER >= 41)
4169 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4170 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4171 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4172#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004173#if (DBVER >= 40)
4174 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4175#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004176 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004177 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4178 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4179#if (DBVER >= 32)
4180 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4181#endif
4182 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4183 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4184 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4185 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4186 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4187#if (DBVER >= 32)
4188 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4189 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4190 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4191#endif
4192 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4193 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4194 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4195 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4196 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4197 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4198 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4199 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4200 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4201 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4202 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4203 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4204 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4205 {NULL, NULL} /* sentinel */
4206};
4207
4208
4209static PyMethodDef DBTxn_methods[] = {
4210 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4211 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4212 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4213 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4214 {NULL, NULL} /* sentinel */
4215};
4216
4217
4218static PyObject*
4219DB_getattr(DBObject* self, char *name)
4220{
4221 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4222}
4223
4224
4225static PyObject*
4226DBEnv_getattr(DBEnvObject* self, char *name)
4227{
4228 if (!strcmp(name, "db_home")) {
4229 CHECK_ENV_NOT_CLOSED(self);
4230 if (self->db_env->db_home == NULL) {
4231 RETURN_NONE();
4232 }
4233 return PyString_FromString(self->db_env->db_home);
4234 }
4235
4236 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4237}
4238
4239
4240static PyObject*
4241DBCursor_getattr(DBCursorObject* self, char *name)
4242{
4243 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4244}
4245
4246static PyObject*
4247DBTxn_getattr(DBTxnObject* self, char *name)
4248{
4249 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4250}
4251
4252static PyObject*
4253DBLock_getattr(DBLockObject* self, char *name)
4254{
4255 return NULL;
4256}
4257
4258statichere PyTypeObject DB_Type = {
4259 PyObject_HEAD_INIT(NULL)
4260 0, /*ob_size*/
4261 "DB", /*tp_name*/
4262 sizeof(DBObject), /*tp_basicsize*/
4263 0, /*tp_itemsize*/
4264 /* methods */
4265 (destructor)DB_dealloc, /*tp_dealloc*/
4266 0, /*tp_print*/
4267 (getattrfunc)DB_getattr, /*tp_getattr*/
4268 0, /*tp_setattr*/
4269 0, /*tp_compare*/
4270 0, /*tp_repr*/
4271 0, /*tp_as_number*/
4272 0, /*tp_as_sequence*/
4273 &DB_mapping,/*tp_as_mapping*/
4274 0, /*tp_hash*/
4275};
4276
4277
4278statichere PyTypeObject DBCursor_Type = {
4279 PyObject_HEAD_INIT(NULL)
4280 0, /*ob_size*/
4281 "DBCursor", /*tp_name*/
4282 sizeof(DBCursorObject), /*tp_basicsize*/
4283 0, /*tp_itemsize*/
4284 /* methods */
4285 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4286 0, /*tp_print*/
4287 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4288 0, /*tp_setattr*/
4289 0, /*tp_compare*/
4290 0, /*tp_repr*/
4291 0, /*tp_as_number*/
4292 0, /*tp_as_sequence*/
4293 0, /*tp_as_mapping*/
4294 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004295#ifdef HAVE_WEAKREF
4296 0, /* tp_call */
4297 0, /* tp_str */
4298 0, /* tp_getattro */
4299 0, /* tp_setattro */
4300 0, /* tp_as_buffer */
4301 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4302 0, /* tp_doc */
4303 0, /* tp_traverse */
4304 0, /* tp_clear */
4305 0, /* tp_richcompare */
4306 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4307#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004308};
4309
4310
4311statichere PyTypeObject DBEnv_Type = {
4312 PyObject_HEAD_INIT(NULL)
4313 0, /*ob_size*/
4314 "DBEnv", /*tp_name*/
4315 sizeof(DBEnvObject), /*tp_basicsize*/
4316 0, /*tp_itemsize*/
4317 /* methods */
4318 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4319 0, /*tp_print*/
4320 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4321 0, /*tp_setattr*/
4322 0, /*tp_compare*/
4323 0, /*tp_repr*/
4324 0, /*tp_as_number*/
4325 0, /*tp_as_sequence*/
4326 0, /*tp_as_mapping*/
4327 0, /*tp_hash*/
4328};
4329
4330statichere PyTypeObject DBTxn_Type = {
4331 PyObject_HEAD_INIT(NULL)
4332 0, /*ob_size*/
4333 "DBTxn", /*tp_name*/
4334 sizeof(DBTxnObject), /*tp_basicsize*/
4335 0, /*tp_itemsize*/
4336 /* methods */
4337 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4338 0, /*tp_print*/
4339 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4340 0, /*tp_setattr*/
4341 0, /*tp_compare*/
4342 0, /*tp_repr*/
4343 0, /*tp_as_number*/
4344 0, /*tp_as_sequence*/
4345 0, /*tp_as_mapping*/
4346 0, /*tp_hash*/
4347};
4348
4349
4350statichere PyTypeObject DBLock_Type = {
4351 PyObject_HEAD_INIT(NULL)
4352 0, /*ob_size*/
4353 "DBLock", /*tp_name*/
4354 sizeof(DBLockObject), /*tp_basicsize*/
4355 0, /*tp_itemsize*/
4356 /* methods */
4357 (destructor)DBLock_dealloc, /*tp_dealloc*/
4358 0, /*tp_print*/
4359 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4360 0, /*tp_setattr*/
4361 0, /*tp_compare*/
4362 0, /*tp_repr*/
4363 0, /*tp_as_number*/
4364 0, /*tp_as_sequence*/
4365 0, /*tp_as_mapping*/
4366 0, /*tp_hash*/
4367};
4368
4369
4370/* --------------------------------------------------------------------- */
4371/* Module-level functions */
4372
4373static PyObject*
4374DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4375{
4376 PyObject* dbenvobj = NULL;
4377 int flags = 0;
4378 char* kwnames[] = { "dbEnv", "flags", NULL};
4379
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4381 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004382 return NULL;
4383 if (dbenvobj == Py_None)
4384 dbenvobj = NULL;
4385 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4386 makeTypeError("DBEnv", dbenvobj);
4387 return NULL;
4388 }
4389
4390 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4391}
4392
4393
4394static PyObject*
4395DBEnv_construct(PyObject* self, PyObject* args)
4396{
4397 int flags = 0;
4398 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4399 return (PyObject* )newDBEnvObject(flags);
4400}
4401
4402
4403static char bsddb_version_doc[] =
4404"Returns a tuple of major, minor, and patch release numbers of the\n\
4405underlying DB library.";
4406
4407static PyObject*
4408bsddb_version(PyObject* self, PyObject* args)
4409{
4410 int major, minor, patch;
4411
4412 if (!PyArg_ParseTuple(args, ":version"))
4413 return NULL;
4414 db_version(&major, &minor, &patch);
4415 return Py_BuildValue("(iii)", major, minor, patch);
4416}
4417
4418
4419/* List of functions defined in the module */
4420
4421static PyMethodDef bsddb_methods[] = {
4422 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4423 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4424 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4425 {NULL, NULL} /* sentinel */
4426};
4427
4428
4429/* --------------------------------------------------------------------- */
4430/* Module initialization */
4431
4432
4433/* Convenience routine to export an integer value.
4434 * Errors are silently ignored, for better or for worse...
4435 */
4436#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4437
Gregory P. Smith41631e82003-09-21 00:08:14 +00004438#define MODULE_NAME_MAX_LEN 11
4439static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004440
4441DL_EXPORT(void) init_bsddb(void)
4442{
4443 PyObject* m;
4444 PyObject* d;
4445 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4446 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4447 PyObject* cvsid_s = PyString_FromString( rcs_id );
4448
4449 /* Initialize the type of the new type objects here; doing it here
4450 is required for portability to Windows without requiring C++. */
4451 DB_Type.ob_type = &PyType_Type;
4452 DBCursor_Type.ob_type = &PyType_Type;
4453 DBEnv_Type.ob_type = &PyType_Type;
4454 DBTxn_Type.ob_type = &PyType_Type;
4455 DBLock_Type.ob_type = &PyType_Type;
4456
4457
Mark Hammonda69d4092003-04-22 23:13:27 +00004458#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004459 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004460 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004461#endif
4462
4463 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004464 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004465
4466 /* Add some symbolic constants to the module */
4467 d = PyModule_GetDict(m);
4468 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4469 PyDict_SetItemString(d, "cvsid", cvsid_s);
4470 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4471 Py_DECREF(pybsddb_version_s);
4472 pybsddb_version_s = NULL;
4473 Py_DECREF(cvsid_s);
4474 cvsid_s = NULL;
4475 Py_DECREF(db_version_s);
4476 db_version_s = NULL;
4477
4478 ADD_INT(d, DB_VERSION_MAJOR);
4479 ADD_INT(d, DB_VERSION_MINOR);
4480 ADD_INT(d, DB_VERSION_PATCH);
4481
4482 ADD_INT(d, DB_MAX_PAGES);
4483 ADD_INT(d, DB_MAX_RECORDS);
4484
Gregory P. Smith41631e82003-09-21 00:08:14 +00004485#if (DBVER >= 42)
4486 ADD_INT(d, DB_RPCCLIENT);
4487#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004488 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004489 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4490 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4491#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492 ADD_INT(d, DB_XA_CREATE);
4493
4494 ADD_INT(d, DB_CREATE);
4495 ADD_INT(d, DB_NOMMAP);
4496 ADD_INT(d, DB_THREAD);
4497
4498 ADD_INT(d, DB_FORCE);
4499 ADD_INT(d, DB_INIT_CDB);
4500 ADD_INT(d, DB_INIT_LOCK);
4501 ADD_INT(d, DB_INIT_LOG);
4502 ADD_INT(d, DB_INIT_MPOOL);
4503 ADD_INT(d, DB_INIT_TXN);
4504#if (DBVER >= 32)
4505 ADD_INT(d, DB_JOINENV);
4506#endif
4507
4508 ADD_INT(d, DB_RECOVER);
4509 ADD_INT(d, DB_RECOVER_FATAL);
4510 ADD_INT(d, DB_TXN_NOSYNC);
4511 ADD_INT(d, DB_USE_ENVIRON);
4512 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4513
4514 ADD_INT(d, DB_LOCKDOWN);
4515 ADD_INT(d, DB_PRIVATE);
4516 ADD_INT(d, DB_SYSTEM_MEM);
4517
4518 ADD_INT(d, DB_TXN_SYNC);
4519 ADD_INT(d, DB_TXN_NOWAIT);
4520
4521 ADD_INT(d, DB_EXCL);
4522 ADD_INT(d, DB_FCNTL_LOCKING);
4523 ADD_INT(d, DB_ODDFILESIZE);
4524 ADD_INT(d, DB_RDWRMASTER);
4525 ADD_INT(d, DB_RDONLY);
4526 ADD_INT(d, DB_TRUNCATE);
4527#if (DBVER >= 32)
4528 ADD_INT(d, DB_EXTENT);
4529 ADD_INT(d, DB_CDB_ALLDB);
4530 ADD_INT(d, DB_VERIFY);
4531#endif
4532 ADD_INT(d, DB_UPGRADE);
4533
4534 ADD_INT(d, DB_AGGRESSIVE);
4535 ADD_INT(d, DB_NOORDERCHK);
4536 ADD_INT(d, DB_ORDERCHKONLY);
4537 ADD_INT(d, DB_PR_PAGE);
4538#if ! (DBVER >= 33)
4539 ADD_INT(d, DB_VRFY_FLAGMASK);
4540 ADD_INT(d, DB_PR_HEADERS);
4541#endif
4542 ADD_INT(d, DB_PR_RECOVERYTEST);
4543 ADD_INT(d, DB_SALVAGE);
4544
4545 ADD_INT(d, DB_LOCK_NORUN);
4546 ADD_INT(d, DB_LOCK_DEFAULT);
4547 ADD_INT(d, DB_LOCK_OLDEST);
4548 ADD_INT(d, DB_LOCK_RANDOM);
4549 ADD_INT(d, DB_LOCK_YOUNGEST);
4550#if (DBVER >= 33)
4551 ADD_INT(d, DB_LOCK_MAXLOCKS);
4552 ADD_INT(d, DB_LOCK_MINLOCKS);
4553 ADD_INT(d, DB_LOCK_MINWRITE);
4554#endif
4555
4556
4557#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004558 /* docs say to use zero instead */
4559 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004560#else
4561 ADD_INT(d, DB_LOCK_CONFLICT);
4562#endif
4563
4564 ADD_INT(d, DB_LOCK_DUMP);
4565 ADD_INT(d, DB_LOCK_GET);
4566 ADD_INT(d, DB_LOCK_INHERIT);
4567 ADD_INT(d, DB_LOCK_PUT);
4568 ADD_INT(d, DB_LOCK_PUT_ALL);
4569 ADD_INT(d, DB_LOCK_PUT_OBJ);
4570
4571 ADD_INT(d, DB_LOCK_NG);
4572 ADD_INT(d, DB_LOCK_READ);
4573 ADD_INT(d, DB_LOCK_WRITE);
4574 ADD_INT(d, DB_LOCK_NOWAIT);
4575#if (DBVER >= 32)
4576 ADD_INT(d, DB_LOCK_WAIT);
4577#endif
4578 ADD_INT(d, DB_LOCK_IWRITE);
4579 ADD_INT(d, DB_LOCK_IREAD);
4580 ADD_INT(d, DB_LOCK_IWR);
4581#if (DBVER >= 33)
4582 ADD_INT(d, DB_LOCK_DIRTY);
4583 ADD_INT(d, DB_LOCK_WWRITE);
4584#endif
4585
4586 ADD_INT(d, DB_LOCK_RECORD);
4587 ADD_INT(d, DB_LOCK_UPGRADE);
4588#if (DBVER >= 32)
4589 ADD_INT(d, DB_LOCK_SWITCH);
4590#endif
4591#if (DBVER >= 33)
4592 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4593#endif
4594
4595 ADD_INT(d, DB_LOCK_NOWAIT);
4596 ADD_INT(d, DB_LOCK_RECORD);
4597 ADD_INT(d, DB_LOCK_UPGRADE);
4598
4599#if (DBVER >= 33)
4600 ADD_INT(d, DB_LSTAT_ABORTED);
4601 ADD_INT(d, DB_LSTAT_ERR);
4602 ADD_INT(d, DB_LSTAT_FREE);
4603 ADD_INT(d, DB_LSTAT_HELD);
4604#if (DBVER == 33)
4605 ADD_INT(d, DB_LSTAT_NOGRANT);
4606#endif
4607 ADD_INT(d, DB_LSTAT_PENDING);
4608 ADD_INT(d, DB_LSTAT_WAITING);
4609#endif
4610
4611 ADD_INT(d, DB_ARCH_ABS);
4612 ADD_INT(d, DB_ARCH_DATA);
4613 ADD_INT(d, DB_ARCH_LOG);
4614
4615 ADD_INT(d, DB_BTREE);
4616 ADD_INT(d, DB_HASH);
4617 ADD_INT(d, DB_RECNO);
4618 ADD_INT(d, DB_QUEUE);
4619 ADD_INT(d, DB_UNKNOWN);
4620
4621 ADD_INT(d, DB_DUP);
4622 ADD_INT(d, DB_DUPSORT);
4623 ADD_INT(d, DB_RECNUM);
4624 ADD_INT(d, DB_RENUMBER);
4625 ADD_INT(d, DB_REVSPLITOFF);
4626 ADD_INT(d, DB_SNAPSHOT);
4627
4628 ADD_INT(d, DB_JOIN_NOSORT);
4629
4630 ADD_INT(d, DB_AFTER);
4631 ADD_INT(d, DB_APPEND);
4632 ADD_INT(d, DB_BEFORE);
4633 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004634#if (DBVER >= 41)
4635 _addIntToDict(d, "DB_CHECKPOINT", 0);
4636#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004637 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004638 ADD_INT(d, DB_CURLSN);
4639#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004640#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004641 ADD_INT(d, DB_COMMIT);
4642#endif
4643 ADD_INT(d, DB_CONSUME);
4644#if (DBVER >= 32)
4645 ADD_INT(d, DB_CONSUME_WAIT);
4646#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004647 ADD_INT(d, DB_CURRENT);
4648#if (DBVER >= 33)
4649 ADD_INT(d, DB_FAST_STAT);
4650#endif
4651 ADD_INT(d, DB_FIRST);
4652 ADD_INT(d, DB_FLUSH);
4653 ADD_INT(d, DB_GET_BOTH);
4654 ADD_INT(d, DB_GET_RECNO);
4655 ADD_INT(d, DB_JOIN_ITEM);
4656 ADD_INT(d, DB_KEYFIRST);
4657 ADD_INT(d, DB_KEYLAST);
4658 ADD_INT(d, DB_LAST);
4659 ADD_INT(d, DB_NEXT);
4660 ADD_INT(d, DB_NEXT_DUP);
4661 ADD_INT(d, DB_NEXT_NODUP);
4662 ADD_INT(d, DB_NODUPDATA);
4663 ADD_INT(d, DB_NOOVERWRITE);
4664 ADD_INT(d, DB_NOSYNC);
4665 ADD_INT(d, DB_POSITION);
4666 ADD_INT(d, DB_PREV);
4667 ADD_INT(d, DB_PREV_NODUP);
4668 ADD_INT(d, DB_RECORDCOUNT);
4669 ADD_INT(d, DB_SET);
4670 ADD_INT(d, DB_SET_RANGE);
4671 ADD_INT(d, DB_SET_RECNO);
4672 ADD_INT(d, DB_WRITECURSOR);
4673
4674 ADD_INT(d, DB_OPFLAGS_MASK);
4675 ADD_INT(d, DB_RMW);
4676#if (DBVER >= 33)
4677 ADD_INT(d, DB_DIRTY_READ);
4678 ADD_INT(d, DB_MULTIPLE);
4679 ADD_INT(d, DB_MULTIPLE_KEY);
4680#endif
4681
4682#if (DBVER >= 33)
4683 ADD_INT(d, DB_DONOTINDEX);
4684#endif
4685
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004686#if (DBVER >= 41)
4687 _addIntToDict(d, "DB_INCOMPLETE", 0);
4688#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004689 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004690#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691 ADD_INT(d, DB_KEYEMPTY);
4692 ADD_INT(d, DB_KEYEXIST);
4693 ADD_INT(d, DB_LOCK_DEADLOCK);
4694 ADD_INT(d, DB_LOCK_NOTGRANTED);
4695 ADD_INT(d, DB_NOSERVER);
4696 ADD_INT(d, DB_NOSERVER_HOME);
4697 ADD_INT(d, DB_NOSERVER_ID);
4698 ADD_INT(d, DB_NOTFOUND);
4699 ADD_INT(d, DB_OLD_VERSION);
4700 ADD_INT(d, DB_RUNRECOVERY);
4701 ADD_INT(d, DB_VERIFY_BAD);
4702#if (DBVER >= 33)
4703 ADD_INT(d, DB_PAGE_NOTFOUND);
4704 ADD_INT(d, DB_SECONDARY_BAD);
4705#endif
4706#if (DBVER >= 40)
4707 ADD_INT(d, DB_STAT_CLEAR);
4708 ADD_INT(d, DB_REGION_INIT);
4709 ADD_INT(d, DB_NOLOCKING);
4710 ADD_INT(d, DB_YIELDCPU);
4711 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4712 ADD_INT(d, DB_NOPANIC);
4713#endif
4714
Gregory P. Smith41631e82003-09-21 00:08:14 +00004715#if (DBVER >= 42)
4716 ADD_INT(d, DB_TIME_NOTGRANTED);
4717 ADD_INT(d, DB_TXN_NOT_DURABLE);
4718 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4719 ADD_INT(d, DB_LOG_AUTOREMOVE);
4720 ADD_INT(d, DB_DIRECT_LOG);
4721 ADD_INT(d, DB_DIRECT_DB);
4722 ADD_INT(d, DB_INIT_REP);
4723 ADD_INT(d, DB_ENCRYPT);
4724 ADD_INT(d, DB_CHKSUM);
4725#endif
4726
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004727#if (DBVER >= 41)
4728 ADD_INT(d, DB_ENCRYPT_AES);
4729 ADD_INT(d, DB_AUTO_COMMIT);
4730#else
4731 /* allow berkeleydb 4.1 aware apps to run on older versions */
4732 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4733#endif
4734
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004735 ADD_INT(d, EINVAL);
4736 ADD_INT(d, EACCES);
4737 ADD_INT(d, ENOSPC);
4738 ADD_INT(d, ENOMEM);
4739 ADD_INT(d, EAGAIN);
4740 ADD_INT(d, EBUSY);
4741 ADD_INT(d, EEXIST);
4742 ADD_INT(d, ENOENT);
4743 ADD_INT(d, EPERM);
4744
Barry Warsaw1baa9822003-03-31 19:51:29 +00004745#if (DBVER >= 40)
4746 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4747 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4748#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004749
4750 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004751 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004752 PyDict_SetItemString(d, "DBError", DBError);
4753
4754 /* Some magic to make DBNotFoundError derive from both DBError and
4755 KeyError, since the API only supports using one base class. */
4756 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4757 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4758 Py_file_input, d, d);
4759 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4760 PyDict_DelItemString(d, "KeyError");
4761
4762
4763 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004764#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004765 PyDict_SetItemString(d, #name, name)
4766
4767#if !INCOMPLETE_IS_WARNING
4768 MAKE_EX(DBIncompleteError);
4769#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00004770 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004771 MAKE_EX(DBKeyEmptyError);
4772 MAKE_EX(DBKeyExistError);
4773 MAKE_EX(DBLockDeadlockError);
4774 MAKE_EX(DBLockNotGrantedError);
4775 MAKE_EX(DBOldVersionError);
4776 MAKE_EX(DBRunRecoveryError);
4777 MAKE_EX(DBVerifyBadError);
4778 MAKE_EX(DBNoServerError);
4779 MAKE_EX(DBNoServerHomeError);
4780 MAKE_EX(DBNoServerIDError);
4781#if (DBVER >= 33)
4782 MAKE_EX(DBPageNotFoundError);
4783 MAKE_EX(DBSecondaryBadError);
4784#endif
4785
4786 MAKE_EX(DBInvalidArgError);
4787 MAKE_EX(DBAccessError);
4788 MAKE_EX(DBNoSpaceError);
4789 MAKE_EX(DBNoMemoryError);
4790 MAKE_EX(DBAgainError);
4791 MAKE_EX(DBBusyError);
4792 MAKE_EX(DBFileExistsError);
4793 MAKE_EX(DBNoSuchFileError);
4794 MAKE_EX(DBPermissionsError);
4795
4796#undef MAKE_EX
4797
4798 /* Check for errors */
4799 if (PyErr_Occurred()) {
4800 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004801 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004802 }
4803}
Gregory P. Smith41631e82003-09-21 00:08:14 +00004804
4805/* allow this module to be named _pybsddb so that it can be installed
4806 * and imported on top of python >= 2.3 that includes its own older
4807 * copy of the library named _bsddb without importing the old version. */
4808DL_EXPORT(void) init_pybsddb(void)
4809{
4810 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
4811 init_bsddb();
4812}