blob: 3ea2c5f59fed24730ec1874da7f81a02d065b1a0 [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)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000300 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301
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,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000333 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000334 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
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000343 Caller MUST 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;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001301 if (!checkTxnObj(txnobj, &txn)) {
1302 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001303 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001304 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001306 if (-1 == _DB_delete(self, txn, &key, 0)) {
1307 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001308 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001309 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310
1311 FREE_DBT(key);
1312 RETURN_NONE();
1313}
1314
1315
1316static PyObject*
1317DB_fd(DBObject* self, PyObject* args)
1318{
1319 int err, the_fd;
1320
1321 if (!PyArg_ParseTuple(args,":fd"))
1322 return NULL;
1323 CHECK_DB_NOT_CLOSED(self);
1324
1325 MYDB_BEGIN_ALLOW_THREADS;
1326 err = self->db->fd(self->db, &the_fd);
1327 MYDB_END_ALLOW_THREADS;
1328 RETURN_IF_ERR();
1329 return PyInt_FromLong(the_fd);
1330}
1331
1332
1333static PyObject*
1334DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1335{
1336 int err, flags=0;
1337 PyObject* txnobj = NULL;
1338 PyObject* keyobj;
1339 PyObject* dfltobj = NULL;
1340 PyObject* retval = NULL;
1341 int dlen = -1;
1342 int doff = -1;
1343 DBT key, data;
1344 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001345 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001346
1347 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001348 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1349 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001350 return NULL;
1351
1352 CHECK_DB_NOT_CLOSED(self);
1353 if (!make_key_dbt(self, keyobj, &key, &flags))
1354 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001355 if (!checkTxnObj(txnobj, &txn)) {
1356 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001357 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001358 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001359
1360 CLEAR_DBT(data);
1361 if (CHECK_DBFLAG(self, DB_THREAD)) {
1362 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1363 data.flags = DB_DBT_MALLOC;
1364 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001365 if (!add_partial_dbt(&data, dlen, doff)) {
1366 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001367 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001368 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369
1370 MYDB_BEGIN_ALLOW_THREADS;
1371 err = self->db->get(self->db, txn, &key, &data, flags);
1372 MYDB_END_ALLOW_THREADS;
1373
1374 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1375 err = 0;
1376 Py_INCREF(dfltobj);
1377 retval = dfltobj;
1378 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001379 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001380 err = 0;
1381 Py_INCREF(Py_None);
1382 retval = Py_None;
1383 }
1384 else if (!err) {
1385 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001386 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1387 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001388 else /* return just the data */
1389 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001390 FREE_DBT(data);
1391 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001392 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393
1394 RETURN_IF_ERR();
1395 return retval;
1396}
1397
1398
1399/* Return size of entry */
1400static PyObject*
1401DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1402{
1403 int err, flags=0;
1404 PyObject* txnobj = NULL;
1405 PyObject* keyobj;
1406 PyObject* retval = NULL;
1407 DBT key, data;
1408 DB_TXN *txn = NULL;
1409 char* kwnames[] = { "key", "txn", NULL };
1410
1411 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1412 &keyobj, &txnobj))
1413 return NULL;
1414 CHECK_DB_NOT_CLOSED(self);
1415 if (!make_key_dbt(self, keyobj, &key, &flags))
1416 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001417 if (!checkTxnObj(txnobj, &txn)) {
1418 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001420 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421 CLEAR_DBT(data);
1422
1423 /* We don't allocate any memory, forcing a ENOMEM error and thus
1424 getting the record size. */
1425 data.flags = DB_DBT_USERMEM;
1426 data.ulen = 0;
1427 MYDB_BEGIN_ALLOW_THREADS;
1428 err = self->db->get(self->db, txn, &key, &data, flags);
1429 MYDB_END_ALLOW_THREADS;
1430 if (err == ENOMEM) {
1431 retval = PyInt_FromLong((long)data.size);
1432 err = 0;
1433 }
1434
1435 FREE_DBT(key);
1436 FREE_DBT(data);
1437 RETURN_IF_ERR();
1438 return retval;
1439}
1440
1441
1442static PyObject*
1443DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1444{
1445 int err, flags=0;
1446 PyObject* txnobj = NULL;
1447 PyObject* keyobj;
1448 PyObject* dataobj;
1449 PyObject* retval = NULL;
1450 DBT key, data;
1451 DB_TXN *txn = NULL;
1452 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1453
1454
1455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1456 &keyobj, &dataobj, &txnobj, &flags))
1457 return NULL;
1458
1459 CHECK_DB_NOT_CLOSED(self);
1460 if (!make_key_dbt(self, keyobj, &key, NULL))
1461 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001462 if ( !make_dbt(dataobj, &data) ||
1463 !checkTxnObj(txnobj, &txn) )
1464 {
1465 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001467 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001468
1469 flags |= DB_GET_BOTH;
1470
1471 if (CHECK_DBFLAG(self, DB_THREAD)) {
1472 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1473 data.flags = DB_DBT_MALLOC;
1474 /* TODO: Is this flag needed? We're passing a data object that should
1475 match what's in the DB, so there should be no need to malloc.
1476 We run the risk of freeing something twice! Check this. */
1477 }
1478
1479 MYDB_BEGIN_ALLOW_THREADS;
1480 err = self->db->get(self->db, txn, &key, &data, flags);
1481 MYDB_END_ALLOW_THREADS;
1482
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001483 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 err = 0;
1485 Py_INCREF(Py_None);
1486 retval = Py_None;
1487 }
1488 else if (!err) {
1489 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1490 FREE_DBT(data); /* Only if retrieval was successful */
1491 }
1492
1493 FREE_DBT(key);
1494 RETURN_IF_ERR();
1495 return retval;
1496}
1497
1498
1499static PyObject*
1500DB_get_byteswapped(DBObject* self, PyObject* args)
1501{
1502#if (DBVER >= 33)
1503 int err = 0;
1504#endif
1505 int retval = -1;
1506
1507 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1508 return NULL;
1509 CHECK_DB_NOT_CLOSED(self);
1510
1511#if (DBVER >= 33)
1512 MYDB_BEGIN_ALLOW_THREADS;
1513 err = self->db->get_byteswapped(self->db, &retval);
1514 MYDB_END_ALLOW_THREADS;
1515 RETURN_IF_ERR();
1516#else
1517 MYDB_BEGIN_ALLOW_THREADS;
1518 retval = self->db->get_byteswapped(self->db);
1519 MYDB_END_ALLOW_THREADS;
1520#endif
1521 return PyInt_FromLong(retval);
1522}
1523
1524
1525static PyObject*
1526DB_get_type(DBObject* self, PyObject* args)
1527{
1528 int type;
1529
1530 if (!PyArg_ParseTuple(args,":get_type"))
1531 return NULL;
1532 CHECK_DB_NOT_CLOSED(self);
1533
1534 MYDB_BEGIN_ALLOW_THREADS;
1535 type = _DB_get_type(self);
1536 MYDB_END_ALLOW_THREADS;
1537 if (type == -1)
1538 return NULL;
1539 return PyInt_FromLong(type);
1540}
1541
1542
1543static PyObject*
1544DB_join(DBObject* self, PyObject* args)
1545{
1546 int err, flags=0;
1547 int length, x;
1548 PyObject* cursorsObj;
1549 DBC** cursors;
1550 DBC* dbc;
1551
1552
1553 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1554 return NULL;
1555
1556 CHECK_DB_NOT_CLOSED(self);
1557
1558 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001559 PyErr_SetString(PyExc_TypeError,
1560 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001561 return NULL;
1562 }
1563
1564 length = PyObject_Length(cursorsObj);
1565 cursors = malloc((length+1) * sizeof(DBC*));
1566 cursors[length] = NULL;
1567 for (x=0; x<length; x++) {
1568 PyObject* item = PySequence_GetItem(cursorsObj, x);
1569 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001570 PyErr_SetString(PyExc_TypeError,
1571 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001572 free(cursors);
1573 return NULL;
1574 }
1575 cursors[x] = ((DBCursorObject*)item)->dbc;
1576 }
1577
1578 MYDB_BEGIN_ALLOW_THREADS;
1579 err = self->db->join(self->db, cursors, &dbc, flags);
1580 MYDB_END_ALLOW_THREADS;
1581 free(cursors);
1582 RETURN_IF_ERR();
1583
Gregory P. Smith7441e652003-11-03 21:35:31 +00001584 /* FIXME: this is a buggy interface. The returned cursor
1585 contains internal references to the passed in cursors
1586 but does not hold python references to them or prevent
1587 them from being closed prematurely. This can cause
1588 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589 return (PyObject*) newDBCursorObject(dbc, self);
1590}
1591
1592
1593static PyObject*
1594DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1595{
1596 int err, flags=0;
1597 PyObject* txnobj = NULL;
1598 PyObject* keyobj;
1599 DBT key;
1600 DB_TXN *txn = NULL;
1601 DB_KEY_RANGE range;
1602 char* kwnames[] = { "key", "txn", "flags", NULL };
1603
1604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1605 &keyobj, &txnobj, &flags))
1606 return NULL;
1607 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001608 if (!make_dbt(keyobj, &key))
1609 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001610 return NULL;
1611 if (!checkTxnObj(txnobj, &txn))
1612 return NULL;
1613
1614 MYDB_BEGIN_ALLOW_THREADS;
1615 err = self->db->key_range(self->db, txn, &key, &range, flags);
1616 MYDB_END_ALLOW_THREADS;
1617
1618 RETURN_IF_ERR();
1619 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1620}
1621
1622
1623static PyObject*
1624DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1625{
1626 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1627 char* filename = NULL;
1628 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001629#if (DBVER >= 41)
1630 PyObject *txnobj = NULL;
1631 DB_TXN *txn = NULL;
1632 /* with dbname */
1633 char* kwnames[] = {
1634 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1635 /* without dbname */
1636 char* kwnames_basic[] = {
1637 "filename", "dbtype", "flags", "mode", "txn", NULL};
1638#else
1639 /* with dbname */
1640 char* kwnames[] = {
1641 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1642 /* without dbname */
1643 char* kwnames_basic[] = {
1644 "filename", "dbtype", "flags", "mode", NULL};
1645#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001646
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001647#if (DBVER >= 41)
1648 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1649 &filename, &dbname, &type, &flags, &mode,
1650 &txnobj))
1651#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001653 &filename, &dbname, &type, &flags,
1654 &mode))
1655#endif
1656 {
1657 PyErr_Clear();
1658 type = DB_UNKNOWN; flags = 0; mode = 0660;
1659 filename = NULL; dbname = NULL;
1660#if (DBVER >= 41)
1661 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1662 kwnames_basic,
1663 &filename, &type, &flags, &mode,
1664 &txnobj))
1665 return NULL;
1666#else
1667 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1668 kwnames_basic,
1669 &filename, &type, &flags, &mode))
1670 return NULL;
1671#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001672 }
1673
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001674#if (DBVER >= 41)
1675 if (!checkTxnObj(txnobj, &txn)) return NULL;
1676#endif
1677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 if (NULL == self->db) {
1679 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1680 "Cannot call open() twice for DB object"));
1681 return NULL;
1682 }
1683
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001684#if 0 && (DBVER >= 41)
1685 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1686 && (self->myenvobj->flags & DB_INIT_TXN))
1687 {
1688 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1689 * explicitly passed) but we are in a transaction ready environment:
1690 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1691 * to work on BerkeleyDB 4.1 without needing to modify their
1692 * DBEnv or DB open calls.
1693 * TODO make this behaviour of the library configurable.
1694 */
1695 flags |= DB_AUTO_COMMIT;
1696 }
1697#endif
1698
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001699 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001700#if (DBVER >= 41)
1701 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1702#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001703 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001704#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001705 MYDB_END_ALLOW_THREADS;
1706 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001707 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001708 self->db = NULL;
1709 return NULL;
1710 }
1711
1712 self->flags = flags;
1713 RETURN_NONE();
1714}
1715
1716
1717static PyObject*
1718DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1719{
1720 int flags=0;
1721 PyObject* txnobj = NULL;
1722 int dlen = -1;
1723 int doff = -1;
1724 PyObject* keyobj, *dataobj, *retval;
1725 DBT key, data;
1726 DB_TXN *txn = NULL;
1727 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1728
1729 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1730 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1731 return NULL;
1732
1733 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001734 if (!make_key_dbt(self, keyobj, &key, NULL))
1735 return NULL;
1736 if ( !make_dbt(dataobj, &data) ||
1737 !add_partial_dbt(&data, dlen, doff) ||
1738 !checkTxnObj(txnobj, &txn) )
1739 {
1740 FREE_DBT(key);
1741 return NULL;
1742 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001743
1744 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1745 FREE_DBT(key);
1746 return NULL;
1747 }
1748
1749 if (flags & DB_APPEND)
1750 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1751 else {
1752 retval = Py_None;
1753 Py_INCREF(retval);
1754 }
1755 FREE_DBT(key);
1756 return retval;
1757}
1758
1759
1760
1761static PyObject*
1762DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1763{
1764 char* filename;
1765 char* database = NULL;
1766 int err, flags=0;
1767 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1768
1769 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1770 &filename, &database, &flags))
1771 return NULL;
1772 CHECK_DB_NOT_CLOSED(self);
1773
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001774 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001775 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001776 RETURN_IF_ERR();
1777 RETURN_NONE();
1778}
1779
1780
1781
1782static PyObject*
1783DB_rename(DBObject* self, PyObject* args)
1784{
1785 char* filename;
1786 char* database;
1787 char* newname;
1788 int err, flags=0;
1789
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001790 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1791 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001792 return NULL;
1793 CHECK_DB_NOT_CLOSED(self);
1794
1795 MYDB_BEGIN_ALLOW_THREADS;
1796 err = self->db->rename(self->db, filename, database, newname, flags);
1797 MYDB_END_ALLOW_THREADS;
1798 RETURN_IF_ERR();
1799 RETURN_NONE();
1800}
1801
1802
1803static PyObject*
1804DB_set_bt_minkey(DBObject* self, PyObject* args)
1805{
1806 int err, minkey;
1807
1808 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1809 return NULL;
1810 CHECK_DB_NOT_CLOSED(self);
1811
1812 MYDB_BEGIN_ALLOW_THREADS;
1813 err = self->db->set_bt_minkey(self->db, minkey);
1814 MYDB_END_ALLOW_THREADS;
1815 RETURN_IF_ERR();
1816 RETURN_NONE();
1817}
1818
1819
1820static PyObject*
1821DB_set_cachesize(DBObject* self, PyObject* args)
1822{
1823 int err;
1824 int gbytes = 0, bytes = 0, ncache = 0;
1825
1826 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1827 &gbytes,&bytes,&ncache))
1828 return NULL;
1829 CHECK_DB_NOT_CLOSED(self);
1830
1831 MYDB_BEGIN_ALLOW_THREADS;
1832 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1833 MYDB_END_ALLOW_THREADS;
1834 RETURN_IF_ERR();
1835 RETURN_NONE();
1836}
1837
1838
1839static PyObject*
1840DB_set_flags(DBObject* self, PyObject* args)
1841{
1842 int err, flags;
1843
1844 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1845 return NULL;
1846 CHECK_DB_NOT_CLOSED(self);
1847
1848 MYDB_BEGIN_ALLOW_THREADS;
1849 err = self->db->set_flags(self->db, flags);
1850 MYDB_END_ALLOW_THREADS;
1851 RETURN_IF_ERR();
1852
1853 self->setflags |= flags;
1854 RETURN_NONE();
1855}
1856
1857
1858static PyObject*
1859DB_set_h_ffactor(DBObject* self, PyObject* args)
1860{
1861 int err, ffactor;
1862
1863 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1864 return NULL;
1865 CHECK_DB_NOT_CLOSED(self);
1866
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->set_h_ffactor(self->db, ffactor);
1869 MYDB_END_ALLOW_THREADS;
1870 RETURN_IF_ERR();
1871 RETURN_NONE();
1872}
1873
1874
1875static PyObject*
1876DB_set_h_nelem(DBObject* self, PyObject* args)
1877{
1878 int err, nelem;
1879
1880 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1881 return NULL;
1882 CHECK_DB_NOT_CLOSED(self);
1883
1884 MYDB_BEGIN_ALLOW_THREADS;
1885 err = self->db->set_h_nelem(self->db, nelem);
1886 MYDB_END_ALLOW_THREADS;
1887 RETURN_IF_ERR();
1888 RETURN_NONE();
1889}
1890
1891
1892static PyObject*
1893DB_set_lorder(DBObject* self, PyObject* args)
1894{
1895 int err, lorder;
1896
1897 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1898 return NULL;
1899 CHECK_DB_NOT_CLOSED(self);
1900
1901 MYDB_BEGIN_ALLOW_THREADS;
1902 err = self->db->set_lorder(self->db, lorder);
1903 MYDB_END_ALLOW_THREADS;
1904 RETURN_IF_ERR();
1905 RETURN_NONE();
1906}
1907
1908
1909static PyObject*
1910DB_set_pagesize(DBObject* self, PyObject* args)
1911{
1912 int err, pagesize;
1913
1914 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1915 return NULL;
1916 CHECK_DB_NOT_CLOSED(self);
1917
1918 MYDB_BEGIN_ALLOW_THREADS;
1919 err = self->db->set_pagesize(self->db, pagesize);
1920 MYDB_END_ALLOW_THREADS;
1921 RETURN_IF_ERR();
1922 RETURN_NONE();
1923}
1924
1925
1926static PyObject*
1927DB_set_re_delim(DBObject* self, PyObject* args)
1928{
1929 int err;
1930 char delim;
1931
1932 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1933 PyErr_Clear();
1934 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1935 return NULL;
1936 }
1937
1938 CHECK_DB_NOT_CLOSED(self);
1939
1940 MYDB_BEGIN_ALLOW_THREADS;
1941 err = self->db->set_re_delim(self->db, delim);
1942 MYDB_END_ALLOW_THREADS;
1943 RETURN_IF_ERR();
1944 RETURN_NONE();
1945}
1946
1947static PyObject*
1948DB_set_re_len(DBObject* self, PyObject* args)
1949{
1950 int err, len;
1951
1952 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1953 return NULL;
1954 CHECK_DB_NOT_CLOSED(self);
1955
1956 MYDB_BEGIN_ALLOW_THREADS;
1957 err = self->db->set_re_len(self->db, len);
1958 MYDB_END_ALLOW_THREADS;
1959 RETURN_IF_ERR();
1960 RETURN_NONE();
1961}
1962
1963
1964static PyObject*
1965DB_set_re_pad(DBObject* self, PyObject* args)
1966{
1967 int err;
1968 char pad;
1969
1970 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1971 PyErr_Clear();
1972 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1973 return NULL;
1974 }
1975 CHECK_DB_NOT_CLOSED(self);
1976
1977 MYDB_BEGIN_ALLOW_THREADS;
1978 err = self->db->set_re_pad(self->db, pad);
1979 MYDB_END_ALLOW_THREADS;
1980 RETURN_IF_ERR();
1981 RETURN_NONE();
1982}
1983
1984
1985static PyObject*
1986DB_set_re_source(DBObject* self, PyObject* args)
1987{
1988 int err;
1989 char *re_source;
1990
1991 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1992 return NULL;
1993 CHECK_DB_NOT_CLOSED(self);
1994
1995 MYDB_BEGIN_ALLOW_THREADS;
1996 err = self->db->set_re_source(self->db, re_source);
1997 MYDB_END_ALLOW_THREADS;
1998 RETURN_IF_ERR();
1999 RETURN_NONE();
2000}
2001
2002
2003#if (DBVER >= 32)
2004static PyObject*
2005DB_set_q_extentsize(DBObject* self, PyObject* args)
2006{
2007 int err;
2008 int extentsize;
2009
2010 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2011 return NULL;
2012 CHECK_DB_NOT_CLOSED(self);
2013
2014 MYDB_BEGIN_ALLOW_THREADS;
2015 err = self->db->set_q_extentsize(self->db, extentsize);
2016 MYDB_END_ALLOW_THREADS;
2017 RETURN_IF_ERR();
2018 RETURN_NONE();
2019}
2020#endif
2021
2022static PyObject*
2023DB_stat(DBObject* self, PyObject* args)
2024{
2025 int err, flags = 0, type;
2026 void* sp;
2027 PyObject* d;
2028
2029
2030 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2031 return NULL;
2032 CHECK_DB_NOT_CLOSED(self);
2033
2034 MYDB_BEGIN_ALLOW_THREADS;
2035#if (DBVER >= 33)
2036 err = self->db->stat(self->db, &sp, flags);
2037#else
2038 err = self->db->stat(self->db, &sp, NULL, flags);
2039#endif
2040 MYDB_END_ALLOW_THREADS;
2041 RETURN_IF_ERR();
2042
2043 self->haveStat = 1;
2044
2045 /* Turn the stat structure into a dictionary */
2046 type = _DB_get_type(self);
2047 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2048 free(sp);
2049 return NULL;
2050 }
2051
2052#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2053#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2054#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2055
2056 switch (type) {
2057 case DB_HASH:
2058 MAKE_HASH_ENTRY(magic);
2059 MAKE_HASH_ENTRY(version);
2060 MAKE_HASH_ENTRY(nkeys);
2061 MAKE_HASH_ENTRY(ndata);
2062 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002063#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002064 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002065#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002066 MAKE_HASH_ENTRY(ffactor);
2067 MAKE_HASH_ENTRY(buckets);
2068 MAKE_HASH_ENTRY(free);
2069 MAKE_HASH_ENTRY(bfree);
2070 MAKE_HASH_ENTRY(bigpages);
2071 MAKE_HASH_ENTRY(big_bfree);
2072 MAKE_HASH_ENTRY(overflows);
2073 MAKE_HASH_ENTRY(ovfl_free);
2074 MAKE_HASH_ENTRY(dup);
2075 MAKE_HASH_ENTRY(dup_free);
2076 break;
2077
2078 case DB_BTREE:
2079 case DB_RECNO:
2080 MAKE_BT_ENTRY(magic);
2081 MAKE_BT_ENTRY(version);
2082 MAKE_BT_ENTRY(nkeys);
2083 MAKE_BT_ENTRY(ndata);
2084 MAKE_BT_ENTRY(pagesize);
2085 MAKE_BT_ENTRY(minkey);
2086 MAKE_BT_ENTRY(re_len);
2087 MAKE_BT_ENTRY(re_pad);
2088 MAKE_BT_ENTRY(levels);
2089 MAKE_BT_ENTRY(int_pg);
2090 MAKE_BT_ENTRY(leaf_pg);
2091 MAKE_BT_ENTRY(dup_pg);
2092 MAKE_BT_ENTRY(over_pg);
2093 MAKE_BT_ENTRY(free);
2094 MAKE_BT_ENTRY(int_pgfree);
2095 MAKE_BT_ENTRY(leaf_pgfree);
2096 MAKE_BT_ENTRY(dup_pgfree);
2097 MAKE_BT_ENTRY(over_pgfree);
2098 break;
2099
2100 case DB_QUEUE:
2101 MAKE_QUEUE_ENTRY(magic);
2102 MAKE_QUEUE_ENTRY(version);
2103 MAKE_QUEUE_ENTRY(nkeys);
2104 MAKE_QUEUE_ENTRY(ndata);
2105 MAKE_QUEUE_ENTRY(pagesize);
2106 MAKE_QUEUE_ENTRY(pages);
2107 MAKE_QUEUE_ENTRY(re_len);
2108 MAKE_QUEUE_ENTRY(re_pad);
2109 MAKE_QUEUE_ENTRY(pgfree);
2110#if (DBVER == 31)
2111 MAKE_QUEUE_ENTRY(start);
2112#endif
2113 MAKE_QUEUE_ENTRY(first_recno);
2114 MAKE_QUEUE_ENTRY(cur_recno);
2115 break;
2116
2117 default:
2118 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2119 Py_DECREF(d);
2120 d = NULL;
2121 }
2122
2123#undef MAKE_HASH_ENTRY
2124#undef MAKE_BT_ENTRY
2125#undef MAKE_QUEUE_ENTRY
2126
2127 free(sp);
2128 return d;
2129}
2130
2131static PyObject*
2132DB_sync(DBObject* self, PyObject* args)
2133{
2134 int err;
2135 int flags = 0;
2136
2137 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2138 return NULL;
2139 CHECK_DB_NOT_CLOSED(self);
2140
2141 MYDB_BEGIN_ALLOW_THREADS;
2142 err = self->db->sync(self->db, flags);
2143 MYDB_END_ALLOW_THREADS;
2144 RETURN_IF_ERR();
2145 RETURN_NONE();
2146}
2147
2148
2149#if (DBVER >= 33)
2150static PyObject*
2151DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2152{
2153 int err, flags=0;
2154 u_int32_t count=0;
2155 PyObject* txnobj = NULL;
2156 DB_TXN *txn = NULL;
2157 char* kwnames[] = { "txn", "flags", NULL };
2158
2159 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2160 &txnobj, &flags))
2161 return NULL;
2162 CHECK_DB_NOT_CLOSED(self);
2163 if (!checkTxnObj(txnobj, &txn))
2164 return NULL;
2165
2166 MYDB_BEGIN_ALLOW_THREADS;
2167 err = self->db->truncate(self->db, txn, &count, flags);
2168 MYDB_END_ALLOW_THREADS;
2169 RETURN_IF_ERR();
2170 return PyInt_FromLong(count);
2171}
2172#endif
2173
2174
2175static PyObject*
2176DB_upgrade(DBObject* self, PyObject* args)
2177{
2178 int err, flags=0;
2179 char *filename;
2180
2181 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2182 return NULL;
2183 CHECK_DB_NOT_CLOSED(self);
2184
2185 MYDB_BEGIN_ALLOW_THREADS;
2186 err = self->db->upgrade(self->db, filename, flags);
2187 MYDB_END_ALLOW_THREADS;
2188 RETURN_IF_ERR();
2189 RETURN_NONE();
2190}
2191
2192
2193static PyObject*
2194DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2195{
2196 int err, flags=0;
2197 char* fileName;
2198 char* dbName=NULL;
2199 char* outFileName=NULL;
2200 FILE* outFile=NULL;
2201 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2202
2203 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2204 &fileName, &dbName, &outFileName, &flags))
2205 return NULL;
2206
2207 CHECK_DB_NOT_CLOSED(self);
2208 if (outFileName)
2209 outFile = fopen(outFileName, "w");
2210
2211 MYDB_BEGIN_ALLOW_THREADS;
2212 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2213 MYDB_END_ALLOW_THREADS;
2214 if (outFileName)
2215 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002216
2217 /* DB.verify acts as a DB handle destructor (like close); this was
2218 * documented in BerkeleyDB 4.2 but had the undocumented effect
2219 * of not being safe in prior versions while still requiring an explicit
2220 * DB.close call afterwards. Lets call close for the user to emulate
2221 * the safe 4.2 behaviour. */
2222#if (DBVER <= 41)
2223 self->db->close(self->db, 0);
2224#endif
2225 self->db = NULL;
2226
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002227 RETURN_IF_ERR();
2228 RETURN_NONE();
2229}
2230
2231
2232static PyObject*
2233DB_set_get_returns_none(DBObject* self, PyObject* args)
2234{
2235 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002236 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002237
2238 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2239 return NULL;
2240 CHECK_DB_NOT_CLOSED(self);
2241
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002242 if (self->moduleFlags.getReturnsNone)
2243 ++oldValue;
2244 if (self->moduleFlags.cursorSetReturnsNone)
2245 ++oldValue;
2246 self->moduleFlags.getReturnsNone = (flags >= 1);
2247 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002248 return PyInt_FromLong(oldValue);
2249}
2250
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002251#if (DBVER >= 41)
2252static PyObject*
2253DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2254{
2255 int err;
2256 u_int32_t flags=0;
2257 char *passwd = NULL;
2258 char* kwnames[] = { "passwd", "flags", NULL };
2259
2260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2261 &passwd, &flags)) {
2262 return NULL;
2263 }
2264
2265 MYDB_BEGIN_ALLOW_THREADS;
2266 err = self->db->set_encrypt(self->db, passwd, flags);
2267 MYDB_END_ALLOW_THREADS;
2268
2269 RETURN_IF_ERR();
2270 RETURN_NONE();
2271}
2272#endif /* DBVER >= 41 */
2273
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002274
2275/*-------------------------------------------------------------- */
2276/* Mapping and Dictionary-like access routines */
2277
2278int DB_length(DBObject* self)
2279{
2280 int err;
2281 long size = 0;
2282 int flags = 0;
2283 void* sp;
2284
2285 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002286 PyErr_SetObject(DBError,
2287 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002288 return -1;
2289 }
2290
2291 if (self->haveStat) { /* Has the stat function been called recently? If
2292 so, we can use the cached value. */
2293 flags = DB_CACHED_COUNTS;
2294 }
2295
2296 MYDB_BEGIN_ALLOW_THREADS;
2297#if (DBVER >= 33)
2298 err = self->db->stat(self->db, &sp, flags);
2299#else
2300 err = self->db->stat(self->db, &sp, NULL, flags);
2301#endif
2302 MYDB_END_ALLOW_THREADS;
2303
2304 if (err)
2305 return -1;
2306
2307 self->haveStat = 1;
2308
2309 /* All the stat structures have matching fields upto the ndata field,
2310 so we can use any of them for the type cast */
2311 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2312 free(sp);
2313 return size;
2314}
2315
2316
2317PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2318{
2319 int err;
2320 PyObject* retval;
2321 DBT key;
2322 DBT data;
2323
2324 CHECK_DB_NOT_CLOSED(self);
2325 if (!make_key_dbt(self, keyobj, &key, NULL))
2326 return NULL;
2327
2328 CLEAR_DBT(data);
2329 if (CHECK_DBFLAG(self, DB_THREAD)) {
2330 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2331 data.flags = DB_DBT_MALLOC;
2332 }
2333 MYDB_BEGIN_ALLOW_THREADS;
2334 err = self->db->get(self->db, NULL, &key, &data, 0);
2335 MYDB_END_ALLOW_THREADS;
2336 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2337 PyErr_SetObject(PyExc_KeyError, keyobj);
2338 retval = NULL;
2339 }
2340 else if (makeDBError(err)) {
2341 retval = NULL;
2342 }
2343 else {
2344 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2345 FREE_DBT(data);
2346 }
2347
2348 FREE_DBT(key);
2349 return retval;
2350}
2351
2352
2353static int
2354DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2355{
2356 DBT key, data;
2357 int retval;
2358 int flags = 0;
2359
2360 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002361 PyErr_SetObject(DBError,
2362 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002363 return -1;
2364 }
2365
2366 if (!make_key_dbt(self, keyobj, &key, NULL))
2367 return -1;
2368
2369 if (dataobj != NULL) {
2370 if (!make_dbt(dataobj, &data))
2371 retval = -1;
2372 else {
2373 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002374 /* dictionaries shouldn't have duplicate keys */
2375 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002376 retval = _DB_put(self, NULL, &key, &data, flags);
2377
2378 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002379 /* try deleting any old record that matches and then PUT it
2380 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002381 _DB_delete(self, NULL, &key, 0);
2382 PyErr_Clear();
2383 retval = _DB_put(self, NULL, &key, &data, flags);
2384 }
2385 }
2386 }
2387 else {
2388 /* dataobj == NULL, so delete the key */
2389 retval = _DB_delete(self, NULL, &key, 0);
2390 }
2391 FREE_DBT(key);
2392 return retval;
2393}
2394
2395
2396static PyObject*
2397DB_has_key(DBObject* self, PyObject* args)
2398{
2399 int err;
2400 PyObject* keyobj;
2401 DBT key, data;
2402 PyObject* txnobj = NULL;
2403 DB_TXN *txn = NULL;
2404
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002405 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002406 return NULL;
2407 CHECK_DB_NOT_CLOSED(self);
2408 if (!make_key_dbt(self, keyobj, &key, NULL))
2409 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002410 if (!checkTxnObj(txnobj, &txn)) {
2411 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002412 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002413 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002414
2415 /* This causes ENOMEM to be returned when the db has the key because
2416 it has a record but can't allocate a buffer for the data. This saves
2417 having to deal with data we won't be using.
2418 */
2419 CLEAR_DBT(data);
2420 data.flags = DB_DBT_USERMEM;
2421
2422 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002423 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002424 MYDB_END_ALLOW_THREADS;
2425 FREE_DBT(key);
2426 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2427}
2428
2429
2430#define _KEYS_LIST 1
2431#define _VALUES_LIST 2
2432#define _ITEMS_LIST 3
2433
2434static PyObject*
2435_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2436{
2437 int err, dbtype;
2438 DBT key;
2439 DBT data;
2440 DBC *cursor;
2441 PyObject* list;
2442 PyObject* item = NULL;
2443
2444 CHECK_DB_NOT_CLOSED(self);
2445 CLEAR_DBT(key);
2446 CLEAR_DBT(data);
2447
2448 dbtype = _DB_get_type(self);
2449 if (dbtype == -1)
2450 return NULL;
2451
2452 list = PyList_New(0);
2453 if (list == NULL) {
2454 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2455 return NULL;
2456 }
2457
2458 /* get a cursor */
2459 MYDB_BEGIN_ALLOW_THREADS;
2460 err = self->db->cursor(self->db, NULL, &cursor, 0);
2461 MYDB_END_ALLOW_THREADS;
2462 RETURN_IF_ERR();
2463
2464 if (CHECK_DBFLAG(self, DB_THREAD)) {
2465 key.flags = DB_DBT_REALLOC;
2466 data.flags = DB_DBT_REALLOC;
2467 }
2468
2469 while (1) { /* use the cursor to traverse the DB, collecting items */
2470 MYDB_BEGIN_ALLOW_THREADS;
2471 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2472 MYDB_END_ALLOW_THREADS;
2473
2474 if (err) {
2475 /* for any error, break out of the loop */
2476 break;
2477 }
2478
2479 switch (type) {
2480 case _KEYS_LIST:
2481 switch(dbtype) {
2482 case DB_BTREE:
2483 case DB_HASH:
2484 default:
2485 item = PyString_FromStringAndSize((char*)key.data, key.size);
2486 break;
2487 case DB_RECNO:
2488 case DB_QUEUE:
2489 item = PyInt_FromLong(*((db_recno_t*)key.data));
2490 break;
2491 }
2492 break;
2493
2494 case _VALUES_LIST:
2495 item = PyString_FromStringAndSize((char*)data.data, data.size);
2496 break;
2497
2498 case _ITEMS_LIST:
2499 switch(dbtype) {
2500 case DB_BTREE:
2501 case DB_HASH:
2502 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002503 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2504 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002505 break;
2506 case DB_RECNO:
2507 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002508 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2509 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002510 break;
2511 }
2512 break;
2513 }
2514 if (item == NULL) {
2515 Py_DECREF(list);
2516 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2517 list = NULL;
2518 goto done;
2519 }
2520 PyList_Append(list, item);
2521 Py_DECREF(item);
2522 }
2523
2524 /* DB_NOTFOUND is okay, it just means we got to the end */
2525 if (err != DB_NOTFOUND && makeDBError(err)) {
2526 Py_DECREF(list);
2527 list = NULL;
2528 }
2529
2530 done:
2531 FREE_DBT(key);
2532 FREE_DBT(data);
2533 MYDB_BEGIN_ALLOW_THREADS;
2534 cursor->c_close(cursor);
2535 MYDB_END_ALLOW_THREADS;
2536 return list;
2537}
2538
2539
2540static PyObject*
2541DB_keys(DBObject* self, PyObject* args)
2542{
2543 PyObject* txnobj = NULL;
2544 DB_TXN *txn = NULL;
2545
2546 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2547 return NULL;
2548 if (!checkTxnObj(txnobj, &txn))
2549 return NULL;
2550 return _DB_make_list(self, txn, _KEYS_LIST);
2551}
2552
2553
2554static PyObject*
2555DB_items(DBObject* self, PyObject* args)
2556{
2557 PyObject* txnobj = NULL;
2558 DB_TXN *txn = NULL;
2559
2560 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2561 return NULL;
2562 if (!checkTxnObj(txnobj, &txn))
2563 return NULL;
2564 return _DB_make_list(self, txn, _ITEMS_LIST);
2565}
2566
2567
2568static PyObject*
2569DB_values(DBObject* self, PyObject* args)
2570{
2571 PyObject* txnobj = NULL;
2572 DB_TXN *txn = NULL;
2573
2574 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2575 return NULL;
2576 if (!checkTxnObj(txnobj, &txn))
2577 return NULL;
2578 return _DB_make_list(self, txn, _VALUES_LIST);
2579}
2580
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002581/* --------------------------------------------------------------------- */
2582/* DBCursor methods */
2583
2584
2585static PyObject*
2586DBC_close(DBCursorObject* self, PyObject* args)
2587{
2588 int err = 0;
2589
2590 if (!PyArg_ParseTuple(args, ":close"))
2591 return NULL;
2592
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002593 if (self->dbc != NULL) {
2594 MYDB_BEGIN_ALLOW_THREADS;
2595 err = self->dbc->c_close(self->dbc);
2596 self->dbc = NULL;
2597 MYDB_END_ALLOW_THREADS;
2598 }
2599 RETURN_IF_ERR();
2600 RETURN_NONE();
2601}
2602
2603
2604static PyObject*
2605DBC_count(DBCursorObject* self, PyObject* args)
2606{
2607 int err = 0;
2608 db_recno_t count;
2609 int flags = 0;
2610
2611 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2612 return NULL;
2613
2614 CHECK_CURSOR_NOT_CLOSED(self);
2615
2616 MYDB_BEGIN_ALLOW_THREADS;
2617 err = self->dbc->c_count(self->dbc, &count, flags);
2618 MYDB_END_ALLOW_THREADS;
2619 RETURN_IF_ERR();
2620
2621 return PyInt_FromLong(count);
2622}
2623
2624
2625static PyObject*
2626DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2627{
2628 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2629}
2630
2631
2632static PyObject*
2633DBC_delete(DBCursorObject* self, PyObject* args)
2634{
2635 int err, flags=0;
2636
2637 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2638 return NULL;
2639
2640 CHECK_CURSOR_NOT_CLOSED(self);
2641
2642 MYDB_BEGIN_ALLOW_THREADS;
2643 err = self->dbc->c_del(self->dbc, flags);
2644 MYDB_END_ALLOW_THREADS;
2645 RETURN_IF_ERR();
2646
2647 self->mydb->haveStat = 0;
2648 RETURN_NONE();
2649}
2650
2651
2652static PyObject*
2653DBC_dup(DBCursorObject* self, PyObject* args)
2654{
2655 int err, flags =0;
2656 DBC* dbc = NULL;
2657
2658 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2659 return NULL;
2660
2661 CHECK_CURSOR_NOT_CLOSED(self);
2662
2663 MYDB_BEGIN_ALLOW_THREADS;
2664 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2665 MYDB_END_ALLOW_THREADS;
2666 RETURN_IF_ERR();
2667
2668 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2669}
2670
2671static PyObject*
2672DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2673{
2674 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2675}
2676
2677
2678static PyObject*
2679DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2680{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002681 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002682 PyObject* keyobj = NULL;
2683 PyObject* dataobj = NULL;
2684 PyObject* retval = NULL;
2685 int dlen = -1;
2686 int doff = -1;
2687 DBT key, data;
2688 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2689
2690 CLEAR_DBT(key);
2691 CLEAR_DBT(data);
2692 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002693 &flags, &dlen, &doff))
2694 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2697 &kwnames[1],
2698 &keyobj, &flags, &dlen, &doff))
2699 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002700 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2702 kwnames, &keyobj, &dataobj,
2703 &flags, &dlen, &doff))
2704 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002705 return NULL;
2706 }
2707 }
2708 }
2709
2710 CHECK_CURSOR_NOT_CLOSED(self);
2711
2712 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2713 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002714 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2715 (!add_partial_dbt(&data, dlen, doff)) )
2716 {
2717 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002718 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002719 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720
2721 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2722 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002723 if (!(key.flags & DB_DBT_REALLOC)) {
2724 key.flags |= DB_DBT_MALLOC;
2725 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726 }
2727
2728 MYDB_BEGIN_ALLOW_THREADS;
2729 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2730 MYDB_END_ALLOW_THREADS;
2731
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002732 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002733 Py_INCREF(Py_None);
2734 retval = Py_None;
2735 }
2736 else if (makeDBError(err)) {
2737 retval = NULL;
2738 }
2739 else {
2740 switch (_DB_get_type(self->mydb)) {
2741 case -1:
2742 retval = NULL;
2743 break;
2744 case DB_BTREE:
2745 case DB_HASH:
2746 default:
2747 retval = Py_BuildValue("s#s#", key.data, key.size,
2748 data.data, data.size);
2749 break;
2750 case DB_RECNO:
2751 case DB_QUEUE:
2752 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2753 data.data, data.size);
2754 break;
2755 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002756 FREE_DBT(data);
2757 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002758 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002759 return retval;
2760}
2761
2762
2763static PyObject*
2764DBC_get_recno(DBCursorObject* self, PyObject* args)
2765{
2766 int err;
2767 db_recno_t recno;
2768 DBT key;
2769 DBT data;
2770
2771 if (!PyArg_ParseTuple(args, ":get_recno"))
2772 return NULL;
2773
2774 CHECK_CURSOR_NOT_CLOSED(self);
2775
2776 CLEAR_DBT(key);
2777 CLEAR_DBT(data);
2778 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2779 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2780 data.flags = DB_DBT_MALLOC;
2781 key.flags = DB_DBT_MALLOC;
2782 }
2783
2784 MYDB_BEGIN_ALLOW_THREADS;
2785 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2786 MYDB_END_ALLOW_THREADS;
2787 RETURN_IF_ERR();
2788
2789 recno = *((db_recno_t*)data.data);
2790 FREE_DBT(key);
2791 FREE_DBT(data);
2792 return PyInt_FromLong(recno);
2793}
2794
2795
2796static PyObject*
2797DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2798{
2799 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2800}
2801
2802
2803static PyObject*
2804DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2805{
2806 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2807}
2808
2809
2810static PyObject*
2811DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2812{
2813 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2814}
2815
2816
2817static PyObject*
2818DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2819{
2820 int err, flags = 0;
2821 PyObject* keyobj, *dataobj;
2822 DBT key, data;
2823 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2824 int dlen = -1;
2825 int doff = -1;
2826
2827 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2828 &keyobj, &dataobj, &flags, &dlen, &doff))
2829 return NULL;
2830
2831 CHECK_CURSOR_NOT_CLOSED(self);
2832
2833 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2834 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002835 if (!make_dbt(dataobj, &data) ||
2836 !add_partial_dbt(&data, dlen, doff) )
2837 {
2838 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002840 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002841
2842 MYDB_BEGIN_ALLOW_THREADS;
2843 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2844 MYDB_END_ALLOW_THREADS;
2845 FREE_DBT(key);
2846 RETURN_IF_ERR();
2847 self->mydb->haveStat = 0;
2848 RETURN_NONE();
2849}
2850
2851
2852static PyObject*
2853DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2854{
2855 int err, flags = 0;
2856 DBT key, data;
2857 PyObject* retval, *keyobj;
2858 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2859 int dlen = -1;
2860 int doff = -1;
2861
2862 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2863 &keyobj, &flags, &dlen, &doff))
2864 return NULL;
2865
2866 CHECK_CURSOR_NOT_CLOSED(self);
2867
2868 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2869 return NULL;
2870
2871 CLEAR_DBT(data);
2872 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2873 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2874 data.flags = DB_DBT_MALLOC;
2875 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002876 if (!add_partial_dbt(&data, dlen, doff)) {
2877 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002878 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002879 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880
2881 MYDB_BEGIN_ALLOW_THREADS;
2882 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2883 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002884 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2885 Py_INCREF(Py_None);
2886 retval = Py_None;
2887 }
2888 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002889 retval = NULL;
2890 }
2891 else {
2892 switch (_DB_get_type(self->mydb)) {
2893 case -1:
2894 retval = NULL;
2895 break;
2896 case DB_BTREE:
2897 case DB_HASH:
2898 default:
2899 retval = Py_BuildValue("s#s#", key.data, key.size,
2900 data.data, data.size);
2901 break;
2902 case DB_RECNO:
2903 case DB_QUEUE:
2904 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2905 data.data, data.size);
2906 break;
2907 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002908 FREE_DBT(data);
2909 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002910 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002911
2912 return retval;
2913}
2914
2915
2916static PyObject*
2917DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2918{
2919 int err, flags = 0;
2920 DBT key, data;
2921 PyObject* retval, *keyobj;
2922 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2923 int dlen = -1;
2924 int doff = -1;
2925
2926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2927 &keyobj, &flags, &dlen, &doff))
2928 return NULL;
2929
2930 CHECK_CURSOR_NOT_CLOSED(self);
2931
2932 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2933 return NULL;
2934
2935 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002936 if (!add_partial_dbt(&data, dlen, doff)) {
2937 FREE_DBT(key);
2938 return NULL;
2939 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002940 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2941 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002942 data.flags |= DB_DBT_MALLOC;
2943 /* only BTREE databases will return anything in the key */
2944 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
2945 key.flags |= DB_DBT_MALLOC;
2946 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002947 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 MYDB_BEGIN_ALLOW_THREADS;
2949 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2950 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002951 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2952 Py_INCREF(Py_None);
2953 retval = Py_None;
2954 }
2955 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002956 retval = NULL;
2957 }
2958 else {
2959 switch (_DB_get_type(self->mydb)) {
2960 case -1:
2961 retval = NULL;
2962 break;
2963 case DB_BTREE:
2964 case DB_HASH:
2965 default:
2966 retval = Py_BuildValue("s#s#", key.data, key.size,
2967 data.data, data.size);
2968 break;
2969 case DB_RECNO:
2970 case DB_QUEUE:
2971 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2972 data.data, data.size);
2973 break;
2974 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002975 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 FREE_DBT(data);
2977 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002978 /* the only time REALLOC should be set is if we used an integer
2979 * key that make_dbt_key malloc'd for us. always free these. */
2980 if (key.flags & DB_DBT_REALLOC) {
2981 FREE_DBT(key);
2982 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983
2984 return retval;
2985}
2986
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002987static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002988_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2989 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002991 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002992 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002993 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002994
Gregory P. Smith7441e652003-11-03 21:35:31 +00002995 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2997 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002998 if (!make_dbt(dataobj, &data)) {
2999 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003000 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003001 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003002
3003 MYDB_BEGIN_ALLOW_THREADS;
3004 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3005 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003006 if ((err == DB_NOTFOUND) && returnsNone) {
3007 Py_INCREF(Py_None);
3008 retval = Py_None;
3009 }
3010 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003011 retval = NULL;
3012 }
3013 else {
3014 switch (_DB_get_type(self->mydb)) {
3015 case -1:
3016 retval = NULL;
3017 break;
3018 case DB_BTREE:
3019 case DB_HASH:
3020 default:
3021 retval = Py_BuildValue("s#s#", key.data, key.size,
3022 data.data, data.size);
3023 break;
3024 case DB_RECNO:
3025 case DB_QUEUE:
3026 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3027 data.data, data.size);
3028 break;
3029 }
3030 }
3031
3032 FREE_DBT(key);
3033 return retval;
3034}
3035
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003036static PyObject*
3037DBC_get_both(DBCursorObject* self, PyObject* args)
3038{
3039 int flags=0;
3040 PyObject *keyobj, *dataobj;
3041
3042 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3043 return NULL;
3044
Gregory P. Smith7441e652003-11-03 21:35:31 +00003045 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003046 CHECK_CURSOR_NOT_CLOSED(self);
3047
3048 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3049 self->mydb->moduleFlags.getReturnsNone);
3050}
3051
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003052/* Return size of entry */
3053static PyObject*
3054DBC_get_current_size(DBCursorObject* self, PyObject* args)
3055{
3056 int err, flags=DB_CURRENT;
3057 PyObject* retval = NULL;
3058 DBT key, data;
3059
3060 if (!PyArg_ParseTuple(args, ":get_current_size"))
3061 return NULL;
3062 CHECK_CURSOR_NOT_CLOSED(self);
3063 CLEAR_DBT(key);
3064 CLEAR_DBT(data);
3065
3066 /* We don't allocate any memory, forcing a ENOMEM error and thus
3067 getting the record size. */
3068 data.flags = DB_DBT_USERMEM;
3069 data.ulen = 0;
3070 MYDB_BEGIN_ALLOW_THREADS;
3071 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3072 MYDB_END_ALLOW_THREADS;
3073 if (err == ENOMEM || !err) {
3074 /* ENOMEM means positive size, !err means zero length value */
3075 retval = PyInt_FromLong((long)data.size);
3076 err = 0;
3077 }
3078
3079 FREE_DBT(key);
3080 FREE_DBT(data);
3081 RETURN_IF_ERR();
3082 return retval;
3083}
3084
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003085static PyObject*
3086DBC_set_both(DBCursorObject* self, PyObject* args)
3087{
3088 int flags=0;
3089 PyObject *keyobj, *dataobj;
3090
3091 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3092 return NULL;
3093
Gregory P. Smith7441e652003-11-03 21:35:31 +00003094 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003095 CHECK_CURSOR_NOT_CLOSED(self);
3096
3097 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3098 self->mydb->moduleFlags.cursorSetReturnsNone);
3099}
3100
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003101
3102static PyObject*
3103DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3104{
3105 int err, irecno, flags=0;
3106 db_recno_t recno;
3107 DBT key, data;
3108 PyObject* retval;
3109 int dlen = -1;
3110 int doff = -1;
3111 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3112
3113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3114 &irecno, &flags, &dlen, &doff))
3115 return NULL;
3116
3117 CHECK_CURSOR_NOT_CLOSED(self);
3118
3119 CLEAR_DBT(key);
3120 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003121 /* use allocated space so DB will be able to realloc room for the real
3122 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003123 key.data = malloc(sizeof(db_recno_t));
3124 if (key.data == NULL) {
3125 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3126 return NULL;
3127 }
3128 key.size = sizeof(db_recno_t);
3129 key.ulen = key.size;
3130 memcpy(key.data, &recno, sizeof(db_recno_t));
3131 key.flags = DB_DBT_REALLOC;
3132
3133 CLEAR_DBT(data);
3134 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3135 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3136 data.flags = DB_DBT_MALLOC;
3137 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003138 if (!add_partial_dbt(&data, dlen, doff)) {
3139 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003140 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003141 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003142
3143 MYDB_BEGIN_ALLOW_THREADS;
3144 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3145 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003146 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3147 Py_INCREF(Py_None);
3148 retval = Py_None;
3149 }
3150 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 retval = NULL;
3152 }
3153 else { /* Can only be used for BTrees, so no need to return int key */
3154 retval = Py_BuildValue("s#s#", key.data, key.size,
3155 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 FREE_DBT(data);
3157 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003158 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003159
3160 return retval;
3161}
3162
3163
3164static PyObject*
3165DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3166{
3167 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3168}
3169
3170
3171static PyObject*
3172DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3173{
3174 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3175}
3176
3177
3178static PyObject*
3179DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3180{
3181 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3182}
3183
3184
3185static PyObject*
3186DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3187{
3188 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3189}
3190
3191
3192static PyObject*
3193DBC_join_item(DBCursorObject* self, PyObject* args)
3194{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003195 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 DBT key, data;
3197 PyObject* retval;
3198
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003199 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003200 return NULL;
3201
3202 CHECK_CURSOR_NOT_CLOSED(self);
3203
3204 CLEAR_DBT(key);
3205 CLEAR_DBT(data);
3206 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3207 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3208 key.flags = DB_DBT_MALLOC;
3209 }
3210
3211 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003212 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003213 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003214 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3215 Py_INCREF(Py_None);
3216 retval = Py_None;
3217 }
3218 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003219 retval = NULL;
3220 }
3221 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003222 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003223 FREE_DBT(key);
3224 }
3225
3226 return retval;
3227}
3228
3229
3230
3231/* --------------------------------------------------------------------- */
3232/* DBEnv methods */
3233
3234
3235static PyObject*
3236DBEnv_close(DBEnvObject* self, PyObject* args)
3237{
3238 int err, flags = 0;
3239
3240 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3241 return NULL;
3242 if (!self->closed) { /* Don't close more than once */
3243 MYDB_BEGIN_ALLOW_THREADS;
3244 err = self->db_env->close(self->db_env, flags);
3245 MYDB_END_ALLOW_THREADS;
3246 /* after calling DBEnv->close, regardless of error, this DBEnv
3247 * may not be accessed again (BerkeleyDB docs). */
3248 self->closed = 1;
3249 self->db_env = NULL;
3250 RETURN_IF_ERR();
3251 }
3252 RETURN_NONE();
3253}
3254
3255
3256static PyObject*
3257DBEnv_open(DBEnvObject* self, PyObject* args)
3258{
3259 int err, flags=0, mode=0660;
3260 char *db_home;
3261
3262 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3263 return NULL;
3264
3265 CHECK_ENV_NOT_CLOSED(self);
3266
3267 MYDB_BEGIN_ALLOW_THREADS;
3268 err = self->db_env->open(self->db_env, db_home, flags, mode);
3269 MYDB_END_ALLOW_THREADS;
3270 RETURN_IF_ERR();
3271 self->closed = 0;
3272 self->flags = flags;
3273 RETURN_NONE();
3274}
3275
3276
3277static PyObject*
3278DBEnv_remove(DBEnvObject* self, PyObject* args)
3279{
3280 int err, flags=0;
3281 char *db_home;
3282
3283 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3284 return NULL;
3285 CHECK_ENV_NOT_CLOSED(self);
3286 MYDB_BEGIN_ALLOW_THREADS;
3287 err = self->db_env->remove(self->db_env, db_home, flags);
3288 MYDB_END_ALLOW_THREADS;
3289 RETURN_IF_ERR();
3290 RETURN_NONE();
3291}
3292
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003293#if (DBVER >= 41)
3294static PyObject*
3295DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3296{
3297 int err;
3298 u_int32_t flags=0;
3299 char *file = NULL;
3300 char *database = NULL;
3301 PyObject *txnobj = NULL;
3302 DB_TXN *txn = NULL;
3303 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3304
3305 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3306 &file, &database, &txnobj, &flags)) {
3307 return NULL;
3308 }
3309 if (!checkTxnObj(txnobj, &txn)) {
3310 return NULL;
3311 }
3312 CHECK_ENV_NOT_CLOSED(self);
3313 MYDB_BEGIN_ALLOW_THREADS;
3314 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3315 MYDB_END_ALLOW_THREADS;
3316 RETURN_IF_ERR();
3317 RETURN_NONE();
3318}
3319
3320static PyObject*
3321DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3322{
3323 int err;
3324 u_int32_t flags=0;
3325 char *file = NULL;
3326 char *database = NULL;
3327 char *newname = NULL;
3328 PyObject *txnobj = NULL;
3329 DB_TXN *txn = NULL;
3330 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3331
3332 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3333 &file, &database, &newname, &txnobj, &flags)) {
3334 return NULL;
3335 }
3336 if (!checkTxnObj(txnobj, &txn)) {
3337 return NULL;
3338 }
3339 CHECK_ENV_NOT_CLOSED(self);
3340 MYDB_BEGIN_ALLOW_THREADS;
3341 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3342 flags);
3343 MYDB_END_ALLOW_THREADS;
3344 RETURN_IF_ERR();
3345 RETURN_NONE();
3346}
3347
3348static PyObject*
3349DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3350{
3351 int err;
3352 u_int32_t flags=0;
3353 char *passwd = NULL;
3354 char* kwnames[] = { "passwd", "flags", NULL };
3355
3356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3357 &passwd, &flags)) {
3358 return NULL;
3359 }
3360
3361 MYDB_BEGIN_ALLOW_THREADS;
3362 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3363 MYDB_END_ALLOW_THREADS;
3364
3365 RETURN_IF_ERR();
3366 RETURN_NONE();
3367}
3368#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003369
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003370#if (DBVER >= 40)
3371static PyObject*
3372DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3373{
3374 int err;
3375 u_int32_t flags=0;
3376 u_int32_t timeout = 0;
3377 char* kwnames[] = { "timeout", "flags", NULL };
3378
3379 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3380 &timeout, &flags)) {
3381 return NULL;
3382 }
3383
3384 MYDB_BEGIN_ALLOW_THREADS;
3385 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3386 MYDB_END_ALLOW_THREADS;
3387
3388 RETURN_IF_ERR();
3389 RETURN_NONE();
3390}
3391#endif /* DBVER >= 40 */
3392
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003394DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3395{
3396 int err;
3397 long shm_key = 0;
3398
3399 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3400 return NULL;
3401 CHECK_ENV_NOT_CLOSED(self);
3402
3403 err = self->db_env->set_shm_key(self->db_env, shm_key);
3404 RETURN_IF_ERR();
3405 RETURN_NONE();
3406}
3407
3408static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3410{
3411 int err, gbytes=0, bytes=0, ncache=0;
3412
3413 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3414 &gbytes, &bytes, &ncache))
3415 return NULL;
3416 CHECK_ENV_NOT_CLOSED(self);
3417
3418 MYDB_BEGIN_ALLOW_THREADS;
3419 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3420 MYDB_END_ALLOW_THREADS;
3421 RETURN_IF_ERR();
3422 RETURN_NONE();
3423}
3424
3425
3426#if (DBVER >= 32)
3427static PyObject*
3428DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3429{
3430 int err, flags=0, onoff=0;
3431
3432 if (!PyArg_ParseTuple(args, "ii:set_flags",
3433 &flags, &onoff))
3434 return NULL;
3435 CHECK_ENV_NOT_CLOSED(self);
3436
3437 MYDB_BEGIN_ALLOW_THREADS;
3438 err = self->db_env->set_flags(self->db_env, flags, onoff);
3439 MYDB_END_ALLOW_THREADS;
3440 RETURN_IF_ERR();
3441 RETURN_NONE();
3442}
3443#endif
3444
3445
3446static PyObject*
3447DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3448{
3449 int err;
3450 char *dir;
3451
3452 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3453 return NULL;
3454 CHECK_ENV_NOT_CLOSED(self);
3455
3456 MYDB_BEGIN_ALLOW_THREADS;
3457 err = self->db_env->set_data_dir(self->db_env, dir);
3458 MYDB_END_ALLOW_THREADS;
3459 RETURN_IF_ERR();
3460 RETURN_NONE();
3461}
3462
3463
3464static PyObject*
3465DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3466{
3467 int err, lg_bsize;
3468
3469 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3470 return NULL;
3471 CHECK_ENV_NOT_CLOSED(self);
3472
3473 MYDB_BEGIN_ALLOW_THREADS;
3474 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3475 MYDB_END_ALLOW_THREADS;
3476 RETURN_IF_ERR();
3477 RETURN_NONE();
3478}
3479
3480
3481static PyObject*
3482DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3483{
3484 int err;
3485 char *dir;
3486
3487 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3488 return NULL;
3489 CHECK_ENV_NOT_CLOSED(self);
3490
3491 MYDB_BEGIN_ALLOW_THREADS;
3492 err = self->db_env->set_lg_dir(self->db_env, dir);
3493 MYDB_END_ALLOW_THREADS;
3494 RETURN_IF_ERR();
3495 RETURN_NONE();
3496}
3497
3498static PyObject*
3499DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3500{
3501 int err, lg_max;
3502
3503 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3504 return NULL;
3505 CHECK_ENV_NOT_CLOSED(self);
3506
3507 MYDB_BEGIN_ALLOW_THREADS;
3508 err = self->db_env->set_lg_max(self->db_env, lg_max);
3509 MYDB_END_ALLOW_THREADS;
3510 RETURN_IF_ERR();
3511 RETURN_NONE();
3512}
3513
3514
3515static PyObject*
3516DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3517{
3518 int err, lk_detect;
3519
3520 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3521 return NULL;
3522 CHECK_ENV_NOT_CLOSED(self);
3523
3524 MYDB_BEGIN_ALLOW_THREADS;
3525 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3526 MYDB_END_ALLOW_THREADS;
3527 RETURN_IF_ERR();
3528 RETURN_NONE();
3529}
3530
3531
3532static PyObject*
3533DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3534{
3535 int err, max;
3536
3537 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3538 return NULL;
3539 CHECK_ENV_NOT_CLOSED(self);
3540
3541 MYDB_BEGIN_ALLOW_THREADS;
3542 err = self->db_env->set_lk_max(self->db_env, max);
3543 MYDB_END_ALLOW_THREADS;
3544 RETURN_IF_ERR();
3545 RETURN_NONE();
3546}
3547
3548
3549#if (DBVER >= 32)
3550
3551static PyObject*
3552DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3553{
3554 int err, max;
3555
3556 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3557 return NULL;
3558 CHECK_ENV_NOT_CLOSED(self);
3559
3560 MYDB_BEGIN_ALLOW_THREADS;
3561 err = self->db_env->set_lk_max_locks(self->db_env, max);
3562 MYDB_END_ALLOW_THREADS;
3563 RETURN_IF_ERR();
3564 RETURN_NONE();
3565}
3566
3567
3568static PyObject*
3569DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3570{
3571 int err, max;
3572
3573 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3574 return NULL;
3575 CHECK_ENV_NOT_CLOSED(self);
3576
3577 MYDB_BEGIN_ALLOW_THREADS;
3578 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3579 MYDB_END_ALLOW_THREADS;
3580 RETURN_IF_ERR();
3581 RETURN_NONE();
3582}
3583
3584
3585static PyObject*
3586DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3587{
3588 int err, max;
3589
3590 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3591 return NULL;
3592 CHECK_ENV_NOT_CLOSED(self);
3593
3594 MYDB_BEGIN_ALLOW_THREADS;
3595 err = self->db_env->set_lk_max_objects(self->db_env, max);
3596 MYDB_END_ALLOW_THREADS;
3597 RETURN_IF_ERR();
3598 RETURN_NONE();
3599}
3600
3601#endif
3602
3603
3604static PyObject*
3605DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3606{
3607 int err, mp_mmapsize;
3608
3609 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3610 return NULL;
3611 CHECK_ENV_NOT_CLOSED(self);
3612
3613 MYDB_BEGIN_ALLOW_THREADS;
3614 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3615 MYDB_END_ALLOW_THREADS;
3616 RETURN_IF_ERR();
3617 RETURN_NONE();
3618}
3619
3620
3621static PyObject*
3622DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3623{
3624 int err;
3625 char *dir;
3626
3627 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3628 return NULL;
3629 CHECK_ENV_NOT_CLOSED(self);
3630
3631 MYDB_BEGIN_ALLOW_THREADS;
3632 err = self->db_env->set_tmp_dir(self->db_env, dir);
3633 MYDB_END_ALLOW_THREADS;
3634 RETURN_IF_ERR();
3635 RETURN_NONE();
3636}
3637
3638
3639static PyObject*
3640DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3641{
3642 int flags = 0;
3643 PyObject* txnobj = NULL;
3644 DB_TXN *txn = NULL;
3645 char* kwnames[] = { "parent", "flags", NULL };
3646
3647 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3648 &txnobj, &flags))
3649 return NULL;
3650
3651 if (!checkTxnObj(txnobj, &txn))
3652 return NULL;
3653 CHECK_ENV_NOT_CLOSED(self);
3654
3655 return (PyObject*)newDBTxnObject(self, txn, flags);
3656}
3657
3658
3659static PyObject*
3660DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3661{
3662 int err, kbyte=0, min=0, flags=0;
3663
3664 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3665 return NULL;
3666 CHECK_ENV_NOT_CLOSED(self);
3667
3668 MYDB_BEGIN_ALLOW_THREADS;
3669#if (DBVER >= 40)
3670 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3671#else
3672 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3673#endif
3674 MYDB_END_ALLOW_THREADS;
3675 RETURN_IF_ERR();
3676 RETURN_NONE();
3677}
3678
3679
3680static PyObject*
3681DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3682{
3683 int err, max;
3684
3685 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3686 return NULL;
3687 CHECK_ENV_NOT_CLOSED(self);
3688
3689 MYDB_BEGIN_ALLOW_THREADS;
3690 err = self->db_env->set_tx_max(self->db_env, max);
3691 MYDB_END_ALLOW_THREADS;
3692 RETURN_IF_ERR();
3693 RETURN_NONE();
3694}
3695
3696
3697static PyObject*
3698DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3699{
3700 int err, atype, flags=0;
3701 int aborted = 0;
3702
3703 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3704 return NULL;
3705 CHECK_ENV_NOT_CLOSED(self);
3706
3707 MYDB_BEGIN_ALLOW_THREADS;
3708#if (DBVER >= 40)
3709 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3710#else
3711 err = lock_detect(self->db_env, flags, atype, &aborted);
3712#endif
3713 MYDB_END_ALLOW_THREADS;
3714 RETURN_IF_ERR();
3715 return PyInt_FromLong(aborted);
3716}
3717
3718
3719static PyObject*
3720DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3721{
3722 int flags=0;
3723 int locker, lock_mode;
3724 DBT obj;
3725 PyObject* objobj;
3726
3727 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3728 return NULL;
3729
3730
3731 if (!make_dbt(objobj, &obj))
3732 return NULL;
3733
3734 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3735}
3736
3737
3738static PyObject*
3739DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3740{
3741 int err;
3742 u_int32_t theID;
3743
3744 if (!PyArg_ParseTuple(args, ":lock_id"))
3745 return NULL;
3746
3747 CHECK_ENV_NOT_CLOSED(self);
3748 MYDB_BEGIN_ALLOW_THREADS;
3749#if (DBVER >= 40)
3750 err = self->db_env->lock_id(self->db_env, &theID);
3751#else
3752 err = lock_id(self->db_env, &theID);
3753#endif
3754 MYDB_END_ALLOW_THREADS;
3755 RETURN_IF_ERR();
3756
3757 return PyInt_FromLong((long)theID);
3758}
3759
3760
3761static PyObject*
3762DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3763{
3764 int err;
3765 DBLockObject* dblockobj;
3766
3767 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3768 return NULL;
3769
3770 CHECK_ENV_NOT_CLOSED(self);
3771 MYDB_BEGIN_ALLOW_THREADS;
3772#if (DBVER >= 40)
3773 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3774#else
3775 err = lock_put(self->db_env, &dblockobj->lock);
3776#endif
3777 MYDB_END_ALLOW_THREADS;
3778 RETURN_IF_ERR();
3779 RETURN_NONE();
3780}
3781
3782
3783static PyObject*
3784DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3785{
3786 int err;
3787 DB_LOCK_STAT* sp;
3788 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003789 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790
3791 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3792 return NULL;
3793 CHECK_ENV_NOT_CLOSED(self);
3794
3795 MYDB_BEGIN_ALLOW_THREADS;
3796#if (DBVER >= 40)
3797 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3798#else
3799#if (DBVER >= 33)
3800 err = lock_stat(self->db_env, &sp);
3801#else
3802 err = lock_stat(self->db_env, &sp, NULL);
3803#endif
3804#endif
3805 MYDB_END_ALLOW_THREADS;
3806 RETURN_IF_ERR();
3807
3808 /* Turn the stat structure into a dictionary */
3809 d = PyDict_New();
3810 if (d == NULL) {
3811 free(sp);
3812 return NULL;
3813 }
3814
3815#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3816
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003817#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003819#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003820 MAKE_ENTRY(nmodes);
3821#if (DBVER >= 32)
3822 MAKE_ENTRY(maxlocks);
3823 MAKE_ENTRY(maxlockers);
3824 MAKE_ENTRY(maxobjects);
3825 MAKE_ENTRY(nlocks);
3826 MAKE_ENTRY(maxnlocks);
3827#endif
3828 MAKE_ENTRY(nlockers);
3829 MAKE_ENTRY(maxnlockers);
3830#if (DBVER >= 32)
3831 MAKE_ENTRY(nobjects);
3832 MAKE_ENTRY(maxnobjects);
3833#endif
3834 MAKE_ENTRY(nrequests);
3835 MAKE_ENTRY(nreleases);
3836 MAKE_ENTRY(nnowaits);
3837 MAKE_ENTRY(nconflicts);
3838 MAKE_ENTRY(ndeadlocks);
3839 MAKE_ENTRY(regsize);
3840 MAKE_ENTRY(region_wait);
3841 MAKE_ENTRY(region_nowait);
3842
3843#undef MAKE_ENTRY
3844 free(sp);
3845 return d;
3846}
3847
3848
3849static PyObject*
3850DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3851{
3852 int flags=0;
3853 int err;
3854 char **log_list_start, **log_list;
3855 PyObject* list;
3856 PyObject* item = NULL;
3857
3858 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3859 return NULL;
3860
3861 CHECK_ENV_NOT_CLOSED(self);
3862 MYDB_BEGIN_ALLOW_THREADS;
3863#if (DBVER >= 40)
3864 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3865#elif (DBVER == 33)
3866 err = log_archive(self->db_env, &log_list, flags);
3867#else
3868 err = log_archive(self->db_env, &log_list, flags, NULL);
3869#endif
3870 MYDB_END_ALLOW_THREADS;
3871 RETURN_IF_ERR();
3872
3873 list = PyList_New(0);
3874 if (list == NULL) {
3875 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3876 return NULL;
3877 }
3878
3879 if (log_list) {
3880 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3881 item = PyString_FromString (*log_list);
3882 if (item == NULL) {
3883 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003884 PyErr_SetString(PyExc_MemoryError,
3885 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003886 list = NULL;
3887 break;
3888 }
3889 PyList_Append(list, item);
3890 Py_DECREF(item);
3891 }
3892 free(log_list_start);
3893 }
3894 return list;
3895}
3896
3897
3898static PyObject*
3899DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3900{
3901 int err;
3902 DB_TXN_STAT* sp;
3903 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003904 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003905
3906 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3907 return NULL;
3908 CHECK_ENV_NOT_CLOSED(self);
3909
3910 MYDB_BEGIN_ALLOW_THREADS;
3911#if (DBVER >= 40)
3912 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3913#elif (DBVER == 33)
3914 err = txn_stat(self->db_env, &sp);
3915#else
3916 err = txn_stat(self->db_env, &sp, NULL);
3917#endif
3918 MYDB_END_ALLOW_THREADS;
3919 RETURN_IF_ERR();
3920
3921 /* Turn the stat structure into a dictionary */
3922 d = PyDict_New();
3923 if (d == NULL) {
3924 free(sp);
3925 return NULL;
3926 }
3927
3928#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3929
3930 MAKE_ENTRY(time_ckp);
3931 MAKE_ENTRY(last_txnid);
3932 MAKE_ENTRY(maxtxns);
3933 MAKE_ENTRY(nactive);
3934 MAKE_ENTRY(maxnactive);
3935 MAKE_ENTRY(nbegins);
3936 MAKE_ENTRY(naborts);
3937 MAKE_ENTRY(ncommits);
3938 MAKE_ENTRY(regsize);
3939 MAKE_ENTRY(region_wait);
3940 MAKE_ENTRY(region_nowait);
3941
3942#undef MAKE_ENTRY
3943 free(sp);
3944 return d;
3945}
3946
3947
3948static PyObject*
3949DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3950{
3951 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003952 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003953
3954 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3955 return NULL;
3956 CHECK_ENV_NOT_CLOSED(self);
3957
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003958 if (self->moduleFlags.getReturnsNone)
3959 ++oldValue;
3960 if (self->moduleFlags.cursorSetReturnsNone)
3961 ++oldValue;
3962 self->moduleFlags.getReturnsNone = (flags >= 1);
3963 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003964 return PyInt_FromLong(oldValue);
3965}
3966
3967
3968/* --------------------------------------------------------------------- */
3969/* DBTxn methods */
3970
3971
3972static PyObject*
3973DBTxn_commit(DBTxnObject* self, PyObject* args)
3974{
3975 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003976 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003977
3978 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3979 return NULL;
3980
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003981 if (!self->txn) {
3982 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3983 "DBTxn must not be used after txn_commit or txn_abort"));
3984 return NULL;
3985 }
3986 txn = self->txn;
3987 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003988 MYDB_BEGIN_ALLOW_THREADS;
3989#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003990 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003991#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003992 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993#endif
3994 MYDB_END_ALLOW_THREADS;
3995 RETURN_IF_ERR();
3996 RETURN_NONE();
3997}
3998
3999static PyObject*
4000DBTxn_prepare(DBTxnObject* self, PyObject* args)
4001{
4002#if (DBVER >= 33)
4003 int err;
4004 char* gid=NULL;
4005 int gid_size=0;
4006
4007 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4008 return NULL;
4009
4010 if (gid_size != DB_XIDDATASIZE) {
4011 PyErr_SetString(PyExc_TypeError,
4012 "gid must be DB_XIDDATASIZE bytes long");
4013 return NULL;
4014 }
4015
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004016 if (!self->txn) {
4017 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4018 "DBTxn must not be used after txn_commit or txn_abort"));
4019 return NULL;
4020 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004021 MYDB_BEGIN_ALLOW_THREADS;
4022#if (DBVER >= 40)
4023 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4024#else
4025 err = txn_prepare(self->txn, (u_int8_t*)gid);
4026#endif
4027 MYDB_END_ALLOW_THREADS;
4028 RETURN_IF_ERR();
4029 RETURN_NONE();
4030#else
4031 int err;
4032
4033 if (!PyArg_ParseTuple(args, ":prepare"))
4034 return NULL;
4035
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004036 if (!self->txn) {
4037 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4038 "DBTxn must not be used after txn_commit or txn_abort"));
4039 return NULL;
4040 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004041 MYDB_BEGIN_ALLOW_THREADS;
4042 err = txn_prepare(self->txn);
4043 MYDB_END_ALLOW_THREADS;
4044 RETURN_IF_ERR();
4045 RETURN_NONE();
4046#endif
4047}
4048
4049
4050static PyObject*
4051DBTxn_abort(DBTxnObject* self, PyObject* args)
4052{
4053 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004054 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004055
4056 if (!PyArg_ParseTuple(args, ":abort"))
4057 return NULL;
4058
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004059 if (!self->txn) {
4060 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4061 "DBTxn must not be used after txn_commit or txn_abort"));
4062 return NULL;
4063 }
4064 txn = self->txn;
4065 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004066 MYDB_BEGIN_ALLOW_THREADS;
4067#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004068 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004069#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004070 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004071#endif
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4075}
4076
4077
4078static PyObject*
4079DBTxn_id(DBTxnObject* self, PyObject* args)
4080{
4081 int id;
4082
4083 if (!PyArg_ParseTuple(args, ":id"))
4084 return NULL;
4085
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004086 if (!self->txn) {
4087 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4088 "DBTxn must not be used after txn_commit or txn_abort"));
4089 return NULL;
4090 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004091 MYDB_BEGIN_ALLOW_THREADS;
4092#if (DBVER >= 40)
4093 id = self->txn->id(self->txn);
4094#else
4095 id = txn_id(self->txn);
4096#endif
4097 MYDB_END_ALLOW_THREADS;
4098 return PyInt_FromLong(id);
4099}
4100
4101/* --------------------------------------------------------------------- */
4102/* Method definition tables and type objects */
4103
4104static PyMethodDef DB_methods[] = {
4105 {"append", (PyCFunction)DB_append, METH_VARARGS},
4106#if (DBVER >= 33)
4107 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4108#endif
4109 {"close", (PyCFunction)DB_close, METH_VARARGS},
4110#if (DBVER >= 32)
4111 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4112 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4113#endif
4114 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4115 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4116 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4117 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4118 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4119 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4120 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4121 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4122 {"join", (PyCFunction)DB_join, METH_VARARGS},
4123 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4124 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4125 {"items", (PyCFunction)DB_items, METH_VARARGS},
4126 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4127 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4128 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4129 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4130 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4131 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4132 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004133#if (DBVER >= 41)
4134 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4135#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004136 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4137 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4138 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4139 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4140 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4141 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4142 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4143 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4144 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4145#if (DBVER >= 32)
4146 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4147#endif
4148 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4149 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4150#if (DBVER >= 33)
4151 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4152#endif
4153 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4154 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4155 {"values", (PyCFunction)DB_values, METH_VARARGS},
4156 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4157 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4158 {NULL, NULL} /* sentinel */
4159};
4160
4161
4162static PyMappingMethods DB_mapping = {
4163 (inquiry)DB_length, /*mp_length*/
4164 (binaryfunc)DB_subscript, /*mp_subscript*/
4165 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4166};
4167
4168
4169static PyMethodDef DBCursor_methods[] = {
4170 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4171 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4172 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4173 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4174 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4175 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4176 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4177 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4178 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4179 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4180 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4181 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4182 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4183 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4184 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004185 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004186 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004187 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4188 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4189 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4190 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4191 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4192 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4193 {NULL, NULL} /* sentinel */
4194};
4195
4196
4197static PyMethodDef DBEnv_methods[] = {
4198 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4199 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4200 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004201#if (DBVER >= 41)
4202 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4203 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4204 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4205#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004206#if (DBVER >= 40)
4207 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4208#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004209 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004210 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4211 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4212#if (DBVER >= 32)
4213 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4214#endif
4215 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4216 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4217 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4218 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4219 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4220#if (DBVER >= 32)
4221 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4222 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4223 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4224#endif
4225 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4226 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4227 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4228 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4229 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4230 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4231 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4232 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4233 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4234 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4235 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4236 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4237 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4238 {NULL, NULL} /* sentinel */
4239};
4240
4241
4242static PyMethodDef DBTxn_methods[] = {
4243 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4244 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4245 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4246 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4247 {NULL, NULL} /* sentinel */
4248};
4249
4250
4251static PyObject*
4252DB_getattr(DBObject* self, char *name)
4253{
4254 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4255}
4256
4257
4258static PyObject*
4259DBEnv_getattr(DBEnvObject* self, char *name)
4260{
4261 if (!strcmp(name, "db_home")) {
4262 CHECK_ENV_NOT_CLOSED(self);
4263 if (self->db_env->db_home == NULL) {
4264 RETURN_NONE();
4265 }
4266 return PyString_FromString(self->db_env->db_home);
4267 }
4268
4269 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4270}
4271
4272
4273static PyObject*
4274DBCursor_getattr(DBCursorObject* self, char *name)
4275{
4276 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4277}
4278
4279static PyObject*
4280DBTxn_getattr(DBTxnObject* self, char *name)
4281{
4282 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4283}
4284
4285static PyObject*
4286DBLock_getattr(DBLockObject* self, char *name)
4287{
4288 return NULL;
4289}
4290
4291statichere PyTypeObject DB_Type = {
4292 PyObject_HEAD_INIT(NULL)
4293 0, /*ob_size*/
4294 "DB", /*tp_name*/
4295 sizeof(DBObject), /*tp_basicsize*/
4296 0, /*tp_itemsize*/
4297 /* methods */
4298 (destructor)DB_dealloc, /*tp_dealloc*/
4299 0, /*tp_print*/
4300 (getattrfunc)DB_getattr, /*tp_getattr*/
4301 0, /*tp_setattr*/
4302 0, /*tp_compare*/
4303 0, /*tp_repr*/
4304 0, /*tp_as_number*/
4305 0, /*tp_as_sequence*/
4306 &DB_mapping,/*tp_as_mapping*/
4307 0, /*tp_hash*/
4308};
4309
4310
4311statichere PyTypeObject DBCursor_Type = {
4312 PyObject_HEAD_INIT(NULL)
4313 0, /*ob_size*/
4314 "DBCursor", /*tp_name*/
4315 sizeof(DBCursorObject), /*tp_basicsize*/
4316 0, /*tp_itemsize*/
4317 /* methods */
4318 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4319 0, /*tp_print*/
4320 (getattrfunc)DBCursor_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*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004328#ifdef HAVE_WEAKREF
4329 0, /* tp_call */
4330 0, /* tp_str */
4331 0, /* tp_getattro */
4332 0, /* tp_setattro */
4333 0, /* tp_as_buffer */
4334 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4335 0, /* tp_doc */
4336 0, /* tp_traverse */
4337 0, /* tp_clear */
4338 0, /* tp_richcompare */
4339 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4340#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004341};
4342
4343
4344statichere PyTypeObject DBEnv_Type = {
4345 PyObject_HEAD_INIT(NULL)
4346 0, /*ob_size*/
4347 "DBEnv", /*tp_name*/
4348 sizeof(DBEnvObject), /*tp_basicsize*/
4349 0, /*tp_itemsize*/
4350 /* methods */
4351 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4352 0, /*tp_print*/
4353 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4354 0, /*tp_setattr*/
4355 0, /*tp_compare*/
4356 0, /*tp_repr*/
4357 0, /*tp_as_number*/
4358 0, /*tp_as_sequence*/
4359 0, /*tp_as_mapping*/
4360 0, /*tp_hash*/
4361};
4362
4363statichere PyTypeObject DBTxn_Type = {
4364 PyObject_HEAD_INIT(NULL)
4365 0, /*ob_size*/
4366 "DBTxn", /*tp_name*/
4367 sizeof(DBTxnObject), /*tp_basicsize*/
4368 0, /*tp_itemsize*/
4369 /* methods */
4370 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4371 0, /*tp_print*/
4372 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4373 0, /*tp_setattr*/
4374 0, /*tp_compare*/
4375 0, /*tp_repr*/
4376 0, /*tp_as_number*/
4377 0, /*tp_as_sequence*/
4378 0, /*tp_as_mapping*/
4379 0, /*tp_hash*/
4380};
4381
4382
4383statichere PyTypeObject DBLock_Type = {
4384 PyObject_HEAD_INIT(NULL)
4385 0, /*ob_size*/
4386 "DBLock", /*tp_name*/
4387 sizeof(DBLockObject), /*tp_basicsize*/
4388 0, /*tp_itemsize*/
4389 /* methods */
4390 (destructor)DBLock_dealloc, /*tp_dealloc*/
4391 0, /*tp_print*/
4392 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4393 0, /*tp_setattr*/
4394 0, /*tp_compare*/
4395 0, /*tp_repr*/
4396 0, /*tp_as_number*/
4397 0, /*tp_as_sequence*/
4398 0, /*tp_as_mapping*/
4399 0, /*tp_hash*/
4400};
4401
4402
4403/* --------------------------------------------------------------------- */
4404/* Module-level functions */
4405
4406static PyObject*
4407DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4408{
4409 PyObject* dbenvobj = NULL;
4410 int flags = 0;
4411 char* kwnames[] = { "dbEnv", "flags", NULL};
4412
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4414 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004415 return NULL;
4416 if (dbenvobj == Py_None)
4417 dbenvobj = NULL;
4418 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4419 makeTypeError("DBEnv", dbenvobj);
4420 return NULL;
4421 }
4422
4423 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4424}
4425
4426
4427static PyObject*
4428DBEnv_construct(PyObject* self, PyObject* args)
4429{
4430 int flags = 0;
4431 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4432 return (PyObject* )newDBEnvObject(flags);
4433}
4434
4435
4436static char bsddb_version_doc[] =
4437"Returns a tuple of major, minor, and patch release numbers of the\n\
4438underlying DB library.";
4439
4440static PyObject*
4441bsddb_version(PyObject* self, PyObject* args)
4442{
4443 int major, minor, patch;
4444
4445 if (!PyArg_ParseTuple(args, ":version"))
4446 return NULL;
4447 db_version(&major, &minor, &patch);
4448 return Py_BuildValue("(iii)", major, minor, patch);
4449}
4450
4451
4452/* List of functions defined in the module */
4453
4454static PyMethodDef bsddb_methods[] = {
4455 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4456 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4457 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4458 {NULL, NULL} /* sentinel */
4459};
4460
4461
4462/* --------------------------------------------------------------------- */
4463/* Module initialization */
4464
4465
4466/* Convenience routine to export an integer value.
4467 * Errors are silently ignored, for better or for worse...
4468 */
4469#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4470
Gregory P. Smith41631e82003-09-21 00:08:14 +00004471#define MODULE_NAME_MAX_LEN 11
4472static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004473
4474DL_EXPORT(void) init_bsddb(void)
4475{
4476 PyObject* m;
4477 PyObject* d;
4478 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4479 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4480 PyObject* cvsid_s = PyString_FromString( rcs_id );
4481
4482 /* Initialize the type of the new type objects here; doing it here
4483 is required for portability to Windows without requiring C++. */
4484 DB_Type.ob_type = &PyType_Type;
4485 DBCursor_Type.ob_type = &PyType_Type;
4486 DBEnv_Type.ob_type = &PyType_Type;
4487 DBTxn_Type.ob_type = &PyType_Type;
4488 DBLock_Type.ob_type = &PyType_Type;
4489
4490
Mark Hammonda69d4092003-04-22 23:13:27 +00004491#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004493 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004494#endif
4495
4496 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004497 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004498
4499 /* Add some symbolic constants to the module */
4500 d = PyModule_GetDict(m);
4501 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4502 PyDict_SetItemString(d, "cvsid", cvsid_s);
4503 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4504 Py_DECREF(pybsddb_version_s);
4505 pybsddb_version_s = NULL;
4506 Py_DECREF(cvsid_s);
4507 cvsid_s = NULL;
4508 Py_DECREF(db_version_s);
4509 db_version_s = NULL;
4510
4511 ADD_INT(d, DB_VERSION_MAJOR);
4512 ADD_INT(d, DB_VERSION_MINOR);
4513 ADD_INT(d, DB_VERSION_PATCH);
4514
4515 ADD_INT(d, DB_MAX_PAGES);
4516 ADD_INT(d, DB_MAX_RECORDS);
4517
Gregory P. Smith41631e82003-09-21 00:08:14 +00004518#if (DBVER >= 42)
4519 ADD_INT(d, DB_RPCCLIENT);
4520#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004521 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004522 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4523 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4524#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004525 ADD_INT(d, DB_XA_CREATE);
4526
4527 ADD_INT(d, DB_CREATE);
4528 ADD_INT(d, DB_NOMMAP);
4529 ADD_INT(d, DB_THREAD);
4530
4531 ADD_INT(d, DB_FORCE);
4532 ADD_INT(d, DB_INIT_CDB);
4533 ADD_INT(d, DB_INIT_LOCK);
4534 ADD_INT(d, DB_INIT_LOG);
4535 ADD_INT(d, DB_INIT_MPOOL);
4536 ADD_INT(d, DB_INIT_TXN);
4537#if (DBVER >= 32)
4538 ADD_INT(d, DB_JOINENV);
4539#endif
4540
4541 ADD_INT(d, DB_RECOVER);
4542 ADD_INT(d, DB_RECOVER_FATAL);
4543 ADD_INT(d, DB_TXN_NOSYNC);
4544 ADD_INT(d, DB_USE_ENVIRON);
4545 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4546
4547 ADD_INT(d, DB_LOCKDOWN);
4548 ADD_INT(d, DB_PRIVATE);
4549 ADD_INT(d, DB_SYSTEM_MEM);
4550
4551 ADD_INT(d, DB_TXN_SYNC);
4552 ADD_INT(d, DB_TXN_NOWAIT);
4553
4554 ADD_INT(d, DB_EXCL);
4555 ADD_INT(d, DB_FCNTL_LOCKING);
4556 ADD_INT(d, DB_ODDFILESIZE);
4557 ADD_INT(d, DB_RDWRMASTER);
4558 ADD_INT(d, DB_RDONLY);
4559 ADD_INT(d, DB_TRUNCATE);
4560#if (DBVER >= 32)
4561 ADD_INT(d, DB_EXTENT);
4562 ADD_INT(d, DB_CDB_ALLDB);
4563 ADD_INT(d, DB_VERIFY);
4564#endif
4565 ADD_INT(d, DB_UPGRADE);
4566
4567 ADD_INT(d, DB_AGGRESSIVE);
4568 ADD_INT(d, DB_NOORDERCHK);
4569 ADD_INT(d, DB_ORDERCHKONLY);
4570 ADD_INT(d, DB_PR_PAGE);
4571#if ! (DBVER >= 33)
4572 ADD_INT(d, DB_VRFY_FLAGMASK);
4573 ADD_INT(d, DB_PR_HEADERS);
4574#endif
4575 ADD_INT(d, DB_PR_RECOVERYTEST);
4576 ADD_INT(d, DB_SALVAGE);
4577
4578 ADD_INT(d, DB_LOCK_NORUN);
4579 ADD_INT(d, DB_LOCK_DEFAULT);
4580 ADD_INT(d, DB_LOCK_OLDEST);
4581 ADD_INT(d, DB_LOCK_RANDOM);
4582 ADD_INT(d, DB_LOCK_YOUNGEST);
4583#if (DBVER >= 33)
4584 ADD_INT(d, DB_LOCK_MAXLOCKS);
4585 ADD_INT(d, DB_LOCK_MINLOCKS);
4586 ADD_INT(d, DB_LOCK_MINWRITE);
4587#endif
4588
4589
4590#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004591 /* docs say to use zero instead */
4592 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593#else
4594 ADD_INT(d, DB_LOCK_CONFLICT);
4595#endif
4596
4597 ADD_INT(d, DB_LOCK_DUMP);
4598 ADD_INT(d, DB_LOCK_GET);
4599 ADD_INT(d, DB_LOCK_INHERIT);
4600 ADD_INT(d, DB_LOCK_PUT);
4601 ADD_INT(d, DB_LOCK_PUT_ALL);
4602 ADD_INT(d, DB_LOCK_PUT_OBJ);
4603
4604 ADD_INT(d, DB_LOCK_NG);
4605 ADD_INT(d, DB_LOCK_READ);
4606 ADD_INT(d, DB_LOCK_WRITE);
4607 ADD_INT(d, DB_LOCK_NOWAIT);
4608#if (DBVER >= 32)
4609 ADD_INT(d, DB_LOCK_WAIT);
4610#endif
4611 ADD_INT(d, DB_LOCK_IWRITE);
4612 ADD_INT(d, DB_LOCK_IREAD);
4613 ADD_INT(d, DB_LOCK_IWR);
4614#if (DBVER >= 33)
4615 ADD_INT(d, DB_LOCK_DIRTY);
4616 ADD_INT(d, DB_LOCK_WWRITE);
4617#endif
4618
4619 ADD_INT(d, DB_LOCK_RECORD);
4620 ADD_INT(d, DB_LOCK_UPGRADE);
4621#if (DBVER >= 32)
4622 ADD_INT(d, DB_LOCK_SWITCH);
4623#endif
4624#if (DBVER >= 33)
4625 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4626#endif
4627
4628 ADD_INT(d, DB_LOCK_NOWAIT);
4629 ADD_INT(d, DB_LOCK_RECORD);
4630 ADD_INT(d, DB_LOCK_UPGRADE);
4631
4632#if (DBVER >= 33)
4633 ADD_INT(d, DB_LSTAT_ABORTED);
4634 ADD_INT(d, DB_LSTAT_ERR);
4635 ADD_INT(d, DB_LSTAT_FREE);
4636 ADD_INT(d, DB_LSTAT_HELD);
4637#if (DBVER == 33)
4638 ADD_INT(d, DB_LSTAT_NOGRANT);
4639#endif
4640 ADD_INT(d, DB_LSTAT_PENDING);
4641 ADD_INT(d, DB_LSTAT_WAITING);
4642#endif
4643
4644 ADD_INT(d, DB_ARCH_ABS);
4645 ADD_INT(d, DB_ARCH_DATA);
4646 ADD_INT(d, DB_ARCH_LOG);
4647
4648 ADD_INT(d, DB_BTREE);
4649 ADD_INT(d, DB_HASH);
4650 ADD_INT(d, DB_RECNO);
4651 ADD_INT(d, DB_QUEUE);
4652 ADD_INT(d, DB_UNKNOWN);
4653
4654 ADD_INT(d, DB_DUP);
4655 ADD_INT(d, DB_DUPSORT);
4656 ADD_INT(d, DB_RECNUM);
4657 ADD_INT(d, DB_RENUMBER);
4658 ADD_INT(d, DB_REVSPLITOFF);
4659 ADD_INT(d, DB_SNAPSHOT);
4660
4661 ADD_INT(d, DB_JOIN_NOSORT);
4662
4663 ADD_INT(d, DB_AFTER);
4664 ADD_INT(d, DB_APPEND);
4665 ADD_INT(d, DB_BEFORE);
4666 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004667#if (DBVER >= 41)
4668 _addIntToDict(d, "DB_CHECKPOINT", 0);
4669#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004670 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004671 ADD_INT(d, DB_CURLSN);
4672#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004673#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004674 ADD_INT(d, DB_COMMIT);
4675#endif
4676 ADD_INT(d, DB_CONSUME);
4677#if (DBVER >= 32)
4678 ADD_INT(d, DB_CONSUME_WAIT);
4679#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680 ADD_INT(d, DB_CURRENT);
4681#if (DBVER >= 33)
4682 ADD_INT(d, DB_FAST_STAT);
4683#endif
4684 ADD_INT(d, DB_FIRST);
4685 ADD_INT(d, DB_FLUSH);
4686 ADD_INT(d, DB_GET_BOTH);
4687 ADD_INT(d, DB_GET_RECNO);
4688 ADD_INT(d, DB_JOIN_ITEM);
4689 ADD_INT(d, DB_KEYFIRST);
4690 ADD_INT(d, DB_KEYLAST);
4691 ADD_INT(d, DB_LAST);
4692 ADD_INT(d, DB_NEXT);
4693 ADD_INT(d, DB_NEXT_DUP);
4694 ADD_INT(d, DB_NEXT_NODUP);
4695 ADD_INT(d, DB_NODUPDATA);
4696 ADD_INT(d, DB_NOOVERWRITE);
4697 ADD_INT(d, DB_NOSYNC);
4698 ADD_INT(d, DB_POSITION);
4699 ADD_INT(d, DB_PREV);
4700 ADD_INT(d, DB_PREV_NODUP);
4701 ADD_INT(d, DB_RECORDCOUNT);
4702 ADD_INT(d, DB_SET);
4703 ADD_INT(d, DB_SET_RANGE);
4704 ADD_INT(d, DB_SET_RECNO);
4705 ADD_INT(d, DB_WRITECURSOR);
4706
4707 ADD_INT(d, DB_OPFLAGS_MASK);
4708 ADD_INT(d, DB_RMW);
4709#if (DBVER >= 33)
4710 ADD_INT(d, DB_DIRTY_READ);
4711 ADD_INT(d, DB_MULTIPLE);
4712 ADD_INT(d, DB_MULTIPLE_KEY);
4713#endif
4714
4715#if (DBVER >= 33)
4716 ADD_INT(d, DB_DONOTINDEX);
4717#endif
4718
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004719#if (DBVER >= 41)
4720 _addIntToDict(d, "DB_INCOMPLETE", 0);
4721#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004722 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004723#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724 ADD_INT(d, DB_KEYEMPTY);
4725 ADD_INT(d, DB_KEYEXIST);
4726 ADD_INT(d, DB_LOCK_DEADLOCK);
4727 ADD_INT(d, DB_LOCK_NOTGRANTED);
4728 ADD_INT(d, DB_NOSERVER);
4729 ADD_INT(d, DB_NOSERVER_HOME);
4730 ADD_INT(d, DB_NOSERVER_ID);
4731 ADD_INT(d, DB_NOTFOUND);
4732 ADD_INT(d, DB_OLD_VERSION);
4733 ADD_INT(d, DB_RUNRECOVERY);
4734 ADD_INT(d, DB_VERIFY_BAD);
4735#if (DBVER >= 33)
4736 ADD_INT(d, DB_PAGE_NOTFOUND);
4737 ADD_INT(d, DB_SECONDARY_BAD);
4738#endif
4739#if (DBVER >= 40)
4740 ADD_INT(d, DB_STAT_CLEAR);
4741 ADD_INT(d, DB_REGION_INIT);
4742 ADD_INT(d, DB_NOLOCKING);
4743 ADD_INT(d, DB_YIELDCPU);
4744 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4745 ADD_INT(d, DB_NOPANIC);
4746#endif
4747
Gregory P. Smith41631e82003-09-21 00:08:14 +00004748#if (DBVER >= 42)
4749 ADD_INT(d, DB_TIME_NOTGRANTED);
4750 ADD_INT(d, DB_TXN_NOT_DURABLE);
4751 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4752 ADD_INT(d, DB_LOG_AUTOREMOVE);
4753 ADD_INT(d, DB_DIRECT_LOG);
4754 ADD_INT(d, DB_DIRECT_DB);
4755 ADD_INT(d, DB_INIT_REP);
4756 ADD_INT(d, DB_ENCRYPT);
4757 ADD_INT(d, DB_CHKSUM);
4758#endif
4759
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004760#if (DBVER >= 41)
4761 ADD_INT(d, DB_ENCRYPT_AES);
4762 ADD_INT(d, DB_AUTO_COMMIT);
4763#else
4764 /* allow berkeleydb 4.1 aware apps to run on older versions */
4765 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4766#endif
4767
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004768 ADD_INT(d, EINVAL);
4769 ADD_INT(d, EACCES);
4770 ADD_INT(d, ENOSPC);
4771 ADD_INT(d, ENOMEM);
4772 ADD_INT(d, EAGAIN);
4773 ADD_INT(d, EBUSY);
4774 ADD_INT(d, EEXIST);
4775 ADD_INT(d, ENOENT);
4776 ADD_INT(d, EPERM);
4777
Barry Warsaw1baa9822003-03-31 19:51:29 +00004778#if (DBVER >= 40)
4779 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4780 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4781#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004782
4783 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004784 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 PyDict_SetItemString(d, "DBError", DBError);
4786
4787 /* Some magic to make DBNotFoundError derive from both DBError and
4788 KeyError, since the API only supports using one base class. */
4789 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4790 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4791 Py_file_input, d, d);
4792 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4793 PyDict_DelItemString(d, "KeyError");
4794
4795
4796 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004797#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004798 PyDict_SetItemString(d, #name, name)
4799
4800#if !INCOMPLETE_IS_WARNING
4801 MAKE_EX(DBIncompleteError);
4802#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00004803 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004804 MAKE_EX(DBKeyEmptyError);
4805 MAKE_EX(DBKeyExistError);
4806 MAKE_EX(DBLockDeadlockError);
4807 MAKE_EX(DBLockNotGrantedError);
4808 MAKE_EX(DBOldVersionError);
4809 MAKE_EX(DBRunRecoveryError);
4810 MAKE_EX(DBVerifyBadError);
4811 MAKE_EX(DBNoServerError);
4812 MAKE_EX(DBNoServerHomeError);
4813 MAKE_EX(DBNoServerIDError);
4814#if (DBVER >= 33)
4815 MAKE_EX(DBPageNotFoundError);
4816 MAKE_EX(DBSecondaryBadError);
4817#endif
4818
4819 MAKE_EX(DBInvalidArgError);
4820 MAKE_EX(DBAccessError);
4821 MAKE_EX(DBNoSpaceError);
4822 MAKE_EX(DBNoMemoryError);
4823 MAKE_EX(DBAgainError);
4824 MAKE_EX(DBBusyError);
4825 MAKE_EX(DBFileExistsError);
4826 MAKE_EX(DBNoSuchFileError);
4827 MAKE_EX(DBPermissionsError);
4828
4829#undef MAKE_EX
4830
4831 /* Check for errors */
4832 if (PyErr_Occurred()) {
4833 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004834 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004835 }
4836}
Gregory P. Smith41631e82003-09-21 00:08:14 +00004837
4838/* allow this module to be named _pybsddb so that it can be installed
4839 * and imported on top of python >= 2.3 that includes its own older
4840 * copy of the library named _bsddb without importing the old version. */
4841DL_EXPORT(void) init_pybsddb(void)
4842{
4843 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
4844 init_bsddb();
4845}