blob: 6a726a589c0383df36b5b73bb21a6d2e12194192 [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
Neal Norwitz37b0c1d2004-07-09 23:33:06 +0000100#define PY_BSDDB_VERSION "4.2.9"
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. Smith31c50652004-06-28 01:20:40 +0000197/* if Python >= 2.1 better support warnings */
198#if PYTHON_API_VERSION >= 1010
199#define HAVE_WARNINGS
200#else
201#undef HAVE_WARNINGS
202#endif
203
Neal Norwitzb4a55812004-07-09 23:30:57 +0000204#if PYTHON_API_VERSION <= 1007
205 /* 1.5 compatibility */
206#define PyObject_New PyObject_NEW
207#define PyObject_Del PyMem_DEL
208#endif
209
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000210struct behaviourFlags {
211 /* What is the default behaviour when DB->get or DBCursor->get returns a
212 DB_NOTFOUND error? Return None or raise an exception? */
213 unsigned int getReturnsNone : 1;
214 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
215 * returns a DB_NOTFOUND error? Return None or raise an exception? */
216 unsigned int cursorSetReturnsNone : 1;
217};
218
219#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000220#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000222typedef struct {
223 PyObject_HEAD
224 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000225 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000226 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000227 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000228#ifdef HAVE_WEAKREF
229 PyObject *in_weakreflist; /* List of weak references */
230#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000231} DBEnvObject;
232
233
234typedef struct {
235 PyObject_HEAD
236 DB* db;
237 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000238 u_int32_t flags; /* saved flags from open() */
239 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000241 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000242#if (DBVER >= 33)
243 PyObject* associateCallback;
244 int primaryDBType;
245#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000246#ifdef HAVE_WEAKREF
247 PyObject *in_weakreflist; /* List of weak references */
248#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000249} DBObject;
250
251
252typedef struct {
253 PyObject_HEAD
254 DBC* dbc;
255 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000256#ifdef HAVE_WEAKREF
257 PyObject *in_weakreflist; /* List of weak references */
258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259} DBCursorObject;
260
261
262typedef struct {
263 PyObject_HEAD
264 DB_TXN* txn;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBTxnObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000274#ifdef HAVE_WEAKREF
275 PyObject *in_weakreflist; /* List of weak references */
276#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000277} DBLockObject;
278
279
280
281staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
282
283#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
284#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
285#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
286#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
287#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
288
289
290/* --------------------------------------------------------------------- */
291/* Utility macros and functions */
292
293#define RETURN_IF_ERR() \
294 if (makeDBError(err)) { \
295 return NULL; \
296 }
297
298#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
299
Gregory P. Smithe2767172003-11-02 08:06:29 +0000300#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
301 if ((nonNull) == NULL) { \
302 PyObject *errTuple = NULL; \
303 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
304 PyErr_SetObject((pyErrObj), errTuple); \
305 Py_DECREF(errTuple); \
306 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000307 }
308
Gregory P. Smithe2767172003-11-02 08:06:29 +0000309#define CHECK_DB_NOT_CLOSED(dbobj) \
310 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
311
312#define CHECK_ENV_NOT_CLOSED(env) \
313 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000314
315#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000316 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000317
318
319#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
320 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
321
322#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
323
324#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000325 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000326
327
328static int makeDBError(int err);
329
330
331/* Return the access method type of the DBObject */
332static int _DB_get_type(DBObject* self)
333{
334#if (DBVER >= 33)
335 DBTYPE type;
336 int err;
337 err = self->db->get_type(self->db, &type);
338 if (makeDBError(err)) {
339 return -1;
340 }
341 return type;
342#else
343 return self->db->get_type(self->db);
344#endif
345}
346
347
348/* Create a DBT structure (containing key and data values) from Python
349 strings. Returns 1 on success, 0 on an error. */
350static int make_dbt(PyObject* obj, DBT* dbt)
351{
352 CLEAR_DBT(*dbt);
353 if (obj == Py_None) {
354 /* no need to do anything, the structure has already been zeroed */
355 }
356 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
357 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000358 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000359 return 0;
360 }
361 return 1;
362}
363
364
365/* Recno and Queue DBs can have integer keys. This function figures out
366 what's been given, verifies that it's allowed, and then makes the DBT.
367
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000368 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000369static int
370make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371{
372 db_recno_t recno;
373 int type;
374
375 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000376 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000377 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000378 if (type == -1)
379 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000380 if (type == DB_RECNO || type == DB_QUEUE) {
381 PyErr_SetString(
382 PyExc_TypeError,
383 "None keys not allowed for Recno and Queue DB's");
384 return 0;
385 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 /* no need to do anything, the structure has already been zeroed */
387 }
388
389 else if (PyString_Check(keyobj)) {
390 /* verify access method type */
391 type = _DB_get_type(self);
392 if (type == -1)
393 return 0;
394 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000395 PyErr_SetString(
396 PyExc_TypeError,
397 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 return 0;
399 }
400
401 key->data = PyString_AS_STRING(keyobj);
402 key->size = PyString_GET_SIZE(keyobj);
403 }
404
405 else if (PyInt_Check(keyobj)) {
406 /* verify access method type */
407 type = _DB_get_type(self);
408 if (type == -1)
409 return 0;
410 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000411 /* if BTREE then an Integer key is allowed with the
412 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 *pflags |= DB_SET_RECNO;
414 }
415 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000416 PyErr_SetString(
417 PyExc_TypeError,
418 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000419 return 0;
420 }
421
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 /* Make a key out of the requested recno, use allocated space so DB
423 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000424 recno = PyInt_AS_LONG(keyobj);
425 key->data = malloc(sizeof(db_recno_t));
426 if (key->data == NULL) {
427 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
428 return 0;
429 }
430 key->ulen = key->size = sizeof(db_recno_t);
431 memcpy(key->data, &recno, sizeof(db_recno_t));
432 key->flags = DB_DBT_REALLOC;
433 }
434 else {
435 PyErr_Format(PyExc_TypeError,
436 "String or Integer object expected for key, %s found",
437 keyobj->ob_type->tp_name);
438 return 0;
439 }
440
441 return 1;
442}
443
444
445/* Add partial record access to an existing DBT data struct.
446 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
447 and the data storage/retrieval will be done using dlen and doff. */
448static int add_partial_dbt(DBT* d, int dlen, int doff) {
449 /* if neither were set we do nothing (-1 is the default value) */
450 if ((dlen == -1) && (doff == -1)) {
451 return 1;
452 }
453
454 if ((dlen < 0) || (doff < 0)) {
455 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
456 return 0;
457 }
458
459 d->flags = d->flags | DB_DBT_PARTIAL;
460 d->dlen = (unsigned int) dlen;
461 d->doff = (unsigned int) doff;
462 return 1;
463}
464
465
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000466/* Callback used to save away more information about errors from the DB
467 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000468static char _db_errmsg[1024];
469static void _db_errorCallback(const char* prefix, char* msg)
470{
471 strcpy(_db_errmsg, msg);
472}
473
474
475/* make a nice exception object to raise for errors. */
476static int makeDBError(int err)
477{
478 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000479 PyObject *errObj = NULL;
480 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000481 int exceptionRaised = 0;
482
483 switch (err) {
484 case 0: /* successful, no error */ break;
485
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000486#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000487 case DB_INCOMPLETE:
488#if INCOMPLETE_IS_WARNING
489 strcpy(errTxt, db_strerror(err));
490 if (_db_errmsg[0]) {
491 strcat(errTxt, " -- ");
492 strcat(errTxt, _db_errmsg);
493 _db_errmsg[0] = 0;
494 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000495#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000496 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
497#else
498 fprintf(stderr, errTxt);
499 fprintf(stderr, "\n");
500#endif
501
502#else /* do an exception instead */
503 errObj = DBIncompleteError;
504#endif
505 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000506#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000507
508 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
509 case DB_KEYEXIST: errObj = DBKeyExistError; break;
510 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
511 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
512 case DB_NOTFOUND: errObj = DBNotFoundError; break;
513 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
514 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
515 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
516 case DB_NOSERVER: errObj = DBNoServerError; break;
517 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
518 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
519#if (DBVER >= 33)
520 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
521 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
522#endif
523
524 case EINVAL: errObj = DBInvalidArgError; break;
525 case EACCES: errObj = DBAccessError; break;
526 case ENOSPC: errObj = DBNoSpaceError; break;
527 case ENOMEM: errObj = DBNoMemoryError; break;
528 case EAGAIN: errObj = DBAgainError; break;
529 case EBUSY : errObj = DBBusyError; break;
530 case EEXIST: errObj = DBFileExistsError; break;
531 case ENOENT: errObj = DBNoSuchFileError; break;
532 case EPERM : errObj = DBPermissionsError; break;
533
534 default: errObj = DBError; break;
535 }
536
537 if (errObj != NULL) {
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +0000538 /* FIXME this needs proper bounds checking on errTxt */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000539 strcpy(errTxt, db_strerror(err));
540 if (_db_errmsg[0]) {
541 strcat(errTxt, " -- ");
542 strcat(errTxt, _db_errmsg);
543 _db_errmsg[0] = 0;
544 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000545
546 errTuple = Py_BuildValue("(is)", err, errTxt);
547 PyErr_SetObject(errObj, errTuple);
548 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549 }
550
551 return ((errObj != NULL) || exceptionRaised);
552}
553
554
555
556/* set a type exception */
557static void makeTypeError(char* expected, PyObject* found)
558{
559 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
560 expected, found->ob_type->tp_name);
561}
562
563
564/* verify that an obj is either None or a DBTxn, and set the txn pointer */
565static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
566{
567 if (txnobj == Py_None || txnobj == NULL) {
568 *txn = NULL;
569 return 1;
570 }
571 if (DBTxnObject_Check(txnobj)) {
572 *txn = ((DBTxnObject*)txnobj)->txn;
573 return 1;
574 }
575 else
576 makeTypeError("DBTxn", txnobj);
577 return 0;
578}
579
580
581/* Delete a key from a database
582 Returns 0 on success, -1 on an error. */
583static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
584{
585 int err;
586
587 MYDB_BEGIN_ALLOW_THREADS;
588 err = self->db->del(self->db, txn, key, 0);
589 MYDB_END_ALLOW_THREADS;
590 if (makeDBError(err)) {
591 return -1;
592 }
593 self->haveStat = 0;
594 return 0;
595}
596
597
598/* Store a key into a database
599 Returns 0 on success, -1 on an error. */
600static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
601{
602 int err;
603
604 MYDB_BEGIN_ALLOW_THREADS;
605 err = self->db->put(self->db, txn, key, data, flags);
606 MYDB_END_ALLOW_THREADS;
607 if (makeDBError(err)) {
608 return -1;
609 }
610 self->haveStat = 0;
611 return 0;
612}
613
614/* Get a key/data pair from a cursor */
615static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
616 PyObject *args, PyObject *kwargs, char *format)
617{
618 int err;
619 PyObject* retval = NULL;
620 DBT key, data;
621 int dlen = -1;
622 int doff = -1;
623 int flags = 0;
624 char* kwnames[] = { "flags", "dlen", "doff", NULL };
625
626 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
627 &flags, &dlen, &doff))
628 return NULL;
629
630 CHECK_CURSOR_NOT_CLOSED(self);
631
632 flags |= extra_flags;
633 CLEAR_DBT(key);
634 CLEAR_DBT(data);
635 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
636 /* Tell BerkeleyDB to malloc the return value (thread safe) */
637 data.flags = DB_DBT_MALLOC;
638 key.flags = DB_DBT_MALLOC;
639 }
640 if (!add_partial_dbt(&data, dlen, doff))
641 return NULL;
642
643 MYDB_BEGIN_ALLOW_THREADS;
644 err = self->dbc->c_get(self->dbc, &key, &data, flags);
645 MYDB_END_ALLOW_THREADS;
646
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000647 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000648 Py_INCREF(Py_None);
649 retval = Py_None;
650 }
651 else if (makeDBError(err)) {
652 retval = NULL;
653 }
654 else { /* otherwise, success! */
655
656 /* if Recno or Queue, return the key as an Int */
657 switch (_DB_get_type(self->mydb)) {
658 case -1:
659 retval = NULL;
660 break;
661
662 case DB_RECNO:
663 case DB_QUEUE:
664 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
665 data.data, data.size);
666 break;
667 case DB_HASH:
668 case DB_BTREE:
669 default:
670 retval = Py_BuildValue("s#s#", key.data, key.size,
671 data.data, data.size);
672 break;
673 }
674 }
675 if (!err) {
676 FREE_DBT(key);
677 FREE_DBT(data);
678 }
679 return retval;
680}
681
682
683/* add an integer to a dictionary using the given name as a key */
684static void _addIntToDict(PyObject* dict, char *name, int value)
685{
686 PyObject* v = PyInt_FromLong((long) value);
687 if (!v || PyDict_SetItemString(dict, name, v))
688 PyErr_Clear();
689
690 Py_XDECREF(v);
691}
692
693
694
695
696/* --------------------------------------------------------------------- */
697/* Allocators and deallocators */
698
699static DBObject*
700newDBObject(DBEnvObject* arg, int flags)
701{
702 DBObject* self;
703 DB_ENV* db_env = NULL;
704 int err;
705
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000707 if (self == NULL)
708 return NULL;
709
710 self->haveStat = 0;
711 self->flags = 0;
712 self->setflags = 0;
713 self->myenvobj = NULL;
714#if (DBVER >= 33)
715 self->associateCallback = NULL;
716 self->primaryDBType = 0;
717#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000718#ifdef HAVE_WEAKREF
719 self->in_weakreflist = NULL;
720#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000721
722 /* keep a reference to our python DBEnv object */
723 if (arg) {
724 Py_INCREF(arg);
725 self->myenvobj = arg;
726 db_env = arg->db_env;
727 }
728
729 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000730 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000731 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000732 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
733 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000734
735 MYDB_BEGIN_ALLOW_THREADS;
736 err = db_create(&self->db, db_env, flags);
737 self->db->set_errcall(self->db, _db_errorCallback);
738#if (DBVER >= 33)
739 self->db->app_private = (void*)self;
740#endif
741 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000742 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
743 * list so that a DBEnv can refuse to close without aborting any open
744 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000745 if (makeDBError(err)) {
746 if (self->myenvobj) {
747 Py_DECREF(self->myenvobj);
748 self->myenvobj = NULL;
749 }
750 self = NULL;
751 }
752 return self;
753}
754
755
756static void
757DB_dealloc(DBObject* self)
758{
759 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000760 /* avoid closing a DB when its DBEnv has been closed out from under
761 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000763 (self->myenvobj && self->myenvobj->db_env))
764 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000765 MYDB_BEGIN_ALLOW_THREADS;
766 self->db->close(self->db, 0);
767 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000768#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769 } else {
770 PyErr_Warn(PyExc_RuntimeWarning,
771 "DB could not be closed in destructor: DBEnv already closed");
772#endif
773 }
774 self->db = NULL;
775 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000776#ifdef HAVE_WEAKREF
777 if (self->in_weakreflist != NULL) {
778 PyObject_ClearWeakRefs((PyObject *) self);
779 }
780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781 if (self->myenvobj) {
782 Py_DECREF(self->myenvobj);
783 self->myenvobj = NULL;
784 }
785#if (DBVER >= 33)
786 if (self->associateCallback != NULL) {
787 Py_DECREF(self->associateCallback);
788 self->associateCallback = NULL;
789 }
790#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000791 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000792}
793
794
795static DBCursorObject*
796newDBCursorObject(DBC* dbc, DBObject* db)
797{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000798 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799 if (self == NULL)
800 return NULL;
801
802 self->dbc = dbc;
803 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000804#ifdef HAVE_WEAKREF
805 self->in_weakreflist = NULL;
806#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000807 Py_INCREF(self->mydb);
808 return self;
809}
810
811
812static void
813DBCursor_dealloc(DBCursorObject* self)
814{
815 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000816
817#ifdef HAVE_WEAKREF
818 if (self->in_weakreflist != NULL) {
819 PyObject_ClearWeakRefs((PyObject *) self);
820 }
821#endif
822
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823 if (self->dbc != NULL) {
824 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000825 /* If the underlying database has been closed, we don't
826 need to do anything. If the environment has been closed
827 we need to leak, as BerkeleyDB will crash trying to access
828 the environment. There was an exception when the
829 user closed the environment even though there still was
830 a database open. */
831 if (self->mydb->db && self->mydb->myenvobj &&
832 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000833 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 self->dbc = NULL;
835 MYDB_END_ALLOW_THREADS;
836 }
837 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839}
840
841
842static DBEnvObject*
843newDBEnvObject(int flags)
844{
845 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000846 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 if (self == NULL)
848 return NULL;
849
850 self->closed = 1;
851 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000852 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
853 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000854#ifdef HAVE_WEAKREF
855 self->in_weakreflist = NULL;
856#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857
858 MYDB_BEGIN_ALLOW_THREADS;
859 err = db_env_create(&self->db_env, flags);
860 MYDB_END_ALLOW_THREADS;
861 if (makeDBError(err)) {
862 self = NULL;
863 }
864 else {
865 self->db_env->set_errcall(self->db_env, _db_errorCallback);
866 }
867 return self;
868}
869
870
871static void
872DBEnv_dealloc(DBEnvObject* self)
873{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000874#ifdef HAVE_WEAKREF
875 if (self->in_weakreflist != NULL) {
876 PyObject_ClearWeakRefs((PyObject *) self);
877 }
878#endif
879
Neal Norwitz37b0c1d2004-07-09 23:33:06 +0000880 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881 MYDB_BEGIN_ALLOW_THREADS;
882 self->db_env->close(self->db_env, 0);
883 MYDB_END_ALLOW_THREADS;
884 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000886}
887
888
889static DBTxnObject*
890newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
891{
892 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000893 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894 if (self == NULL)
895 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000896#ifdef HAVE_WEAKREF
897 self->in_weakreflist = NULL;
898#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899
900 MYDB_BEGIN_ALLOW_THREADS;
901#if (DBVER >= 40)
902 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
903#else
904 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
905#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000906 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
907 * list so that a DBEnv can refuse to close without aborting any open
908 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909 MYDB_END_ALLOW_THREADS;
910 if (makeDBError(err)) {
911 self = NULL;
912 }
913 return self;
914}
915
916
917static void
918DBTxn_dealloc(DBTxnObject* self)
919{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000920#ifdef HAVE_WEAKREF
921 if (self->in_weakreflist != NULL) {
922 PyObject_ClearWeakRefs((PyObject *) self);
923 }
924#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000925
Gregory P. Smith31c50652004-06-28 01:20:40 +0000926#ifdef HAVE_WARNINGS
927 if (self->txn) {
928 /* it hasn't been finalized, abort it! */
929 MYDB_BEGIN_ALLOW_THREADS;
930#if (DBVER >= 40)
931 self->txn->abort(self->txn);
932#else
933 txn_abort(self->txn);
934#endif
935 MYDB_END_ALLOW_THREADS;
936 PyErr_Warn(PyExc_RuntimeWarning,
937 "DBTxn aborted in destructor. No prior commit() or abort().");
938 }
939#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942}
943
944
945static DBLockObject*
946newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
947 db_lockmode_t lock_mode, int flags)
948{
949 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000950 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 if (self == NULL)
952 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000953#ifdef HAVE_WEAKREF
954 self->in_weakreflist = NULL;
955#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956
957 MYDB_BEGIN_ALLOW_THREADS;
958#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000959 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
960 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000961#else
962 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
963#endif
964 MYDB_END_ALLOW_THREADS;
965 if (makeDBError(err)) {
966 self = NULL;
967 }
968
969 return self;
970}
971
972
973static void
974DBLock_dealloc(DBLockObject* self)
975{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000976#ifdef HAVE_WEAKREF
977 if (self->in_weakreflist != NULL) {
978 PyObject_ClearWeakRefs((PyObject *) self);
979 }
980#endif
981 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000984}
985
986
987/* --------------------------------------------------------------------- */
988/* DB methods */
989
990static PyObject*
991DB_append(DBObject* self, PyObject* args)
992{
993 PyObject* txnobj = NULL;
994 PyObject* dataobj;
995 db_recno_t recno;
996 DBT key, data;
997 DB_TXN *txn = NULL;
998
999 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1000 return NULL;
1001
1002 CHECK_DB_NOT_CLOSED(self);
1003
1004 /* make a dummy key out of a recno */
1005 recno = 0;
1006 CLEAR_DBT(key);
1007 key.data = &recno;
1008 key.size = sizeof(recno);
1009 key.ulen = key.size;
1010 key.flags = DB_DBT_USERMEM;
1011
1012 if (!make_dbt(dataobj, &data)) return NULL;
1013 if (!checkTxnObj(txnobj, &txn)) return NULL;
1014
1015 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1016 return NULL;
1017
1018 return PyInt_FromLong(recno);
1019}
1020
1021
1022#if (DBVER >= 33)
1023
1024static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001025_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1026 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001027{
1028 int retval = DB_DONOTINDEX;
1029 DBObject* secondaryDB = (DBObject*)db->app_private;
1030 PyObject* callback = secondaryDB->associateCallback;
1031 int type = secondaryDB->primaryDBType;
1032 PyObject* key;
1033 PyObject* data;
1034 PyObject* args;
1035 PyObject* result;
1036
1037
1038 if (callback != NULL) {
1039 MYDB_BEGIN_BLOCK_THREADS;
1040
1041 if (type == DB_RECNO || type == DB_QUEUE) {
1042 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1043 }
1044 else {
1045 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1046 }
1047 data = PyString_FromStringAndSize(priData->data, priData->size);
1048 args = PyTuple_New(2);
1049 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1050 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1051
1052 result = PyEval_CallObject(callback, args);
1053
1054 if (result == NULL) {
1055 PyErr_Print();
1056 }
1057 else if (result == Py_None) {
1058 retval = DB_DONOTINDEX;
1059 }
1060 else if (PyInt_Check(result)) {
1061 retval = PyInt_AsLong(result);
1062 }
1063 else if (PyString_Check(result)) {
1064 char* data;
1065 int size;
1066
1067 CLEAR_DBT(*secKey);
1068#if PYTHON_API_VERSION <= 1007
1069 /* 1.5 compatibility */
1070 size = PyString_Size(result);
1071 data = PyString_AsString(result);
1072#else
1073 PyString_AsStringAndSize(result, &data, &size);
1074#endif
1075 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1076 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001077 if (secKey->data) {
1078 memcpy(secKey->data, data, size);
1079 secKey->size = size;
1080 retval = 0;
1081 }
1082 else {
1083 PyErr_SetString(PyExc_MemoryError,
1084 "malloc failed in _db_associateCallback");
1085 PyErr_Print();
1086 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001087 }
1088 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001089 PyErr_SetString(
1090 PyExc_TypeError,
1091 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001092 PyErr_Print();
1093 }
1094
1095 Py_DECREF(args);
1096 if (result) {
1097 Py_DECREF(result);
1098 }
1099
1100 MYDB_END_BLOCK_THREADS;
1101 }
1102 return retval;
1103}
1104
1105
1106static PyObject*
1107DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1108{
1109 int err, flags=0;
1110 DBObject* secondaryDB;
1111 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001112#if (DBVER >= 41)
1113 PyObject *txnobj = NULL;
1114 DB_TXN *txn = NULL;
1115 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1116#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001117 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001118#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001119
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001120#if (DBVER >= 41)
1121 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1122 &secondaryDB, &callback, &flags,
1123 &txnobj)) {
1124#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001126 &secondaryDB, &callback, &flags)) {
1127#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001129 }
1130
1131#if (DBVER >= 41)
1132 if (!checkTxnObj(txnobj, &txn)) return NULL;
1133#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001134
1135 CHECK_DB_NOT_CLOSED(self);
1136 if (!DBObject_Check(secondaryDB)) {
1137 makeTypeError("DB", (PyObject*)secondaryDB);
1138 return NULL;
1139 }
1140 if (callback == Py_None) {
1141 callback = NULL;
1142 }
1143 else if (!PyCallable_Check(callback)) {
1144 makeTypeError("Callable", callback);
1145 return NULL;
1146 }
1147
1148 /* Save a reference to the callback in the secondary DB. */
1149 if (self->associateCallback != NULL) {
1150 Py_DECREF(self->associateCallback);
1151 }
1152 Py_INCREF(callback);
1153 secondaryDB->associateCallback = callback;
1154 secondaryDB->primaryDBType = _DB_get_type(self);
1155
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001156 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1157 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1158 * The global interepreter lock is not initialized until the first
1159 * thread is created using thread.start_new_thread() or fork() is
1160 * called. that would cause the ALLOW_THREADS here to segfault due
1161 * to a null pointer reference if no threads or child processes
1162 * have been created. This works around that and is a no-op if
1163 * threads have already been initialized.
1164 * (see pybsddb-users mailing list post on 2002-08-07)
1165 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001166#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001167 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001168#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001170#if (DBVER >= 41)
1171 err = self->db->associate(self->db,
1172 txn,
1173 secondaryDB->db,
1174 _db_associateCallback,
1175 flags);
1176#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001177 err = self->db->associate(self->db,
1178 secondaryDB->db,
1179 _db_associateCallback,
1180 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001181#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001182 MYDB_END_ALLOW_THREADS;
1183
1184 if (err) {
1185 Py_DECREF(self->associateCallback);
1186 self->associateCallback = NULL;
1187 secondaryDB->primaryDBType = 0;
1188 }
1189
1190 RETURN_IF_ERR();
1191 RETURN_NONE();
1192}
1193
1194
1195#endif
1196
1197
1198static PyObject*
1199DB_close(DBObject* self, PyObject* args)
1200{
1201 int err, flags=0;
1202 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1203 return NULL;
1204 if (self->db != NULL) {
1205 if (self->myenvobj)
1206 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001208 self->db = NULL;
1209 RETURN_IF_ERR();
1210 }
1211 RETURN_NONE();
1212}
1213
1214
1215#if (DBVER >= 32)
1216static PyObject*
1217_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1218{
1219 int err, flags=0, type;
1220 PyObject* txnobj = NULL;
1221 PyObject* retval = NULL;
1222 DBT key, data;
1223 DB_TXN *txn = NULL;
1224 char* kwnames[] = { "txn", "flags", NULL };
1225
1226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1227 &txnobj, &flags))
1228 return NULL;
1229
1230 CHECK_DB_NOT_CLOSED(self);
1231 type = _DB_get_type(self);
1232 if (type == -1)
1233 return NULL;
1234 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235 PyErr_SetString(PyExc_TypeError,
1236 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237 return NULL;
1238 }
1239 if (!checkTxnObj(txnobj, &txn))
1240 return NULL;
1241
1242 CLEAR_DBT(key);
1243 CLEAR_DBT(data);
1244 if (CHECK_DBFLAG(self, DB_THREAD)) {
1245 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1246 data.flags = DB_DBT_MALLOC;
1247 key.flags = DB_DBT_MALLOC;
1248 }
1249
1250 MYDB_BEGIN_ALLOW_THREADS;
1251 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1252 MYDB_END_ALLOW_THREADS;
1253
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001254 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001255 err = 0;
1256 Py_INCREF(Py_None);
1257 retval = Py_None;
1258 }
1259 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001260 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1261 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001262 FREE_DBT(key);
1263 FREE_DBT(data);
1264 }
1265
1266 RETURN_IF_ERR();
1267 return retval;
1268}
1269
1270static PyObject*
1271DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1272{
1273 return _DB_consume(self, args, kwargs, DB_CONSUME);
1274}
1275
1276static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001277DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1278 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001279{
1280 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1281}
1282#endif
1283
1284
1285
1286static PyObject*
1287DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1288{
1289 int err, flags=0;
1290 DBC* dbc;
1291 PyObject* txnobj = NULL;
1292 DB_TXN *txn = NULL;
1293 char* kwnames[] = { "txn", "flags", NULL };
1294
1295 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1296 &txnobj, &flags))
1297 return NULL;
1298 CHECK_DB_NOT_CLOSED(self);
1299 if (!checkTxnObj(txnobj, &txn))
1300 return NULL;
1301
1302 MYDB_BEGIN_ALLOW_THREADS;
1303 err = self->db->cursor(self->db, txn, &dbc, flags);
1304 MYDB_END_ALLOW_THREADS;
1305 RETURN_IF_ERR();
1306 return (PyObject*) newDBCursorObject(dbc, self);
1307}
1308
1309
1310static PyObject*
1311DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1312{
1313 PyObject* txnobj = NULL;
1314 int flags = 0;
1315 PyObject* keyobj;
1316 DBT key;
1317 DB_TXN *txn = NULL;
1318 char* kwnames[] = { "key", "txn", "flags", NULL };
1319
1320 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1321 &keyobj, &txnobj, &flags))
1322 return NULL;
1323 CHECK_DB_NOT_CLOSED(self);
1324 if (!make_key_dbt(self, keyobj, &key, NULL))
1325 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001326 if (!checkTxnObj(txnobj, &txn)) {
1327 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001328 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001329 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001330
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001331 if (-1 == _DB_delete(self, txn, &key, 0)) {
1332 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001334 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001335
1336 FREE_DBT(key);
1337 RETURN_NONE();
1338}
1339
1340
1341static PyObject*
1342DB_fd(DBObject* self, PyObject* args)
1343{
1344 int err, the_fd;
1345
1346 if (!PyArg_ParseTuple(args,":fd"))
1347 return NULL;
1348 CHECK_DB_NOT_CLOSED(self);
1349
1350 MYDB_BEGIN_ALLOW_THREADS;
1351 err = self->db->fd(self->db, &the_fd);
1352 MYDB_END_ALLOW_THREADS;
1353 RETURN_IF_ERR();
1354 return PyInt_FromLong(the_fd);
1355}
1356
1357
1358static PyObject*
1359DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1360{
1361 int err, flags=0;
1362 PyObject* txnobj = NULL;
1363 PyObject* keyobj;
1364 PyObject* dfltobj = NULL;
1365 PyObject* retval = NULL;
1366 int dlen = -1;
1367 int doff = -1;
1368 DBT key, data;
1369 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001370 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371
1372 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001373 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1374 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001375 return NULL;
1376
1377 CHECK_DB_NOT_CLOSED(self);
1378 if (!make_key_dbt(self, keyobj, &key, &flags))
1379 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001380 if (!checkTxnObj(txnobj, &txn)) {
1381 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001382 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001383 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001384
1385 CLEAR_DBT(data);
1386 if (CHECK_DBFLAG(self, DB_THREAD)) {
1387 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1388 data.flags = DB_DBT_MALLOC;
1389 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001390 if (!add_partial_dbt(&data, dlen, doff)) {
1391 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001394
1395 MYDB_BEGIN_ALLOW_THREADS;
1396 err = self->db->get(self->db, txn, &key, &data, flags);
1397 MYDB_END_ALLOW_THREADS;
1398
1399 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1400 err = 0;
1401 Py_INCREF(dfltobj);
1402 retval = dfltobj;
1403 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001404 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405 err = 0;
1406 Py_INCREF(Py_None);
1407 retval = Py_None;
1408 }
1409 else if (!err) {
1410 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001411 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1412 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001413 else /* return just the data */
1414 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001415 FREE_DBT(data);
1416 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001417 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001418
1419 RETURN_IF_ERR();
1420 return retval;
1421}
1422
Gregory P. Smith19699a92004-06-28 04:06:49 +00001423static PyObject*
1424DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1425{
1426 int err, flags=0;
1427 PyObject* txnobj = NULL;
1428 PyObject* keyobj;
1429 PyObject* dfltobj = NULL;
1430 PyObject* retval = NULL;
1431 int dlen = -1;
1432 int doff = -1;
1433 DBT key, pkey, data;
1434 DB_TXN *txn = NULL;
1435 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1438 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1439 &doff))
1440 return NULL;
1441
1442 CHECK_DB_NOT_CLOSED(self);
1443 if (!make_key_dbt(self, keyobj, &key, &flags))
1444 return NULL;
1445 if (!checkTxnObj(txnobj, &txn)) {
1446 FREE_DBT(key);
1447 return NULL;
1448 }
1449
1450 CLEAR_DBT(data);
1451 if (CHECK_DBFLAG(self, DB_THREAD)) {
1452 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1453 data.flags = DB_DBT_MALLOC;
1454 }
1455 if (!add_partial_dbt(&data, dlen, doff)) {
1456 FREE_DBT(key);
1457 return NULL;
1458 }
1459
1460 CLEAR_DBT(pkey);
1461 pkey.flags = DB_DBT_MALLOC;
1462
1463 MYDB_BEGIN_ALLOW_THREADS;
1464 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1465 MYDB_END_ALLOW_THREADS;
1466
1467 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1468 err = 0;
1469 Py_INCREF(dfltobj);
1470 retval = dfltobj;
1471 }
1472 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1473 err = 0;
1474 Py_INCREF(Py_None);
1475 retval = Py_None;
1476 }
1477 else if (!err) {
1478 PyObject *pkeyObj;
1479 PyObject *dataObj;
1480 dataObj = PyString_FromStringAndSize(data.data, data.size);
1481
1482 if (self->primaryDBType == DB_RECNO ||
1483 self->primaryDBType == DB_QUEUE)
1484 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1485 else
1486 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1487
1488 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1489 {
1490 PyObject *keyObj;
1491 int type = _DB_get_type(self);
1492 if (type == DB_RECNO || type == DB_QUEUE)
1493 keyObj = PyInt_FromLong(*(long *)key.data);
1494 else
1495 keyObj = PyString_FromStringAndSize(key.data, key.size);
1496 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1497 }
1498 else /* return just the pkey and data */
1499 {
1500 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1501 }
1502 FREE_DBT(pkey);
1503 FREE_DBT(data);
1504 }
1505 FREE_DBT(key);
1506
1507 RETURN_IF_ERR();
1508 return retval;
1509}
1510
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511
1512/* Return size of entry */
1513static PyObject*
1514DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1515{
1516 int err, flags=0;
1517 PyObject* txnobj = NULL;
1518 PyObject* keyobj;
1519 PyObject* retval = NULL;
1520 DBT key, data;
1521 DB_TXN *txn = NULL;
1522 char* kwnames[] = { "key", "txn", NULL };
1523
1524 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1525 &keyobj, &txnobj))
1526 return NULL;
1527 CHECK_DB_NOT_CLOSED(self);
1528 if (!make_key_dbt(self, keyobj, &key, &flags))
1529 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001530 if (!checkTxnObj(txnobj, &txn)) {
1531 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001533 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001534 CLEAR_DBT(data);
1535
1536 /* We don't allocate any memory, forcing a ENOMEM error and thus
1537 getting the record size. */
1538 data.flags = DB_DBT_USERMEM;
1539 data.ulen = 0;
1540 MYDB_BEGIN_ALLOW_THREADS;
1541 err = self->db->get(self->db, txn, &key, &data, flags);
1542 MYDB_END_ALLOW_THREADS;
1543 if (err == ENOMEM) {
1544 retval = PyInt_FromLong((long)data.size);
1545 err = 0;
1546 }
1547
1548 FREE_DBT(key);
1549 FREE_DBT(data);
1550 RETURN_IF_ERR();
1551 return retval;
1552}
1553
1554
1555static PyObject*
1556DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1557{
1558 int err, flags=0;
1559 PyObject* txnobj = NULL;
1560 PyObject* keyobj;
1561 PyObject* dataobj;
1562 PyObject* retval = NULL;
1563 DBT key, data;
1564 DB_TXN *txn = NULL;
1565 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1566
1567
1568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1569 &keyobj, &dataobj, &txnobj, &flags))
1570 return NULL;
1571
1572 CHECK_DB_NOT_CLOSED(self);
1573 if (!make_key_dbt(self, keyobj, &key, NULL))
1574 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001575 if ( !make_dbt(dataobj, &data) ||
1576 !checkTxnObj(txnobj, &txn) )
1577 {
1578 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001579 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001580 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001581
1582 flags |= DB_GET_BOTH;
1583
1584 if (CHECK_DBFLAG(self, DB_THREAD)) {
1585 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1586 data.flags = DB_DBT_MALLOC;
1587 /* TODO: Is this flag needed? We're passing a data object that should
1588 match what's in the DB, so there should be no need to malloc.
1589 We run the risk of freeing something twice! Check this. */
1590 }
1591
1592 MYDB_BEGIN_ALLOW_THREADS;
1593 err = self->db->get(self->db, txn, &key, &data, flags);
1594 MYDB_END_ALLOW_THREADS;
1595
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001596 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001597 err = 0;
1598 Py_INCREF(Py_None);
1599 retval = Py_None;
1600 }
1601 else if (!err) {
1602 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1603 FREE_DBT(data); /* Only if retrieval was successful */
1604 }
1605
1606 FREE_DBT(key);
1607 RETURN_IF_ERR();
1608 return retval;
1609}
1610
1611
1612static PyObject*
1613DB_get_byteswapped(DBObject* self, PyObject* args)
1614{
1615#if (DBVER >= 33)
1616 int err = 0;
1617#endif
1618 int retval = -1;
1619
1620 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1621 return NULL;
1622 CHECK_DB_NOT_CLOSED(self);
1623
1624#if (DBVER >= 33)
1625 MYDB_BEGIN_ALLOW_THREADS;
1626 err = self->db->get_byteswapped(self->db, &retval);
1627 MYDB_END_ALLOW_THREADS;
1628 RETURN_IF_ERR();
1629#else
1630 MYDB_BEGIN_ALLOW_THREADS;
1631 retval = self->db->get_byteswapped(self->db);
1632 MYDB_END_ALLOW_THREADS;
1633#endif
1634 return PyInt_FromLong(retval);
1635}
1636
1637
1638static PyObject*
1639DB_get_type(DBObject* self, PyObject* args)
1640{
1641 int type;
1642
1643 if (!PyArg_ParseTuple(args,":get_type"))
1644 return NULL;
1645 CHECK_DB_NOT_CLOSED(self);
1646
1647 MYDB_BEGIN_ALLOW_THREADS;
1648 type = _DB_get_type(self);
1649 MYDB_END_ALLOW_THREADS;
1650 if (type == -1)
1651 return NULL;
1652 return PyInt_FromLong(type);
1653}
1654
1655
1656static PyObject*
1657DB_join(DBObject* self, PyObject* args)
1658{
1659 int err, flags=0;
1660 int length, x;
1661 PyObject* cursorsObj;
1662 DBC** cursors;
1663 DBC* dbc;
1664
1665
1666 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1667 return NULL;
1668
1669 CHECK_DB_NOT_CLOSED(self);
1670
1671 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001672 PyErr_SetString(PyExc_TypeError,
1673 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001674 return NULL;
1675 }
1676
1677 length = PyObject_Length(cursorsObj);
1678 cursors = malloc((length+1) * sizeof(DBC*));
1679 cursors[length] = NULL;
1680 for (x=0; x<length; x++) {
1681 PyObject* item = PySequence_GetItem(cursorsObj, x);
1682 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001683 PyErr_SetString(PyExc_TypeError,
1684 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685 free(cursors);
1686 return NULL;
1687 }
1688 cursors[x] = ((DBCursorObject*)item)->dbc;
1689 }
1690
1691 MYDB_BEGIN_ALLOW_THREADS;
1692 err = self->db->join(self->db, cursors, &dbc, flags);
1693 MYDB_END_ALLOW_THREADS;
1694 free(cursors);
1695 RETURN_IF_ERR();
1696
Gregory P. Smith7441e652003-11-03 21:35:31 +00001697 /* FIXME: this is a buggy interface. The returned cursor
1698 contains internal references to the passed in cursors
1699 but does not hold python references to them or prevent
1700 them from being closed prematurely. This can cause
1701 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001702 return (PyObject*) newDBCursorObject(dbc, self);
1703}
1704
1705
1706static PyObject*
1707DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1708{
1709 int err, flags=0;
1710 PyObject* txnobj = NULL;
1711 PyObject* keyobj;
1712 DBT key;
1713 DB_TXN *txn = NULL;
1714 DB_KEY_RANGE range;
1715 char* kwnames[] = { "key", "txn", "flags", NULL };
1716
1717 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1718 &keyobj, &txnobj, &flags))
1719 return NULL;
1720 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001721 if (!make_dbt(keyobj, &key))
1722 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 return NULL;
1724 if (!checkTxnObj(txnobj, &txn))
1725 return NULL;
1726
1727 MYDB_BEGIN_ALLOW_THREADS;
1728 err = self->db->key_range(self->db, txn, &key, &range, flags);
1729 MYDB_END_ALLOW_THREADS;
1730
1731 RETURN_IF_ERR();
1732 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1733}
1734
1735
1736static PyObject*
1737DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1738{
1739 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1740 char* filename = NULL;
1741 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001742#if (DBVER >= 41)
1743 PyObject *txnobj = NULL;
1744 DB_TXN *txn = NULL;
1745 /* with dbname */
1746 char* kwnames[] = {
1747 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1748 /* without dbname */
1749 char* kwnames_basic[] = {
1750 "filename", "dbtype", "flags", "mode", "txn", NULL};
1751#else
1752 /* with dbname */
1753 char* kwnames[] = {
1754 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1755 /* without dbname */
1756 char* kwnames_basic[] = {
1757 "filename", "dbtype", "flags", "mode", NULL};
1758#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001759
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001760#if (DBVER >= 41)
1761 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1762 &filename, &dbname, &type, &flags, &mode,
1763 &txnobj))
1764#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001765 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001766 &filename, &dbname, &type, &flags,
1767 &mode))
1768#endif
1769 {
1770 PyErr_Clear();
1771 type = DB_UNKNOWN; flags = 0; mode = 0660;
1772 filename = NULL; dbname = NULL;
1773#if (DBVER >= 41)
1774 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1775 kwnames_basic,
1776 &filename, &type, &flags, &mode,
1777 &txnobj))
1778 return NULL;
1779#else
1780 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1781 kwnames_basic,
1782 &filename, &type, &flags, &mode))
1783 return NULL;
1784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001785 }
1786
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001787#if (DBVER >= 41)
1788 if (!checkTxnObj(txnobj, &txn)) return NULL;
1789#endif
1790
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001791 if (NULL == self->db) {
1792 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1793 "Cannot call open() twice for DB object"));
1794 return NULL;
1795 }
1796
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001797#if 0 && (DBVER >= 41)
1798 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1799 && (self->myenvobj->flags & DB_INIT_TXN))
1800 {
1801 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1802 * explicitly passed) but we are in a transaction ready environment:
1803 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1804 * to work on BerkeleyDB 4.1 without needing to modify their
1805 * DBEnv or DB open calls.
1806 * TODO make this behaviour of the library configurable.
1807 */
1808 flags |= DB_AUTO_COMMIT;
1809 }
1810#endif
1811
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001812 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001813#if (DBVER >= 41)
1814 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1815#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001817#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001818 MYDB_END_ALLOW_THREADS;
1819 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001820 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 self->db = NULL;
1822 return NULL;
1823 }
1824
1825 self->flags = flags;
1826 RETURN_NONE();
1827}
1828
1829
1830static PyObject*
1831DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1832{
1833 int flags=0;
1834 PyObject* txnobj = NULL;
1835 int dlen = -1;
1836 int doff = -1;
1837 PyObject* keyobj, *dataobj, *retval;
1838 DBT key, data;
1839 DB_TXN *txn = NULL;
1840 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1841
1842 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1843 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1844 return NULL;
1845
1846 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001847 if (!make_key_dbt(self, keyobj, &key, NULL))
1848 return NULL;
1849 if ( !make_dbt(dataobj, &data) ||
1850 !add_partial_dbt(&data, dlen, doff) ||
1851 !checkTxnObj(txnobj, &txn) )
1852 {
1853 FREE_DBT(key);
1854 return NULL;
1855 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856
1857 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1858 FREE_DBT(key);
1859 return NULL;
1860 }
1861
1862 if (flags & DB_APPEND)
1863 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1864 else {
1865 retval = Py_None;
1866 Py_INCREF(retval);
1867 }
1868 FREE_DBT(key);
1869 return retval;
1870}
1871
1872
1873
1874static PyObject*
1875DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1876{
1877 char* filename;
1878 char* database = NULL;
1879 int err, flags=0;
1880 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1881
1882 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1883 &filename, &database, &flags))
1884 return NULL;
1885 CHECK_DB_NOT_CLOSED(self);
1886
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001887 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001888 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001889 RETURN_IF_ERR();
1890 RETURN_NONE();
1891}
1892
1893
1894
1895static PyObject*
1896DB_rename(DBObject* self, PyObject* args)
1897{
1898 char* filename;
1899 char* database;
1900 char* newname;
1901 int err, flags=0;
1902
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001903 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1904 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001905 return NULL;
1906 CHECK_DB_NOT_CLOSED(self);
1907
1908 MYDB_BEGIN_ALLOW_THREADS;
1909 err = self->db->rename(self->db, filename, database, newname, flags);
1910 MYDB_END_ALLOW_THREADS;
1911 RETURN_IF_ERR();
1912 RETURN_NONE();
1913}
1914
1915
1916static PyObject*
1917DB_set_bt_minkey(DBObject* self, PyObject* args)
1918{
1919 int err, minkey;
1920
1921 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1922 return NULL;
1923 CHECK_DB_NOT_CLOSED(self);
1924
1925 MYDB_BEGIN_ALLOW_THREADS;
1926 err = self->db->set_bt_minkey(self->db, minkey);
1927 MYDB_END_ALLOW_THREADS;
1928 RETURN_IF_ERR();
1929 RETURN_NONE();
1930}
1931
1932
1933static PyObject*
1934DB_set_cachesize(DBObject* self, PyObject* args)
1935{
1936 int err;
1937 int gbytes = 0, bytes = 0, ncache = 0;
1938
1939 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1940 &gbytes,&bytes,&ncache))
1941 return NULL;
1942 CHECK_DB_NOT_CLOSED(self);
1943
1944 MYDB_BEGIN_ALLOW_THREADS;
1945 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1946 MYDB_END_ALLOW_THREADS;
1947 RETURN_IF_ERR();
1948 RETURN_NONE();
1949}
1950
1951
1952static PyObject*
1953DB_set_flags(DBObject* self, PyObject* args)
1954{
1955 int err, flags;
1956
1957 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1958 return NULL;
1959 CHECK_DB_NOT_CLOSED(self);
1960
1961 MYDB_BEGIN_ALLOW_THREADS;
1962 err = self->db->set_flags(self->db, flags);
1963 MYDB_END_ALLOW_THREADS;
1964 RETURN_IF_ERR();
1965
1966 self->setflags |= flags;
1967 RETURN_NONE();
1968}
1969
1970
1971static PyObject*
1972DB_set_h_ffactor(DBObject* self, PyObject* args)
1973{
1974 int err, ffactor;
1975
1976 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1977 return NULL;
1978 CHECK_DB_NOT_CLOSED(self);
1979
1980 MYDB_BEGIN_ALLOW_THREADS;
1981 err = self->db->set_h_ffactor(self->db, ffactor);
1982 MYDB_END_ALLOW_THREADS;
1983 RETURN_IF_ERR();
1984 RETURN_NONE();
1985}
1986
1987
1988static PyObject*
1989DB_set_h_nelem(DBObject* self, PyObject* args)
1990{
1991 int err, nelem;
1992
1993 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1994 return NULL;
1995 CHECK_DB_NOT_CLOSED(self);
1996
1997 MYDB_BEGIN_ALLOW_THREADS;
1998 err = self->db->set_h_nelem(self->db, nelem);
1999 MYDB_END_ALLOW_THREADS;
2000 RETURN_IF_ERR();
2001 RETURN_NONE();
2002}
2003
2004
2005static PyObject*
2006DB_set_lorder(DBObject* self, PyObject* args)
2007{
2008 int err, lorder;
2009
2010 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2011 return NULL;
2012 CHECK_DB_NOT_CLOSED(self);
2013
2014 MYDB_BEGIN_ALLOW_THREADS;
2015 err = self->db->set_lorder(self->db, lorder);
2016 MYDB_END_ALLOW_THREADS;
2017 RETURN_IF_ERR();
2018 RETURN_NONE();
2019}
2020
2021
2022static PyObject*
2023DB_set_pagesize(DBObject* self, PyObject* args)
2024{
2025 int err, pagesize;
2026
2027 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2028 return NULL;
2029 CHECK_DB_NOT_CLOSED(self);
2030
2031 MYDB_BEGIN_ALLOW_THREADS;
2032 err = self->db->set_pagesize(self->db, pagesize);
2033 MYDB_END_ALLOW_THREADS;
2034 RETURN_IF_ERR();
2035 RETURN_NONE();
2036}
2037
2038
2039static PyObject*
2040DB_set_re_delim(DBObject* self, PyObject* args)
2041{
2042 int err;
2043 char delim;
2044
2045 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2046 PyErr_Clear();
2047 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2048 return NULL;
2049 }
2050
2051 CHECK_DB_NOT_CLOSED(self);
2052
2053 MYDB_BEGIN_ALLOW_THREADS;
2054 err = self->db->set_re_delim(self->db, delim);
2055 MYDB_END_ALLOW_THREADS;
2056 RETURN_IF_ERR();
2057 RETURN_NONE();
2058}
2059
2060static PyObject*
2061DB_set_re_len(DBObject* self, PyObject* args)
2062{
2063 int err, len;
2064
2065 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2066 return NULL;
2067 CHECK_DB_NOT_CLOSED(self);
2068
2069 MYDB_BEGIN_ALLOW_THREADS;
2070 err = self->db->set_re_len(self->db, len);
2071 MYDB_END_ALLOW_THREADS;
2072 RETURN_IF_ERR();
2073 RETURN_NONE();
2074}
2075
2076
2077static PyObject*
2078DB_set_re_pad(DBObject* self, PyObject* args)
2079{
2080 int err;
2081 char pad;
2082
2083 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2084 PyErr_Clear();
2085 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2086 return NULL;
2087 }
2088 CHECK_DB_NOT_CLOSED(self);
2089
2090 MYDB_BEGIN_ALLOW_THREADS;
2091 err = self->db->set_re_pad(self->db, pad);
2092 MYDB_END_ALLOW_THREADS;
2093 RETURN_IF_ERR();
2094 RETURN_NONE();
2095}
2096
2097
2098static PyObject*
2099DB_set_re_source(DBObject* self, PyObject* args)
2100{
2101 int err;
2102 char *re_source;
2103
2104 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2105 return NULL;
2106 CHECK_DB_NOT_CLOSED(self);
2107
2108 MYDB_BEGIN_ALLOW_THREADS;
2109 err = self->db->set_re_source(self->db, re_source);
2110 MYDB_END_ALLOW_THREADS;
2111 RETURN_IF_ERR();
2112 RETURN_NONE();
2113}
2114
2115
2116#if (DBVER >= 32)
2117static PyObject*
2118DB_set_q_extentsize(DBObject* self, PyObject* args)
2119{
2120 int err;
2121 int extentsize;
2122
2123 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2124 return NULL;
2125 CHECK_DB_NOT_CLOSED(self);
2126
2127 MYDB_BEGIN_ALLOW_THREADS;
2128 err = self->db->set_q_extentsize(self->db, extentsize);
2129 MYDB_END_ALLOW_THREADS;
2130 RETURN_IF_ERR();
2131 RETURN_NONE();
2132}
2133#endif
2134
2135static PyObject*
2136DB_stat(DBObject* self, PyObject* args)
2137{
2138 int err, flags = 0, type;
2139 void* sp;
2140 PyObject* d;
2141
2142
2143 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2144 return NULL;
2145 CHECK_DB_NOT_CLOSED(self);
2146
2147 MYDB_BEGIN_ALLOW_THREADS;
2148#if (DBVER >= 33)
2149 err = self->db->stat(self->db, &sp, flags);
2150#else
2151 err = self->db->stat(self->db, &sp, NULL, flags);
2152#endif
2153 MYDB_END_ALLOW_THREADS;
2154 RETURN_IF_ERR();
2155
2156 self->haveStat = 1;
2157
2158 /* Turn the stat structure into a dictionary */
2159 type = _DB_get_type(self);
2160 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2161 free(sp);
2162 return NULL;
2163 }
2164
2165#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2166#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2167#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2168
2169 switch (type) {
2170 case DB_HASH:
2171 MAKE_HASH_ENTRY(magic);
2172 MAKE_HASH_ENTRY(version);
2173 MAKE_HASH_ENTRY(nkeys);
2174 MAKE_HASH_ENTRY(ndata);
2175 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002176#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002177 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002178#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002179 MAKE_HASH_ENTRY(ffactor);
2180 MAKE_HASH_ENTRY(buckets);
2181 MAKE_HASH_ENTRY(free);
2182 MAKE_HASH_ENTRY(bfree);
2183 MAKE_HASH_ENTRY(bigpages);
2184 MAKE_HASH_ENTRY(big_bfree);
2185 MAKE_HASH_ENTRY(overflows);
2186 MAKE_HASH_ENTRY(ovfl_free);
2187 MAKE_HASH_ENTRY(dup);
2188 MAKE_HASH_ENTRY(dup_free);
2189 break;
2190
2191 case DB_BTREE:
2192 case DB_RECNO:
2193 MAKE_BT_ENTRY(magic);
2194 MAKE_BT_ENTRY(version);
2195 MAKE_BT_ENTRY(nkeys);
2196 MAKE_BT_ENTRY(ndata);
2197 MAKE_BT_ENTRY(pagesize);
2198 MAKE_BT_ENTRY(minkey);
2199 MAKE_BT_ENTRY(re_len);
2200 MAKE_BT_ENTRY(re_pad);
2201 MAKE_BT_ENTRY(levels);
2202 MAKE_BT_ENTRY(int_pg);
2203 MAKE_BT_ENTRY(leaf_pg);
2204 MAKE_BT_ENTRY(dup_pg);
2205 MAKE_BT_ENTRY(over_pg);
2206 MAKE_BT_ENTRY(free);
2207 MAKE_BT_ENTRY(int_pgfree);
2208 MAKE_BT_ENTRY(leaf_pgfree);
2209 MAKE_BT_ENTRY(dup_pgfree);
2210 MAKE_BT_ENTRY(over_pgfree);
2211 break;
2212
2213 case DB_QUEUE:
2214 MAKE_QUEUE_ENTRY(magic);
2215 MAKE_QUEUE_ENTRY(version);
2216 MAKE_QUEUE_ENTRY(nkeys);
2217 MAKE_QUEUE_ENTRY(ndata);
2218 MAKE_QUEUE_ENTRY(pagesize);
2219 MAKE_QUEUE_ENTRY(pages);
2220 MAKE_QUEUE_ENTRY(re_len);
2221 MAKE_QUEUE_ENTRY(re_pad);
2222 MAKE_QUEUE_ENTRY(pgfree);
2223#if (DBVER == 31)
2224 MAKE_QUEUE_ENTRY(start);
2225#endif
2226 MAKE_QUEUE_ENTRY(first_recno);
2227 MAKE_QUEUE_ENTRY(cur_recno);
2228 break;
2229
2230 default:
2231 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2232 Py_DECREF(d);
2233 d = NULL;
2234 }
2235
2236#undef MAKE_HASH_ENTRY
2237#undef MAKE_BT_ENTRY
2238#undef MAKE_QUEUE_ENTRY
2239
2240 free(sp);
2241 return d;
2242}
2243
2244static PyObject*
2245DB_sync(DBObject* self, PyObject* args)
2246{
2247 int err;
2248 int flags = 0;
2249
2250 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2251 return NULL;
2252 CHECK_DB_NOT_CLOSED(self);
2253
2254 MYDB_BEGIN_ALLOW_THREADS;
2255 err = self->db->sync(self->db, flags);
2256 MYDB_END_ALLOW_THREADS;
2257 RETURN_IF_ERR();
2258 RETURN_NONE();
2259}
2260
2261
2262#if (DBVER >= 33)
2263static PyObject*
2264DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2265{
2266 int err, flags=0;
2267 u_int32_t count=0;
2268 PyObject* txnobj = NULL;
2269 DB_TXN *txn = NULL;
2270 char* kwnames[] = { "txn", "flags", NULL };
2271
2272 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2273 &txnobj, &flags))
2274 return NULL;
2275 CHECK_DB_NOT_CLOSED(self);
2276 if (!checkTxnObj(txnobj, &txn))
2277 return NULL;
2278
2279 MYDB_BEGIN_ALLOW_THREADS;
2280 err = self->db->truncate(self->db, txn, &count, flags);
2281 MYDB_END_ALLOW_THREADS;
2282 RETURN_IF_ERR();
2283 return PyInt_FromLong(count);
2284}
2285#endif
2286
2287
2288static PyObject*
2289DB_upgrade(DBObject* self, PyObject* args)
2290{
2291 int err, flags=0;
2292 char *filename;
2293
2294 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2295 return NULL;
2296 CHECK_DB_NOT_CLOSED(self);
2297
2298 MYDB_BEGIN_ALLOW_THREADS;
2299 err = self->db->upgrade(self->db, filename, flags);
2300 MYDB_END_ALLOW_THREADS;
2301 RETURN_IF_ERR();
2302 RETURN_NONE();
2303}
2304
2305
2306static PyObject*
2307DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2308{
2309 int err, flags=0;
2310 char* fileName;
2311 char* dbName=NULL;
2312 char* outFileName=NULL;
2313 FILE* outFile=NULL;
2314 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2315
2316 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2317 &fileName, &dbName, &outFileName, &flags))
2318 return NULL;
2319
2320 CHECK_DB_NOT_CLOSED(self);
2321 if (outFileName)
2322 outFile = fopen(outFileName, "w");
2323
2324 MYDB_BEGIN_ALLOW_THREADS;
2325 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2326 MYDB_END_ALLOW_THREADS;
2327 if (outFileName)
2328 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002329
2330 /* DB.verify acts as a DB handle destructor (like close); this was
2331 * documented in BerkeleyDB 4.2 but had the undocumented effect
2332 * of not being safe in prior versions while still requiring an explicit
2333 * DB.close call afterwards. Lets call close for the user to emulate
2334 * the safe 4.2 behaviour. */
2335#if (DBVER <= 41)
2336 self->db->close(self->db, 0);
2337#endif
2338 self->db = NULL;
2339
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002340 RETURN_IF_ERR();
2341 RETURN_NONE();
2342}
2343
2344
2345static PyObject*
2346DB_set_get_returns_none(DBObject* self, PyObject* args)
2347{
2348 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002349 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002350
2351 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2352 return NULL;
2353 CHECK_DB_NOT_CLOSED(self);
2354
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002355 if (self->moduleFlags.getReturnsNone)
2356 ++oldValue;
2357 if (self->moduleFlags.cursorSetReturnsNone)
2358 ++oldValue;
2359 self->moduleFlags.getReturnsNone = (flags >= 1);
2360 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002361 return PyInt_FromLong(oldValue);
2362}
2363
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002364#if (DBVER >= 41)
2365static PyObject*
2366DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2367{
2368 int err;
2369 u_int32_t flags=0;
2370 char *passwd = NULL;
2371 char* kwnames[] = { "passwd", "flags", NULL };
2372
2373 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2374 &passwd, &flags)) {
2375 return NULL;
2376 }
2377
2378 MYDB_BEGIN_ALLOW_THREADS;
2379 err = self->db->set_encrypt(self->db, passwd, flags);
2380 MYDB_END_ALLOW_THREADS;
2381
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2384}
2385#endif /* DBVER >= 41 */
2386
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002387
2388/*-------------------------------------------------------------- */
2389/* Mapping and Dictionary-like access routines */
2390
2391int DB_length(DBObject* self)
2392{
2393 int err;
2394 long size = 0;
2395 int flags = 0;
2396 void* sp;
2397
2398 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002399 PyErr_SetObject(DBError,
2400 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002401 return -1;
2402 }
2403
2404 if (self->haveStat) { /* Has the stat function been called recently? If
2405 so, we can use the cached value. */
2406 flags = DB_CACHED_COUNTS;
2407 }
2408
2409 MYDB_BEGIN_ALLOW_THREADS;
2410#if (DBVER >= 33)
2411 err = self->db->stat(self->db, &sp, flags);
2412#else
2413 err = self->db->stat(self->db, &sp, NULL, flags);
2414#endif
2415 MYDB_END_ALLOW_THREADS;
2416
2417 if (err)
2418 return -1;
2419
2420 self->haveStat = 1;
2421
2422 /* All the stat structures have matching fields upto the ndata field,
2423 so we can use any of them for the type cast */
2424 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2425 free(sp);
2426 return size;
2427}
2428
2429
2430PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2431{
2432 int err;
2433 PyObject* retval;
2434 DBT key;
2435 DBT data;
2436
2437 CHECK_DB_NOT_CLOSED(self);
2438 if (!make_key_dbt(self, keyobj, &key, NULL))
2439 return NULL;
2440
2441 CLEAR_DBT(data);
2442 if (CHECK_DBFLAG(self, DB_THREAD)) {
2443 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2444 data.flags = DB_DBT_MALLOC;
2445 }
2446 MYDB_BEGIN_ALLOW_THREADS;
2447 err = self->db->get(self->db, NULL, &key, &data, 0);
2448 MYDB_END_ALLOW_THREADS;
2449 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2450 PyErr_SetObject(PyExc_KeyError, keyobj);
2451 retval = NULL;
2452 }
2453 else if (makeDBError(err)) {
2454 retval = NULL;
2455 }
2456 else {
2457 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2458 FREE_DBT(data);
2459 }
2460
2461 FREE_DBT(key);
2462 return retval;
2463}
2464
2465
2466static int
2467DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2468{
2469 DBT key, data;
2470 int retval;
2471 int flags = 0;
2472
2473 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002474 PyErr_SetObject(DBError,
2475 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002476 return -1;
2477 }
2478
2479 if (!make_key_dbt(self, keyobj, &key, NULL))
2480 return -1;
2481
2482 if (dataobj != NULL) {
2483 if (!make_dbt(dataobj, &data))
2484 retval = -1;
2485 else {
2486 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002487 /* dictionaries shouldn't have duplicate keys */
2488 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002489 retval = _DB_put(self, NULL, &key, &data, flags);
2490
2491 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002492 /* try deleting any old record that matches and then PUT it
2493 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002494 _DB_delete(self, NULL, &key, 0);
2495 PyErr_Clear();
2496 retval = _DB_put(self, NULL, &key, &data, flags);
2497 }
2498 }
2499 }
2500 else {
2501 /* dataobj == NULL, so delete the key */
2502 retval = _DB_delete(self, NULL, &key, 0);
2503 }
2504 FREE_DBT(key);
2505 return retval;
2506}
2507
2508
2509static PyObject*
2510DB_has_key(DBObject* self, PyObject* args)
2511{
2512 int err;
2513 PyObject* keyobj;
2514 DBT key, data;
2515 PyObject* txnobj = NULL;
2516 DB_TXN *txn = NULL;
2517
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002518 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002519 return NULL;
2520 CHECK_DB_NOT_CLOSED(self);
2521 if (!make_key_dbt(self, keyobj, &key, NULL))
2522 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002523 if (!checkTxnObj(txnobj, &txn)) {
2524 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002525 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002526 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002527
2528 /* This causes ENOMEM to be returned when the db has the key because
2529 it has a record but can't allocate a buffer for the data. This saves
2530 having to deal with data we won't be using.
2531 */
2532 CLEAR_DBT(data);
2533 data.flags = DB_DBT_USERMEM;
2534
2535 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002536 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002537 MYDB_END_ALLOW_THREADS;
2538 FREE_DBT(key);
2539 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2540}
2541
2542
2543#define _KEYS_LIST 1
2544#define _VALUES_LIST 2
2545#define _ITEMS_LIST 3
2546
2547static PyObject*
2548_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2549{
2550 int err, dbtype;
2551 DBT key;
2552 DBT data;
2553 DBC *cursor;
2554 PyObject* list;
2555 PyObject* item = NULL;
2556
2557 CHECK_DB_NOT_CLOSED(self);
2558 CLEAR_DBT(key);
2559 CLEAR_DBT(data);
2560
2561 dbtype = _DB_get_type(self);
2562 if (dbtype == -1)
2563 return NULL;
2564
2565 list = PyList_New(0);
2566 if (list == NULL) {
2567 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2568 return NULL;
2569 }
2570
2571 /* get a cursor */
2572 MYDB_BEGIN_ALLOW_THREADS;
2573 err = self->db->cursor(self->db, NULL, &cursor, 0);
2574 MYDB_END_ALLOW_THREADS;
2575 RETURN_IF_ERR();
2576
2577 if (CHECK_DBFLAG(self, DB_THREAD)) {
2578 key.flags = DB_DBT_REALLOC;
2579 data.flags = DB_DBT_REALLOC;
2580 }
2581
2582 while (1) { /* use the cursor to traverse the DB, collecting items */
2583 MYDB_BEGIN_ALLOW_THREADS;
2584 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2585 MYDB_END_ALLOW_THREADS;
2586
2587 if (err) {
2588 /* for any error, break out of the loop */
2589 break;
2590 }
2591
2592 switch (type) {
2593 case _KEYS_LIST:
2594 switch(dbtype) {
2595 case DB_BTREE:
2596 case DB_HASH:
2597 default:
2598 item = PyString_FromStringAndSize((char*)key.data, key.size);
2599 break;
2600 case DB_RECNO:
2601 case DB_QUEUE:
2602 item = PyInt_FromLong(*((db_recno_t*)key.data));
2603 break;
2604 }
2605 break;
2606
2607 case _VALUES_LIST:
2608 item = PyString_FromStringAndSize((char*)data.data, data.size);
2609 break;
2610
2611 case _ITEMS_LIST:
2612 switch(dbtype) {
2613 case DB_BTREE:
2614 case DB_HASH:
2615 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002616 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2617 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002618 break;
2619 case DB_RECNO:
2620 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002621 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2622 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002623 break;
2624 }
2625 break;
2626 }
2627 if (item == NULL) {
2628 Py_DECREF(list);
2629 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2630 list = NULL;
2631 goto done;
2632 }
2633 PyList_Append(list, item);
2634 Py_DECREF(item);
2635 }
2636
2637 /* DB_NOTFOUND is okay, it just means we got to the end */
2638 if (err != DB_NOTFOUND && makeDBError(err)) {
2639 Py_DECREF(list);
2640 list = NULL;
2641 }
2642
2643 done:
2644 FREE_DBT(key);
2645 FREE_DBT(data);
2646 MYDB_BEGIN_ALLOW_THREADS;
2647 cursor->c_close(cursor);
2648 MYDB_END_ALLOW_THREADS;
2649 return list;
2650}
2651
2652
2653static PyObject*
2654DB_keys(DBObject* self, PyObject* args)
2655{
2656 PyObject* txnobj = NULL;
2657 DB_TXN *txn = NULL;
2658
2659 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2660 return NULL;
2661 if (!checkTxnObj(txnobj, &txn))
2662 return NULL;
2663 return _DB_make_list(self, txn, _KEYS_LIST);
2664}
2665
2666
2667static PyObject*
2668DB_items(DBObject* self, PyObject* args)
2669{
2670 PyObject* txnobj = NULL;
2671 DB_TXN *txn = NULL;
2672
2673 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2674 return NULL;
2675 if (!checkTxnObj(txnobj, &txn))
2676 return NULL;
2677 return _DB_make_list(self, txn, _ITEMS_LIST);
2678}
2679
2680
2681static PyObject*
2682DB_values(DBObject* self, PyObject* args)
2683{
2684 PyObject* txnobj = NULL;
2685 DB_TXN *txn = NULL;
2686
2687 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2688 return NULL;
2689 if (!checkTxnObj(txnobj, &txn))
2690 return NULL;
2691 return _DB_make_list(self, txn, _VALUES_LIST);
2692}
2693
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002694/* --------------------------------------------------------------------- */
2695/* DBCursor methods */
2696
2697
2698static PyObject*
2699DBC_close(DBCursorObject* self, PyObject* args)
2700{
2701 int err = 0;
2702
2703 if (!PyArg_ParseTuple(args, ":close"))
2704 return NULL;
2705
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706 if (self->dbc != NULL) {
2707 MYDB_BEGIN_ALLOW_THREADS;
2708 err = self->dbc->c_close(self->dbc);
2709 self->dbc = NULL;
2710 MYDB_END_ALLOW_THREADS;
2711 }
2712 RETURN_IF_ERR();
2713 RETURN_NONE();
2714}
2715
2716
2717static PyObject*
2718DBC_count(DBCursorObject* self, PyObject* args)
2719{
2720 int err = 0;
2721 db_recno_t count;
2722 int flags = 0;
2723
2724 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2725 return NULL;
2726
2727 CHECK_CURSOR_NOT_CLOSED(self);
2728
2729 MYDB_BEGIN_ALLOW_THREADS;
2730 err = self->dbc->c_count(self->dbc, &count, flags);
2731 MYDB_END_ALLOW_THREADS;
2732 RETURN_IF_ERR();
2733
2734 return PyInt_FromLong(count);
2735}
2736
2737
2738static PyObject*
2739DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2740{
2741 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2742}
2743
2744
2745static PyObject*
2746DBC_delete(DBCursorObject* self, PyObject* args)
2747{
2748 int err, flags=0;
2749
2750 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2751 return NULL;
2752
2753 CHECK_CURSOR_NOT_CLOSED(self);
2754
2755 MYDB_BEGIN_ALLOW_THREADS;
2756 err = self->dbc->c_del(self->dbc, flags);
2757 MYDB_END_ALLOW_THREADS;
2758 RETURN_IF_ERR();
2759
2760 self->mydb->haveStat = 0;
2761 RETURN_NONE();
2762}
2763
2764
2765static PyObject*
2766DBC_dup(DBCursorObject* self, PyObject* args)
2767{
2768 int err, flags =0;
2769 DBC* dbc = NULL;
2770
2771 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2772 return NULL;
2773
2774 CHECK_CURSOR_NOT_CLOSED(self);
2775
2776 MYDB_BEGIN_ALLOW_THREADS;
2777 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2778 MYDB_END_ALLOW_THREADS;
2779 RETURN_IF_ERR();
2780
2781 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2782}
2783
2784static PyObject*
2785DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2786{
2787 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2788}
2789
2790
2791static PyObject*
2792DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2793{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002794 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002795 PyObject* keyobj = NULL;
2796 PyObject* dataobj = NULL;
2797 PyObject* retval = NULL;
2798 int dlen = -1;
2799 int doff = -1;
2800 DBT key, data;
2801 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2802
2803 CLEAR_DBT(key);
2804 CLEAR_DBT(data);
2805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002806 &flags, &dlen, &doff))
2807 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002808 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002809 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2810 &kwnames[1],
2811 &keyobj, &flags, &dlen, &doff))
2812 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002814 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2815 kwnames, &keyobj, &dataobj,
2816 &flags, &dlen, &doff))
2817 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002818 return NULL;
2819 }
2820 }
2821 }
2822
2823 CHECK_CURSOR_NOT_CLOSED(self);
2824
2825 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2826 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002827 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2828 (!add_partial_dbt(&data, dlen, doff)) )
2829 {
2830 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002831 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002832 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002833
2834 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2835 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002836 if (!(key.flags & DB_DBT_REALLOC)) {
2837 key.flags |= DB_DBT_MALLOC;
2838 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 }
2840
2841 MYDB_BEGIN_ALLOW_THREADS;
2842 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2843 MYDB_END_ALLOW_THREADS;
2844
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002845 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 Py_INCREF(Py_None);
2847 retval = Py_None;
2848 }
2849 else if (makeDBError(err)) {
2850 retval = NULL;
2851 }
2852 else {
2853 switch (_DB_get_type(self->mydb)) {
2854 case -1:
2855 retval = NULL;
2856 break;
2857 case DB_BTREE:
2858 case DB_HASH:
2859 default:
2860 retval = Py_BuildValue("s#s#", key.data, key.size,
2861 data.data, data.size);
2862 break;
2863 case DB_RECNO:
2864 case DB_QUEUE:
2865 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2866 data.data, data.size);
2867 break;
2868 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002869 FREE_DBT(data);
2870 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002871 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 return retval;
2873}
2874
Gregory P. Smith19699a92004-06-28 04:06:49 +00002875static PyObject*
2876DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2877{
2878 int err, flags=0;
2879 PyObject* keyobj = NULL;
2880 PyObject* dataobj = NULL;
2881 PyObject* retval = NULL;
2882 int dlen = -1;
2883 int doff = -1;
2884 DBT key, pkey, data;
2885 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2886
2887 CLEAR_DBT(key);
2888 CLEAR_DBT(data);
2889 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
2890 &flags, &dlen, &doff))
2891 {
2892 PyErr_Clear();
2893 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
2894 &kwnames[1],
2895 &keyobj, &flags, &dlen, &doff))
2896 {
2897 PyErr_Clear();
2898 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
2899 kwnames, &keyobj, &dataobj,
2900 &flags, &dlen, &doff))
2901 {
2902 return NULL;
2903 }
2904 }
2905 }
2906
2907 CHECK_CURSOR_NOT_CLOSED(self);
2908
2909 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2910 return NULL;
2911 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2912 (!add_partial_dbt(&data, dlen, doff)) ) {
2913 FREE_DBT(key);
2914 return NULL;
2915 }
2916
2917 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2918 data.flags = DB_DBT_MALLOC;
2919 if (!(key.flags & DB_DBT_REALLOC)) {
2920 key.flags |= DB_DBT_MALLOC;
2921 }
2922 }
2923
2924 CLEAR_DBT(pkey);
2925 pkey.flags = DB_DBT_MALLOC;
2926
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
2929 MYDB_END_ALLOW_THREADS;
2930
2931 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2932 Py_INCREF(Py_None);
2933 retval = Py_None;
2934 }
2935 else if (makeDBError(err)) {
2936 retval = NULL;
2937 }
2938 else {
2939 PyObject *pkeyObj;
2940 PyObject *dataObj;
2941 dataObj = PyString_FromStringAndSize(data.data, data.size);
2942
2943 if (self->mydb->primaryDBType == DB_RECNO ||
2944 self->mydb->primaryDBType == DB_QUEUE)
2945 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
2946 else
2947 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
2948
2949 if (flags & DB_SET_RECNO) /* return key, pkey and data */
2950 {
2951 PyObject *keyObj;
2952 int type = _DB_get_type(self->mydb);
2953 if (type == DB_RECNO || type == DB_QUEUE)
2954 keyObj = PyInt_FromLong(*(long *)key.data);
2955 else
2956 keyObj = PyString_FromStringAndSize(key.data, key.size);
2957 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
2958 FREE_DBT(key);
2959 }
2960 else /* return just the pkey and data */
2961 {
2962 retval = Py_BuildValue("OO", pkeyObj, dataObj);
2963 }
2964 FREE_DBT(pkey);
2965 FREE_DBT(data);
2966 }
2967 /* the only time REALLOC should be set is if we used an integer
2968 * key that make_key_dbt malloc'd for us. always free these. */
2969 if (key.flags & DB_DBT_REALLOC) {
2970 FREE_DBT(key);
2971 }
2972 return retval;
2973}
2974
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975
2976static PyObject*
2977DBC_get_recno(DBCursorObject* self, PyObject* args)
2978{
2979 int err;
2980 db_recno_t recno;
2981 DBT key;
2982 DBT data;
2983
2984 if (!PyArg_ParseTuple(args, ":get_recno"))
2985 return NULL;
2986
2987 CHECK_CURSOR_NOT_CLOSED(self);
2988
2989 CLEAR_DBT(key);
2990 CLEAR_DBT(data);
2991 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2992 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2993 data.flags = DB_DBT_MALLOC;
2994 key.flags = DB_DBT_MALLOC;
2995 }
2996
2997 MYDB_BEGIN_ALLOW_THREADS;
2998 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2999 MYDB_END_ALLOW_THREADS;
3000 RETURN_IF_ERR();
3001
3002 recno = *((db_recno_t*)data.data);
3003 FREE_DBT(key);
3004 FREE_DBT(data);
3005 return PyInt_FromLong(recno);
3006}
3007
3008
3009static PyObject*
3010DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3011{
3012 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3013}
3014
3015
3016static PyObject*
3017DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3018{
3019 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3020}
3021
3022
3023static PyObject*
3024DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3025{
3026 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3027}
3028
3029
3030static PyObject*
3031DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3032{
3033 int err, flags = 0;
3034 PyObject* keyobj, *dataobj;
3035 DBT key, data;
3036 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3037 int dlen = -1;
3038 int doff = -1;
3039
3040 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3041 &keyobj, &dataobj, &flags, &dlen, &doff))
3042 return NULL;
3043
3044 CHECK_CURSOR_NOT_CLOSED(self);
3045
3046 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3047 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003048 if (!make_dbt(dataobj, &data) ||
3049 !add_partial_dbt(&data, dlen, doff) )
3050 {
3051 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003052 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003053 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003054
3055 MYDB_BEGIN_ALLOW_THREADS;
3056 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3057 MYDB_END_ALLOW_THREADS;
3058 FREE_DBT(key);
3059 RETURN_IF_ERR();
3060 self->mydb->haveStat = 0;
3061 RETURN_NONE();
3062}
3063
3064
3065static PyObject*
3066DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3067{
3068 int err, flags = 0;
3069 DBT key, data;
3070 PyObject* retval, *keyobj;
3071 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3072 int dlen = -1;
3073 int doff = -1;
3074
3075 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3076 &keyobj, &flags, &dlen, &doff))
3077 return NULL;
3078
3079 CHECK_CURSOR_NOT_CLOSED(self);
3080
3081 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3082 return NULL;
3083
3084 CLEAR_DBT(data);
3085 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3086 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3087 data.flags = DB_DBT_MALLOC;
3088 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003089 if (!add_partial_dbt(&data, dlen, doff)) {
3090 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003091 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003092 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003093
3094 MYDB_BEGIN_ALLOW_THREADS;
3095 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3096 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003097 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3098 Py_INCREF(Py_None);
3099 retval = Py_None;
3100 }
3101 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 retval = NULL;
3103 }
3104 else {
3105 switch (_DB_get_type(self->mydb)) {
3106 case -1:
3107 retval = NULL;
3108 break;
3109 case DB_BTREE:
3110 case DB_HASH:
3111 default:
3112 retval = Py_BuildValue("s#s#", key.data, key.size,
3113 data.data, data.size);
3114 break;
3115 case DB_RECNO:
3116 case DB_QUEUE:
3117 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3118 data.data, data.size);
3119 break;
3120 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003121 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003122 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003123 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003124 /* the only time REALLOC should be set is if we used an integer
3125 * key that make_key_dbt malloc'd for us. always free these. */
3126 if (key.flags & DB_DBT_REALLOC) {
3127 FREE_DBT(key);
3128 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003129
3130 return retval;
3131}
3132
3133
3134static PyObject*
3135DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3136{
3137 int err, flags = 0;
3138 DBT key, data;
3139 PyObject* retval, *keyobj;
3140 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3141 int dlen = -1;
3142 int doff = -1;
3143
3144 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3145 &keyobj, &flags, &dlen, &doff))
3146 return NULL;
3147
3148 CHECK_CURSOR_NOT_CLOSED(self);
3149
3150 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3151 return NULL;
3152
3153 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003154 if (!add_partial_dbt(&data, dlen, doff)) {
3155 FREE_DBT(key);
3156 return NULL;
3157 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3159 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003160 data.flags |= DB_DBT_MALLOC;
3161 /* only BTREE databases will return anything in the key */
3162 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3163 key.flags |= DB_DBT_MALLOC;
3164 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003166 MYDB_BEGIN_ALLOW_THREADS;
3167 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3168 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003169 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3170 Py_INCREF(Py_None);
3171 retval = Py_None;
3172 }
3173 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 retval = NULL;
3175 }
3176 else {
3177 switch (_DB_get_type(self->mydb)) {
3178 case -1:
3179 retval = NULL;
3180 break;
3181 case DB_BTREE:
3182 case DB_HASH:
3183 default:
3184 retval = Py_BuildValue("s#s#", key.data, key.size,
3185 data.data, data.size);
3186 break;
3187 case DB_RECNO:
3188 case DB_QUEUE:
3189 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3190 data.data, data.size);
3191 break;
3192 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003193 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194 FREE_DBT(data);
3195 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003196 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003197 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003198 if (key.flags & DB_DBT_REALLOC) {
3199 FREE_DBT(key);
3200 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003201
3202 return retval;
3203}
3204
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003205static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003206_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3207 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003209 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003211 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003212
Gregory P. Smith7441e652003-11-03 21:35:31 +00003213 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003214 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3215 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003216 if (!make_dbt(dataobj, &data)) {
3217 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003219 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003220
3221 MYDB_BEGIN_ALLOW_THREADS;
3222 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3223 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003224 if ((err == DB_NOTFOUND) && returnsNone) {
3225 Py_INCREF(Py_None);
3226 retval = Py_None;
3227 }
3228 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003229 retval = NULL;
3230 }
3231 else {
3232 switch (_DB_get_type(self->mydb)) {
3233 case -1:
3234 retval = NULL;
3235 break;
3236 case DB_BTREE:
3237 case DB_HASH:
3238 default:
3239 retval = Py_BuildValue("s#s#", key.data, key.size,
3240 data.data, data.size);
3241 break;
3242 case DB_RECNO:
3243 case DB_QUEUE:
3244 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3245 data.data, data.size);
3246 break;
3247 }
3248 }
3249
3250 FREE_DBT(key);
3251 return retval;
3252}
3253
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003254static PyObject*
3255DBC_get_both(DBCursorObject* self, PyObject* args)
3256{
3257 int flags=0;
3258 PyObject *keyobj, *dataobj;
3259
3260 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3261 return NULL;
3262
Gregory P. Smith7441e652003-11-03 21:35:31 +00003263 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003264 CHECK_CURSOR_NOT_CLOSED(self);
3265
3266 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3267 self->mydb->moduleFlags.getReturnsNone);
3268}
3269
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003270/* Return size of entry */
3271static PyObject*
3272DBC_get_current_size(DBCursorObject* self, PyObject* args)
3273{
3274 int err, flags=DB_CURRENT;
3275 PyObject* retval = NULL;
3276 DBT key, data;
3277
3278 if (!PyArg_ParseTuple(args, ":get_current_size"))
3279 return NULL;
3280 CHECK_CURSOR_NOT_CLOSED(self);
3281 CLEAR_DBT(key);
3282 CLEAR_DBT(data);
3283
3284 /* We don't allocate any memory, forcing a ENOMEM error and thus
3285 getting the record size. */
3286 data.flags = DB_DBT_USERMEM;
3287 data.ulen = 0;
3288 MYDB_BEGIN_ALLOW_THREADS;
3289 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3290 MYDB_END_ALLOW_THREADS;
3291 if (err == ENOMEM || !err) {
3292 /* ENOMEM means positive size, !err means zero length value */
3293 retval = PyInt_FromLong((long)data.size);
3294 err = 0;
3295 }
3296
3297 FREE_DBT(key);
3298 FREE_DBT(data);
3299 RETURN_IF_ERR();
3300 return retval;
3301}
3302
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003303static PyObject*
3304DBC_set_both(DBCursorObject* self, PyObject* args)
3305{
3306 int flags=0;
3307 PyObject *keyobj, *dataobj;
3308
3309 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3310 return NULL;
3311
Gregory P. Smith7441e652003-11-03 21:35:31 +00003312 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003313 CHECK_CURSOR_NOT_CLOSED(self);
3314
3315 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3316 self->mydb->moduleFlags.cursorSetReturnsNone);
3317}
3318
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319
3320static PyObject*
3321DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3322{
3323 int err, irecno, flags=0;
3324 db_recno_t recno;
3325 DBT key, data;
3326 PyObject* retval;
3327 int dlen = -1;
3328 int doff = -1;
3329 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3330
3331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3332 &irecno, &flags, &dlen, &doff))
3333 return NULL;
3334
3335 CHECK_CURSOR_NOT_CLOSED(self);
3336
3337 CLEAR_DBT(key);
3338 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003339 /* use allocated space so DB will be able to realloc room for the real
3340 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341 key.data = malloc(sizeof(db_recno_t));
3342 if (key.data == NULL) {
3343 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3344 return NULL;
3345 }
3346 key.size = sizeof(db_recno_t);
3347 key.ulen = key.size;
3348 memcpy(key.data, &recno, sizeof(db_recno_t));
3349 key.flags = DB_DBT_REALLOC;
3350
3351 CLEAR_DBT(data);
3352 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3353 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3354 data.flags = DB_DBT_MALLOC;
3355 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003356 if (!add_partial_dbt(&data, dlen, doff)) {
3357 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003358 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003359 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360
3361 MYDB_BEGIN_ALLOW_THREADS;
3362 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3363 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003364 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3365 Py_INCREF(Py_None);
3366 retval = Py_None;
3367 }
3368 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003369 retval = NULL;
3370 }
3371 else { /* Can only be used for BTrees, so no need to return int key */
3372 retval = Py_BuildValue("s#s#", key.data, key.size,
3373 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003374 FREE_DBT(data);
3375 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003376 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003377
3378 return retval;
3379}
3380
3381
3382static PyObject*
3383DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3384{
3385 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3386}
3387
3388
3389static PyObject*
3390DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3391{
3392 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3393}
3394
3395
3396static PyObject*
3397DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3398{
3399 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3400}
3401
3402
3403static PyObject*
3404DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3405{
3406 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3407}
3408
3409
3410static PyObject*
3411DBC_join_item(DBCursorObject* self, PyObject* args)
3412{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003413 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 DBT key, data;
3415 PyObject* retval;
3416
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003417 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 return NULL;
3419
3420 CHECK_CURSOR_NOT_CLOSED(self);
3421
3422 CLEAR_DBT(key);
3423 CLEAR_DBT(data);
3424 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3425 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3426 key.flags = DB_DBT_MALLOC;
3427 }
3428
3429 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003430 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003432 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3433 Py_INCREF(Py_None);
3434 retval = Py_None;
3435 }
3436 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003437 retval = NULL;
3438 }
3439 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003440 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003441 FREE_DBT(key);
3442 }
3443
3444 return retval;
3445}
3446
3447
3448
3449/* --------------------------------------------------------------------- */
3450/* DBEnv methods */
3451
3452
3453static PyObject*
3454DBEnv_close(DBEnvObject* self, PyObject* args)
3455{
3456 int err, flags = 0;
3457
3458 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3459 return NULL;
3460 if (!self->closed) { /* Don't close more than once */
3461 MYDB_BEGIN_ALLOW_THREADS;
3462 err = self->db_env->close(self->db_env, flags);
3463 MYDB_END_ALLOW_THREADS;
3464 /* after calling DBEnv->close, regardless of error, this DBEnv
3465 * may not be accessed again (BerkeleyDB docs). */
3466 self->closed = 1;
3467 self->db_env = NULL;
3468 RETURN_IF_ERR();
3469 }
3470 RETURN_NONE();
3471}
3472
3473
3474static PyObject*
3475DBEnv_open(DBEnvObject* self, PyObject* args)
3476{
3477 int err, flags=0, mode=0660;
3478 char *db_home;
3479
3480 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3481 return NULL;
3482
3483 CHECK_ENV_NOT_CLOSED(self);
3484
3485 MYDB_BEGIN_ALLOW_THREADS;
3486 err = self->db_env->open(self->db_env, db_home, flags, mode);
3487 MYDB_END_ALLOW_THREADS;
3488 RETURN_IF_ERR();
3489 self->closed = 0;
3490 self->flags = flags;
3491 RETURN_NONE();
3492}
3493
3494
3495static PyObject*
3496DBEnv_remove(DBEnvObject* self, PyObject* args)
3497{
3498 int err, flags=0;
3499 char *db_home;
3500
3501 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3502 return NULL;
3503 CHECK_ENV_NOT_CLOSED(self);
3504 MYDB_BEGIN_ALLOW_THREADS;
3505 err = self->db_env->remove(self->db_env, db_home, flags);
3506 MYDB_END_ALLOW_THREADS;
3507 RETURN_IF_ERR();
3508 RETURN_NONE();
3509}
3510
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003511#if (DBVER >= 41)
3512static PyObject*
3513DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3514{
3515 int err;
3516 u_int32_t flags=0;
3517 char *file = NULL;
3518 char *database = NULL;
3519 PyObject *txnobj = NULL;
3520 DB_TXN *txn = NULL;
3521 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3522
3523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3524 &file, &database, &txnobj, &flags)) {
3525 return NULL;
3526 }
3527 if (!checkTxnObj(txnobj, &txn)) {
3528 return NULL;
3529 }
3530 CHECK_ENV_NOT_CLOSED(self);
3531 MYDB_BEGIN_ALLOW_THREADS;
3532 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3533 MYDB_END_ALLOW_THREADS;
3534 RETURN_IF_ERR();
3535 RETURN_NONE();
3536}
3537
3538static PyObject*
3539DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3540{
3541 int err;
3542 u_int32_t flags=0;
3543 char *file = NULL;
3544 char *database = NULL;
3545 char *newname = NULL;
3546 PyObject *txnobj = NULL;
3547 DB_TXN *txn = NULL;
3548 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3549
3550 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3551 &file, &database, &newname, &txnobj, &flags)) {
3552 return NULL;
3553 }
3554 if (!checkTxnObj(txnobj, &txn)) {
3555 return NULL;
3556 }
3557 CHECK_ENV_NOT_CLOSED(self);
3558 MYDB_BEGIN_ALLOW_THREADS;
3559 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3560 flags);
3561 MYDB_END_ALLOW_THREADS;
3562 RETURN_IF_ERR();
3563 RETURN_NONE();
3564}
3565
3566static PyObject*
3567DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3568{
3569 int err;
3570 u_int32_t flags=0;
3571 char *passwd = NULL;
3572 char* kwnames[] = { "passwd", "flags", NULL };
3573
3574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3575 &passwd, &flags)) {
3576 return NULL;
3577 }
3578
3579 MYDB_BEGIN_ALLOW_THREADS;
3580 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3581 MYDB_END_ALLOW_THREADS;
3582
3583 RETURN_IF_ERR();
3584 RETURN_NONE();
3585}
3586#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003588#if (DBVER >= 40)
3589static PyObject*
3590DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3591{
3592 int err;
3593 u_int32_t flags=0;
3594 u_int32_t timeout = 0;
3595 char* kwnames[] = { "timeout", "flags", NULL };
3596
3597 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3598 &timeout, &flags)) {
3599 return NULL;
3600 }
3601
3602 MYDB_BEGIN_ALLOW_THREADS;
3603 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3604 MYDB_END_ALLOW_THREADS;
3605
3606 RETURN_IF_ERR();
3607 RETURN_NONE();
3608}
3609#endif /* DBVER >= 40 */
3610
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003612DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3613{
3614 int err;
3615 long shm_key = 0;
3616
3617 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3618 return NULL;
3619 CHECK_ENV_NOT_CLOSED(self);
3620
3621 err = self->db_env->set_shm_key(self->db_env, shm_key);
3622 RETURN_IF_ERR();
3623 RETURN_NONE();
3624}
3625
3626static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003627DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3628{
3629 int err, gbytes=0, bytes=0, ncache=0;
3630
3631 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3632 &gbytes, &bytes, &ncache))
3633 return NULL;
3634 CHECK_ENV_NOT_CLOSED(self);
3635
3636 MYDB_BEGIN_ALLOW_THREADS;
3637 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3638 MYDB_END_ALLOW_THREADS;
3639 RETURN_IF_ERR();
3640 RETURN_NONE();
3641}
3642
3643
3644#if (DBVER >= 32)
3645static PyObject*
3646DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3647{
3648 int err, flags=0, onoff=0;
3649
3650 if (!PyArg_ParseTuple(args, "ii:set_flags",
3651 &flags, &onoff))
3652 return NULL;
3653 CHECK_ENV_NOT_CLOSED(self);
3654
3655 MYDB_BEGIN_ALLOW_THREADS;
3656 err = self->db_env->set_flags(self->db_env, flags, onoff);
3657 MYDB_END_ALLOW_THREADS;
3658 RETURN_IF_ERR();
3659 RETURN_NONE();
3660}
3661#endif
3662
3663
3664static PyObject*
3665DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3666{
3667 int err;
3668 char *dir;
3669
3670 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3671 return NULL;
3672 CHECK_ENV_NOT_CLOSED(self);
3673
3674 MYDB_BEGIN_ALLOW_THREADS;
3675 err = self->db_env->set_data_dir(self->db_env, dir);
3676 MYDB_END_ALLOW_THREADS;
3677 RETURN_IF_ERR();
3678 RETURN_NONE();
3679}
3680
3681
3682static PyObject*
3683DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3684{
3685 int err, lg_bsize;
3686
3687 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3688 return NULL;
3689 CHECK_ENV_NOT_CLOSED(self);
3690
3691 MYDB_BEGIN_ALLOW_THREADS;
3692 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3693 MYDB_END_ALLOW_THREADS;
3694 RETURN_IF_ERR();
3695 RETURN_NONE();
3696}
3697
3698
3699static PyObject*
3700DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3701{
3702 int err;
3703 char *dir;
3704
3705 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3706 return NULL;
3707 CHECK_ENV_NOT_CLOSED(self);
3708
3709 MYDB_BEGIN_ALLOW_THREADS;
3710 err = self->db_env->set_lg_dir(self->db_env, dir);
3711 MYDB_END_ALLOW_THREADS;
3712 RETURN_IF_ERR();
3713 RETURN_NONE();
3714}
3715
3716static PyObject*
3717DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3718{
3719 int err, lg_max;
3720
3721 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3722 return NULL;
3723 CHECK_ENV_NOT_CLOSED(self);
3724
3725 MYDB_BEGIN_ALLOW_THREADS;
3726 err = self->db_env->set_lg_max(self->db_env, lg_max);
3727 MYDB_END_ALLOW_THREADS;
3728 RETURN_IF_ERR();
3729 RETURN_NONE();
3730}
3731
3732
3733static PyObject*
3734DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3735{
3736 int err, lk_detect;
3737
3738 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3739 return NULL;
3740 CHECK_ENV_NOT_CLOSED(self);
3741
3742 MYDB_BEGIN_ALLOW_THREADS;
3743 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3744 MYDB_END_ALLOW_THREADS;
3745 RETURN_IF_ERR();
3746 RETURN_NONE();
3747}
3748
3749
3750static PyObject*
3751DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3752{
3753 int err, max;
3754
3755 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3756 return NULL;
3757 CHECK_ENV_NOT_CLOSED(self);
3758
3759 MYDB_BEGIN_ALLOW_THREADS;
3760 err = self->db_env->set_lk_max(self->db_env, max);
3761 MYDB_END_ALLOW_THREADS;
3762 RETURN_IF_ERR();
3763 RETURN_NONE();
3764}
3765
3766
3767#if (DBVER >= 32)
3768
3769static PyObject*
3770DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3771{
3772 int err, max;
3773
3774 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3775 return NULL;
3776 CHECK_ENV_NOT_CLOSED(self);
3777
3778 MYDB_BEGIN_ALLOW_THREADS;
3779 err = self->db_env->set_lk_max_locks(self->db_env, max);
3780 MYDB_END_ALLOW_THREADS;
3781 RETURN_IF_ERR();
3782 RETURN_NONE();
3783}
3784
3785
3786static PyObject*
3787DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3788{
3789 int err, max;
3790
3791 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3792 return NULL;
3793 CHECK_ENV_NOT_CLOSED(self);
3794
3795 MYDB_BEGIN_ALLOW_THREADS;
3796 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3797 MYDB_END_ALLOW_THREADS;
3798 RETURN_IF_ERR();
3799 RETURN_NONE();
3800}
3801
3802
3803static PyObject*
3804DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3805{
3806 int err, max;
3807
3808 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3809 return NULL;
3810 CHECK_ENV_NOT_CLOSED(self);
3811
3812 MYDB_BEGIN_ALLOW_THREADS;
3813 err = self->db_env->set_lk_max_objects(self->db_env, max);
3814 MYDB_END_ALLOW_THREADS;
3815 RETURN_IF_ERR();
3816 RETURN_NONE();
3817}
3818
3819#endif
3820
3821
3822static PyObject*
3823DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3824{
3825 int err, mp_mmapsize;
3826
3827 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3828 return NULL;
3829 CHECK_ENV_NOT_CLOSED(self);
3830
3831 MYDB_BEGIN_ALLOW_THREADS;
3832 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3833 MYDB_END_ALLOW_THREADS;
3834 RETURN_IF_ERR();
3835 RETURN_NONE();
3836}
3837
3838
3839static PyObject*
3840DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3841{
3842 int err;
3843 char *dir;
3844
3845 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3846 return NULL;
3847 CHECK_ENV_NOT_CLOSED(self);
3848
3849 MYDB_BEGIN_ALLOW_THREADS;
3850 err = self->db_env->set_tmp_dir(self->db_env, dir);
3851 MYDB_END_ALLOW_THREADS;
3852 RETURN_IF_ERR();
3853 RETURN_NONE();
3854}
3855
3856
3857static PyObject*
3858DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3859{
3860 int flags = 0;
3861 PyObject* txnobj = NULL;
3862 DB_TXN *txn = NULL;
3863 char* kwnames[] = { "parent", "flags", NULL };
3864
3865 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3866 &txnobj, &flags))
3867 return NULL;
3868
3869 if (!checkTxnObj(txnobj, &txn))
3870 return NULL;
3871 CHECK_ENV_NOT_CLOSED(self);
3872
3873 return (PyObject*)newDBTxnObject(self, txn, flags);
3874}
3875
3876
3877static PyObject*
3878DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3879{
3880 int err, kbyte=0, min=0, flags=0;
3881
3882 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3883 return NULL;
3884 CHECK_ENV_NOT_CLOSED(self);
3885
3886 MYDB_BEGIN_ALLOW_THREADS;
3887#if (DBVER >= 40)
3888 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3889#else
3890 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3891#endif
3892 MYDB_END_ALLOW_THREADS;
3893 RETURN_IF_ERR();
3894 RETURN_NONE();
3895}
3896
3897
3898static PyObject*
3899DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3900{
3901 int err, max;
3902
3903 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3904 return NULL;
3905 CHECK_ENV_NOT_CLOSED(self);
3906
3907 MYDB_BEGIN_ALLOW_THREADS;
3908 err = self->db_env->set_tx_max(self->db_env, max);
3909 MYDB_END_ALLOW_THREADS;
3910 RETURN_IF_ERR();
3911 RETURN_NONE();
3912}
3913
3914
3915static PyObject*
3916DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3917{
3918 int err, atype, flags=0;
3919 int aborted = 0;
3920
3921 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3922 return NULL;
3923 CHECK_ENV_NOT_CLOSED(self);
3924
3925 MYDB_BEGIN_ALLOW_THREADS;
3926#if (DBVER >= 40)
3927 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3928#else
3929 err = lock_detect(self->db_env, flags, atype, &aborted);
3930#endif
3931 MYDB_END_ALLOW_THREADS;
3932 RETURN_IF_ERR();
3933 return PyInt_FromLong(aborted);
3934}
3935
3936
3937static PyObject*
3938DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3939{
3940 int flags=0;
3941 int locker, lock_mode;
3942 DBT obj;
3943 PyObject* objobj;
3944
3945 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3946 return NULL;
3947
3948
3949 if (!make_dbt(objobj, &obj))
3950 return NULL;
3951
3952 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3953}
3954
3955
3956static PyObject*
3957DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3958{
3959 int err;
3960 u_int32_t theID;
3961
3962 if (!PyArg_ParseTuple(args, ":lock_id"))
3963 return NULL;
3964
3965 CHECK_ENV_NOT_CLOSED(self);
3966 MYDB_BEGIN_ALLOW_THREADS;
3967#if (DBVER >= 40)
3968 err = self->db_env->lock_id(self->db_env, &theID);
3969#else
3970 err = lock_id(self->db_env, &theID);
3971#endif
3972 MYDB_END_ALLOW_THREADS;
3973 RETURN_IF_ERR();
3974
3975 return PyInt_FromLong((long)theID);
3976}
3977
3978
3979static PyObject*
3980DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3981{
3982 int err;
3983 DBLockObject* dblockobj;
3984
3985 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3986 return NULL;
3987
3988 CHECK_ENV_NOT_CLOSED(self);
3989 MYDB_BEGIN_ALLOW_THREADS;
3990#if (DBVER >= 40)
3991 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3992#else
3993 err = lock_put(self->db_env, &dblockobj->lock);
3994#endif
3995 MYDB_END_ALLOW_THREADS;
3996 RETURN_IF_ERR();
3997 RETURN_NONE();
3998}
3999
4000
4001static PyObject*
4002DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4003{
4004 int err;
4005 DB_LOCK_STAT* sp;
4006 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004007 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004008
4009 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4010 return NULL;
4011 CHECK_ENV_NOT_CLOSED(self);
4012
4013 MYDB_BEGIN_ALLOW_THREADS;
4014#if (DBVER >= 40)
4015 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4016#else
4017#if (DBVER >= 33)
4018 err = lock_stat(self->db_env, &sp);
4019#else
4020 err = lock_stat(self->db_env, &sp, NULL);
4021#endif
4022#endif
4023 MYDB_END_ALLOW_THREADS;
4024 RETURN_IF_ERR();
4025
4026 /* Turn the stat structure into a dictionary */
4027 d = PyDict_New();
4028 if (d == NULL) {
4029 free(sp);
4030 return NULL;
4031 }
4032
4033#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4034
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004035#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004036 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004038 MAKE_ENTRY(nmodes);
4039#if (DBVER >= 32)
4040 MAKE_ENTRY(maxlocks);
4041 MAKE_ENTRY(maxlockers);
4042 MAKE_ENTRY(maxobjects);
4043 MAKE_ENTRY(nlocks);
4044 MAKE_ENTRY(maxnlocks);
4045#endif
4046 MAKE_ENTRY(nlockers);
4047 MAKE_ENTRY(maxnlockers);
4048#if (DBVER >= 32)
4049 MAKE_ENTRY(nobjects);
4050 MAKE_ENTRY(maxnobjects);
4051#endif
4052 MAKE_ENTRY(nrequests);
4053 MAKE_ENTRY(nreleases);
4054 MAKE_ENTRY(nnowaits);
4055 MAKE_ENTRY(nconflicts);
4056 MAKE_ENTRY(ndeadlocks);
4057 MAKE_ENTRY(regsize);
4058 MAKE_ENTRY(region_wait);
4059 MAKE_ENTRY(region_nowait);
4060
4061#undef MAKE_ENTRY
4062 free(sp);
4063 return d;
4064}
4065
4066
4067static PyObject*
4068DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4069{
4070 int flags=0;
4071 int err;
4072 char **log_list_start, **log_list;
4073 PyObject* list;
4074 PyObject* item = NULL;
4075
4076 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4077 return NULL;
4078
4079 CHECK_ENV_NOT_CLOSED(self);
4080 MYDB_BEGIN_ALLOW_THREADS;
4081#if (DBVER >= 40)
4082 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4083#elif (DBVER == 33)
4084 err = log_archive(self->db_env, &log_list, flags);
4085#else
4086 err = log_archive(self->db_env, &log_list, flags, NULL);
4087#endif
4088 MYDB_END_ALLOW_THREADS;
4089 RETURN_IF_ERR();
4090
4091 list = PyList_New(0);
4092 if (list == NULL) {
4093 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4094 return NULL;
4095 }
4096
4097 if (log_list) {
4098 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4099 item = PyString_FromString (*log_list);
4100 if (item == NULL) {
4101 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004102 PyErr_SetString(PyExc_MemoryError,
4103 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004104 list = NULL;
4105 break;
4106 }
4107 PyList_Append(list, item);
4108 Py_DECREF(item);
4109 }
4110 free(log_list_start);
4111 }
4112 return list;
4113}
4114
4115
4116static PyObject*
4117DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4118{
4119 int err;
4120 DB_TXN_STAT* sp;
4121 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004122 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004123
4124 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4125 return NULL;
4126 CHECK_ENV_NOT_CLOSED(self);
4127
4128 MYDB_BEGIN_ALLOW_THREADS;
4129#if (DBVER >= 40)
4130 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4131#elif (DBVER == 33)
4132 err = txn_stat(self->db_env, &sp);
4133#else
4134 err = txn_stat(self->db_env, &sp, NULL);
4135#endif
4136 MYDB_END_ALLOW_THREADS;
4137 RETURN_IF_ERR();
4138
4139 /* Turn the stat structure into a dictionary */
4140 d = PyDict_New();
4141 if (d == NULL) {
4142 free(sp);
4143 return NULL;
4144 }
4145
4146#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4147
4148 MAKE_ENTRY(time_ckp);
4149 MAKE_ENTRY(last_txnid);
4150 MAKE_ENTRY(maxtxns);
4151 MAKE_ENTRY(nactive);
4152 MAKE_ENTRY(maxnactive);
4153 MAKE_ENTRY(nbegins);
4154 MAKE_ENTRY(naborts);
4155 MAKE_ENTRY(ncommits);
4156 MAKE_ENTRY(regsize);
4157 MAKE_ENTRY(region_wait);
4158 MAKE_ENTRY(region_nowait);
4159
4160#undef MAKE_ENTRY
4161 free(sp);
4162 return d;
4163}
4164
4165
4166static PyObject*
4167DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4168{
4169 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004170 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004171
4172 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4173 return NULL;
4174 CHECK_ENV_NOT_CLOSED(self);
4175
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004176 if (self->moduleFlags.getReturnsNone)
4177 ++oldValue;
4178 if (self->moduleFlags.cursorSetReturnsNone)
4179 ++oldValue;
4180 self->moduleFlags.getReturnsNone = (flags >= 1);
4181 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004182 return PyInt_FromLong(oldValue);
4183}
4184
4185
4186/* --------------------------------------------------------------------- */
4187/* DBTxn methods */
4188
4189
4190static PyObject*
4191DBTxn_commit(DBTxnObject* self, PyObject* args)
4192{
4193 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004194 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004195
4196 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4197 return NULL;
4198
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004199 if (!self->txn) {
4200 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4201 "DBTxn must not be used after txn_commit or txn_abort"));
4202 return NULL;
4203 }
4204 txn = self->txn;
4205 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004206 MYDB_BEGIN_ALLOW_THREADS;
4207#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004208 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004209#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004210 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004211#endif
4212 MYDB_END_ALLOW_THREADS;
4213 RETURN_IF_ERR();
4214 RETURN_NONE();
4215}
4216
4217static PyObject*
4218DBTxn_prepare(DBTxnObject* self, PyObject* args)
4219{
4220#if (DBVER >= 33)
4221 int err;
4222 char* gid=NULL;
4223 int gid_size=0;
4224
4225 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4226 return NULL;
4227
4228 if (gid_size != DB_XIDDATASIZE) {
4229 PyErr_SetString(PyExc_TypeError,
4230 "gid must be DB_XIDDATASIZE bytes long");
4231 return NULL;
4232 }
4233
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004234 if (!self->txn) {
4235 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4236 "DBTxn must not be used after txn_commit or txn_abort"));
4237 return NULL;
4238 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004239 MYDB_BEGIN_ALLOW_THREADS;
4240#if (DBVER >= 40)
4241 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4242#else
4243 err = txn_prepare(self->txn, (u_int8_t*)gid);
4244#endif
4245 MYDB_END_ALLOW_THREADS;
4246 RETURN_IF_ERR();
4247 RETURN_NONE();
4248#else
4249 int err;
4250
4251 if (!PyArg_ParseTuple(args, ":prepare"))
4252 return NULL;
4253
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004254 if (!self->txn) {
4255 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4256 "DBTxn must not be used after txn_commit or txn_abort"));
4257 return NULL;
4258 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004259 MYDB_BEGIN_ALLOW_THREADS;
4260 err = txn_prepare(self->txn);
4261 MYDB_END_ALLOW_THREADS;
4262 RETURN_IF_ERR();
4263 RETURN_NONE();
4264#endif
4265}
4266
4267
4268static PyObject*
4269DBTxn_abort(DBTxnObject* self, PyObject* args)
4270{
4271 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004272 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004273
4274 if (!PyArg_ParseTuple(args, ":abort"))
4275 return NULL;
4276
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004277 if (!self->txn) {
4278 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4279 "DBTxn must not be used after txn_commit or txn_abort"));
4280 return NULL;
4281 }
4282 txn = self->txn;
4283 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004284 MYDB_BEGIN_ALLOW_THREADS;
4285#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004286 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004287#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004288 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004289#endif
4290 MYDB_END_ALLOW_THREADS;
4291 RETURN_IF_ERR();
4292 RETURN_NONE();
4293}
4294
4295
4296static PyObject*
4297DBTxn_id(DBTxnObject* self, PyObject* args)
4298{
4299 int id;
4300
4301 if (!PyArg_ParseTuple(args, ":id"))
4302 return NULL;
4303
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004304 if (!self->txn) {
4305 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4306 "DBTxn must not be used after txn_commit or txn_abort"));
4307 return NULL;
4308 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004309 MYDB_BEGIN_ALLOW_THREADS;
4310#if (DBVER >= 40)
4311 id = self->txn->id(self->txn);
4312#else
4313 id = txn_id(self->txn);
4314#endif
4315 MYDB_END_ALLOW_THREADS;
4316 return PyInt_FromLong(id);
4317}
4318
4319/* --------------------------------------------------------------------- */
4320/* Method definition tables and type objects */
4321
4322static PyMethodDef DB_methods[] = {
4323 {"append", (PyCFunction)DB_append, METH_VARARGS},
4324#if (DBVER >= 33)
4325 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4326#endif
4327 {"close", (PyCFunction)DB_close, METH_VARARGS},
4328#if (DBVER >= 32)
4329 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4330 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4331#endif
4332 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4333 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4334 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4335 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00004336 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004337 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4338 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4339 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4340 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4341 {"join", (PyCFunction)DB_join, METH_VARARGS},
4342 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4343 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4344 {"items", (PyCFunction)DB_items, METH_VARARGS},
4345 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4346 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4347 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4348 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4349 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4350 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4351 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004352#if (DBVER >= 41)
4353 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4354#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004355 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4356 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4357 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4358 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4359 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4360 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4361 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4362 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4363 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4364#if (DBVER >= 32)
4365 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4366#endif
4367 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4368 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4369#if (DBVER >= 33)
4370 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4371#endif
4372 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4373 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4374 {"values", (PyCFunction)DB_values, METH_VARARGS},
4375 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4376 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4377 {NULL, NULL} /* sentinel */
4378};
4379
4380
4381static PyMappingMethods DB_mapping = {
4382 (inquiry)DB_length, /*mp_length*/
4383 (binaryfunc)DB_subscript, /*mp_subscript*/
4384 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4385};
4386
4387
4388static PyMethodDef DBCursor_methods[] = {
4389 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4390 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4391 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4392 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4393 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4394 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4395 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00004396 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004397 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4398 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4399 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4400 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4401 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4402 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4403 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4404 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004405 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004406 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004407 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4408 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4409 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4410 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4411 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4412 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4413 {NULL, NULL} /* sentinel */
4414};
4415
4416
4417static PyMethodDef DBEnv_methods[] = {
4418 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4419 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4420 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004421#if (DBVER >= 41)
4422 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4423 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4424 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4425#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004426#if (DBVER >= 40)
4427 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4428#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004429 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004430 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4431 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4432#if (DBVER >= 32)
4433 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4434#endif
4435 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4436 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4437 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4438 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4439 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4440#if (DBVER >= 32)
4441 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4442 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4443 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4444#endif
4445 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4446 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4447 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4448 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4449 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4450 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4451 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4452 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4453 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4454 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4455 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4456 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4457 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4458 {NULL, NULL} /* sentinel */
4459};
4460
4461
4462static PyMethodDef DBTxn_methods[] = {
4463 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4464 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4465 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4466 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4467 {NULL, NULL} /* sentinel */
4468};
4469
4470
4471static PyObject*
4472DB_getattr(DBObject* self, char *name)
4473{
4474 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4475}
4476
4477
4478static PyObject*
4479DBEnv_getattr(DBEnvObject* self, char *name)
4480{
4481 if (!strcmp(name, "db_home")) {
4482 CHECK_ENV_NOT_CLOSED(self);
4483 if (self->db_env->db_home == NULL) {
4484 RETURN_NONE();
4485 }
4486 return PyString_FromString(self->db_env->db_home);
4487 }
4488
4489 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4490}
4491
4492
4493static PyObject*
4494DBCursor_getattr(DBCursorObject* self, char *name)
4495{
4496 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4497}
4498
4499static PyObject*
4500DBTxn_getattr(DBTxnObject* self, char *name)
4501{
4502 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4503}
4504
4505static PyObject*
4506DBLock_getattr(DBLockObject* self, char *name)
4507{
4508 return NULL;
4509}
4510
4511statichere PyTypeObject DB_Type = {
4512 PyObject_HEAD_INIT(NULL)
4513 0, /*ob_size*/
4514 "DB", /*tp_name*/
4515 sizeof(DBObject), /*tp_basicsize*/
4516 0, /*tp_itemsize*/
4517 /* methods */
4518 (destructor)DB_dealloc, /*tp_dealloc*/
4519 0, /*tp_print*/
4520 (getattrfunc)DB_getattr, /*tp_getattr*/
4521 0, /*tp_setattr*/
4522 0, /*tp_compare*/
4523 0, /*tp_repr*/
4524 0, /*tp_as_number*/
4525 0, /*tp_as_sequence*/
4526 &DB_mapping,/*tp_as_mapping*/
4527 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004528#ifdef HAVE_WEAKREF
4529 0, /* tp_call */
4530 0, /* tp_str */
4531 0, /* tp_getattro */
4532 0, /* tp_setattro */
4533 0, /* tp_as_buffer */
4534 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4535 0, /* tp_doc */
4536 0, /* tp_traverse */
4537 0, /* tp_clear */
4538 0, /* tp_richcompare */
4539 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4540#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004541};
4542
4543
4544statichere PyTypeObject DBCursor_Type = {
4545 PyObject_HEAD_INIT(NULL)
4546 0, /*ob_size*/
4547 "DBCursor", /*tp_name*/
4548 sizeof(DBCursorObject), /*tp_basicsize*/
4549 0, /*tp_itemsize*/
4550 /* methods */
4551 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4552 0, /*tp_print*/
4553 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4554 0, /*tp_setattr*/
4555 0, /*tp_compare*/
4556 0, /*tp_repr*/
4557 0, /*tp_as_number*/
4558 0, /*tp_as_sequence*/
4559 0, /*tp_as_mapping*/
4560 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004561#ifdef HAVE_WEAKREF
4562 0, /* tp_call */
4563 0, /* tp_str */
4564 0, /* tp_getattro */
4565 0, /* tp_setattro */
4566 0, /* tp_as_buffer */
4567 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4568 0, /* tp_doc */
4569 0, /* tp_traverse */
4570 0, /* tp_clear */
4571 0, /* tp_richcompare */
4572 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4573#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004574};
4575
4576
4577statichere PyTypeObject DBEnv_Type = {
4578 PyObject_HEAD_INIT(NULL)
4579 0, /*ob_size*/
4580 "DBEnv", /*tp_name*/
4581 sizeof(DBEnvObject), /*tp_basicsize*/
4582 0, /*tp_itemsize*/
4583 /* methods */
4584 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4585 0, /*tp_print*/
4586 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4587 0, /*tp_setattr*/
4588 0, /*tp_compare*/
4589 0, /*tp_repr*/
4590 0, /*tp_as_number*/
4591 0, /*tp_as_sequence*/
4592 0, /*tp_as_mapping*/
4593 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004594#ifdef HAVE_WEAKREF
4595 0, /* tp_call */
4596 0, /* tp_str */
4597 0, /* tp_getattro */
4598 0, /* tp_setattro */
4599 0, /* tp_as_buffer */
4600 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4601 0, /* tp_doc */
4602 0, /* tp_traverse */
4603 0, /* tp_clear */
4604 0, /* tp_richcompare */
4605 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4606#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607};
4608
4609statichere PyTypeObject DBTxn_Type = {
4610 PyObject_HEAD_INIT(NULL)
4611 0, /*ob_size*/
4612 "DBTxn", /*tp_name*/
4613 sizeof(DBTxnObject), /*tp_basicsize*/
4614 0, /*tp_itemsize*/
4615 /* methods */
4616 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4617 0, /*tp_print*/
4618 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4619 0, /*tp_setattr*/
4620 0, /*tp_compare*/
4621 0, /*tp_repr*/
4622 0, /*tp_as_number*/
4623 0, /*tp_as_sequence*/
4624 0, /*tp_as_mapping*/
4625 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004626#ifdef HAVE_WEAKREF
4627 0, /* tp_call */
4628 0, /* tp_str */
4629 0, /* tp_getattro */
4630 0, /* tp_setattro */
4631 0, /* tp_as_buffer */
4632 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4633 0, /* tp_doc */
4634 0, /* tp_traverse */
4635 0, /* tp_clear */
4636 0, /* tp_richcompare */
4637 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4638#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004639};
4640
4641
4642statichere PyTypeObject DBLock_Type = {
4643 PyObject_HEAD_INIT(NULL)
4644 0, /*ob_size*/
4645 "DBLock", /*tp_name*/
4646 sizeof(DBLockObject), /*tp_basicsize*/
4647 0, /*tp_itemsize*/
4648 /* methods */
4649 (destructor)DBLock_dealloc, /*tp_dealloc*/
4650 0, /*tp_print*/
4651 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4652 0, /*tp_setattr*/
4653 0, /*tp_compare*/
4654 0, /*tp_repr*/
4655 0, /*tp_as_number*/
4656 0, /*tp_as_sequence*/
4657 0, /*tp_as_mapping*/
4658 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004659#ifdef HAVE_WEAKREF
4660 0, /* tp_call */
4661 0, /* tp_str */
4662 0, /* tp_getattro */
4663 0, /* tp_setattro */
4664 0, /* tp_as_buffer */
4665 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4666 0, /* tp_doc */
4667 0, /* tp_traverse */
4668 0, /* tp_clear */
4669 0, /* tp_richcompare */
4670 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4671#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004672};
4673
4674
4675/* --------------------------------------------------------------------- */
4676/* Module-level functions */
4677
4678static PyObject*
4679DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4680{
4681 PyObject* dbenvobj = NULL;
4682 int flags = 0;
4683 char* kwnames[] = { "dbEnv", "flags", NULL};
4684
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4686 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687 return NULL;
4688 if (dbenvobj == Py_None)
4689 dbenvobj = NULL;
4690 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4691 makeTypeError("DBEnv", dbenvobj);
4692 return NULL;
4693 }
4694
4695 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4696}
4697
4698
4699static PyObject*
4700DBEnv_construct(PyObject* self, PyObject* args)
4701{
4702 int flags = 0;
4703 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4704 return (PyObject* )newDBEnvObject(flags);
4705}
4706
4707
4708static char bsddb_version_doc[] =
4709"Returns a tuple of major, minor, and patch release numbers of the\n\
4710underlying DB library.";
4711
4712static PyObject*
4713bsddb_version(PyObject* self, PyObject* args)
4714{
4715 int major, minor, patch;
4716
4717 if (!PyArg_ParseTuple(args, ":version"))
4718 return NULL;
4719 db_version(&major, &minor, &patch);
4720 return Py_BuildValue("(iii)", major, minor, patch);
4721}
4722
4723
4724/* List of functions defined in the module */
4725
4726static PyMethodDef bsddb_methods[] = {
4727 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4728 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4729 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4730 {NULL, NULL} /* sentinel */
4731};
4732
4733
4734/* --------------------------------------------------------------------- */
4735/* Module initialization */
4736
4737
4738/* Convenience routine to export an integer value.
4739 * Errors are silently ignored, for better or for worse...
4740 */
4741#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4742
Gregory P. Smith41631e82003-09-21 00:08:14 +00004743#define MODULE_NAME_MAX_LEN 11
4744static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004745
4746DL_EXPORT(void) init_bsddb(void)
4747{
4748 PyObject* m;
4749 PyObject* d;
4750 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4751 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4752 PyObject* cvsid_s = PyString_FromString( rcs_id );
4753
4754 /* Initialize the type of the new type objects here; doing it here
4755 is required for portability to Windows without requiring C++. */
4756 DB_Type.ob_type = &PyType_Type;
4757 DBCursor_Type.ob_type = &PyType_Type;
4758 DBEnv_Type.ob_type = &PyType_Type;
4759 DBTxn_Type.ob_type = &PyType_Type;
4760 DBLock_Type.ob_type = &PyType_Type;
4761
4762
Mark Hammonda69d4092003-04-22 23:13:27 +00004763#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004764 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004765 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766#endif
4767
4768 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004769 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004770
4771 /* Add some symbolic constants to the module */
4772 d = PyModule_GetDict(m);
4773 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4774 PyDict_SetItemString(d, "cvsid", cvsid_s);
4775 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4776 Py_DECREF(pybsddb_version_s);
4777 pybsddb_version_s = NULL;
4778 Py_DECREF(cvsid_s);
4779 cvsid_s = NULL;
4780 Py_DECREF(db_version_s);
4781 db_version_s = NULL;
4782
4783 ADD_INT(d, DB_VERSION_MAJOR);
4784 ADD_INT(d, DB_VERSION_MINOR);
4785 ADD_INT(d, DB_VERSION_PATCH);
4786
4787 ADD_INT(d, DB_MAX_PAGES);
4788 ADD_INT(d, DB_MAX_RECORDS);
4789
Gregory P. Smith41631e82003-09-21 00:08:14 +00004790#if (DBVER >= 42)
4791 ADD_INT(d, DB_RPCCLIENT);
4792#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004793 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004794 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4795 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4796#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004797 ADD_INT(d, DB_XA_CREATE);
4798
4799 ADD_INT(d, DB_CREATE);
4800 ADD_INT(d, DB_NOMMAP);
4801 ADD_INT(d, DB_THREAD);
4802
4803 ADD_INT(d, DB_FORCE);
4804 ADD_INT(d, DB_INIT_CDB);
4805 ADD_INT(d, DB_INIT_LOCK);
4806 ADD_INT(d, DB_INIT_LOG);
4807 ADD_INT(d, DB_INIT_MPOOL);
4808 ADD_INT(d, DB_INIT_TXN);
4809#if (DBVER >= 32)
4810 ADD_INT(d, DB_JOINENV);
4811#endif
4812
4813 ADD_INT(d, DB_RECOVER);
4814 ADD_INT(d, DB_RECOVER_FATAL);
4815 ADD_INT(d, DB_TXN_NOSYNC);
4816 ADD_INT(d, DB_USE_ENVIRON);
4817 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4818
4819 ADD_INT(d, DB_LOCKDOWN);
4820 ADD_INT(d, DB_PRIVATE);
4821 ADD_INT(d, DB_SYSTEM_MEM);
4822
4823 ADD_INT(d, DB_TXN_SYNC);
4824 ADD_INT(d, DB_TXN_NOWAIT);
4825
4826 ADD_INT(d, DB_EXCL);
4827 ADD_INT(d, DB_FCNTL_LOCKING);
4828 ADD_INT(d, DB_ODDFILESIZE);
4829 ADD_INT(d, DB_RDWRMASTER);
4830 ADD_INT(d, DB_RDONLY);
4831 ADD_INT(d, DB_TRUNCATE);
4832#if (DBVER >= 32)
4833 ADD_INT(d, DB_EXTENT);
4834 ADD_INT(d, DB_CDB_ALLDB);
4835 ADD_INT(d, DB_VERIFY);
4836#endif
4837 ADD_INT(d, DB_UPGRADE);
4838
4839 ADD_INT(d, DB_AGGRESSIVE);
4840 ADD_INT(d, DB_NOORDERCHK);
4841 ADD_INT(d, DB_ORDERCHKONLY);
4842 ADD_INT(d, DB_PR_PAGE);
4843#if ! (DBVER >= 33)
4844 ADD_INT(d, DB_VRFY_FLAGMASK);
4845 ADD_INT(d, DB_PR_HEADERS);
4846#endif
4847 ADD_INT(d, DB_PR_RECOVERYTEST);
4848 ADD_INT(d, DB_SALVAGE);
4849
4850 ADD_INT(d, DB_LOCK_NORUN);
4851 ADD_INT(d, DB_LOCK_DEFAULT);
4852 ADD_INT(d, DB_LOCK_OLDEST);
4853 ADD_INT(d, DB_LOCK_RANDOM);
4854 ADD_INT(d, DB_LOCK_YOUNGEST);
4855#if (DBVER >= 33)
4856 ADD_INT(d, DB_LOCK_MAXLOCKS);
4857 ADD_INT(d, DB_LOCK_MINLOCKS);
4858 ADD_INT(d, DB_LOCK_MINWRITE);
4859#endif
4860
4861
4862#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004863 /* docs say to use zero instead */
4864 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004865#else
4866 ADD_INT(d, DB_LOCK_CONFLICT);
4867#endif
4868
4869 ADD_INT(d, DB_LOCK_DUMP);
4870 ADD_INT(d, DB_LOCK_GET);
4871 ADD_INT(d, DB_LOCK_INHERIT);
4872 ADD_INT(d, DB_LOCK_PUT);
4873 ADD_INT(d, DB_LOCK_PUT_ALL);
4874 ADD_INT(d, DB_LOCK_PUT_OBJ);
4875
4876 ADD_INT(d, DB_LOCK_NG);
4877 ADD_INT(d, DB_LOCK_READ);
4878 ADD_INT(d, DB_LOCK_WRITE);
4879 ADD_INT(d, DB_LOCK_NOWAIT);
4880#if (DBVER >= 32)
4881 ADD_INT(d, DB_LOCK_WAIT);
4882#endif
4883 ADD_INT(d, DB_LOCK_IWRITE);
4884 ADD_INT(d, DB_LOCK_IREAD);
4885 ADD_INT(d, DB_LOCK_IWR);
4886#if (DBVER >= 33)
4887 ADD_INT(d, DB_LOCK_DIRTY);
4888 ADD_INT(d, DB_LOCK_WWRITE);
4889#endif
4890
4891 ADD_INT(d, DB_LOCK_RECORD);
4892 ADD_INT(d, DB_LOCK_UPGRADE);
4893#if (DBVER >= 32)
4894 ADD_INT(d, DB_LOCK_SWITCH);
4895#endif
4896#if (DBVER >= 33)
4897 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4898#endif
4899
4900 ADD_INT(d, DB_LOCK_NOWAIT);
4901 ADD_INT(d, DB_LOCK_RECORD);
4902 ADD_INT(d, DB_LOCK_UPGRADE);
4903
4904#if (DBVER >= 33)
4905 ADD_INT(d, DB_LSTAT_ABORTED);
4906 ADD_INT(d, DB_LSTAT_ERR);
4907 ADD_INT(d, DB_LSTAT_FREE);
4908 ADD_INT(d, DB_LSTAT_HELD);
4909#if (DBVER == 33)
4910 ADD_INT(d, DB_LSTAT_NOGRANT);
4911#endif
4912 ADD_INT(d, DB_LSTAT_PENDING);
4913 ADD_INT(d, DB_LSTAT_WAITING);
4914#endif
4915
4916 ADD_INT(d, DB_ARCH_ABS);
4917 ADD_INT(d, DB_ARCH_DATA);
4918 ADD_INT(d, DB_ARCH_LOG);
4919
4920 ADD_INT(d, DB_BTREE);
4921 ADD_INT(d, DB_HASH);
4922 ADD_INT(d, DB_RECNO);
4923 ADD_INT(d, DB_QUEUE);
4924 ADD_INT(d, DB_UNKNOWN);
4925
4926 ADD_INT(d, DB_DUP);
4927 ADD_INT(d, DB_DUPSORT);
4928 ADD_INT(d, DB_RECNUM);
4929 ADD_INT(d, DB_RENUMBER);
4930 ADD_INT(d, DB_REVSPLITOFF);
4931 ADD_INT(d, DB_SNAPSHOT);
4932
4933 ADD_INT(d, DB_JOIN_NOSORT);
4934
4935 ADD_INT(d, DB_AFTER);
4936 ADD_INT(d, DB_APPEND);
4937 ADD_INT(d, DB_BEFORE);
4938 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004939#if (DBVER >= 41)
4940 _addIntToDict(d, "DB_CHECKPOINT", 0);
4941#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004942 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004943 ADD_INT(d, DB_CURLSN);
4944#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004945#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004946 ADD_INT(d, DB_COMMIT);
4947#endif
4948 ADD_INT(d, DB_CONSUME);
4949#if (DBVER >= 32)
4950 ADD_INT(d, DB_CONSUME_WAIT);
4951#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004952 ADD_INT(d, DB_CURRENT);
4953#if (DBVER >= 33)
4954 ADD_INT(d, DB_FAST_STAT);
4955#endif
4956 ADD_INT(d, DB_FIRST);
4957 ADD_INT(d, DB_FLUSH);
4958 ADD_INT(d, DB_GET_BOTH);
4959 ADD_INT(d, DB_GET_RECNO);
4960 ADD_INT(d, DB_JOIN_ITEM);
4961 ADD_INT(d, DB_KEYFIRST);
4962 ADD_INT(d, DB_KEYLAST);
4963 ADD_INT(d, DB_LAST);
4964 ADD_INT(d, DB_NEXT);
4965 ADD_INT(d, DB_NEXT_DUP);
4966 ADD_INT(d, DB_NEXT_NODUP);
4967 ADD_INT(d, DB_NODUPDATA);
4968 ADD_INT(d, DB_NOOVERWRITE);
4969 ADD_INT(d, DB_NOSYNC);
4970 ADD_INT(d, DB_POSITION);
4971 ADD_INT(d, DB_PREV);
4972 ADD_INT(d, DB_PREV_NODUP);
4973 ADD_INT(d, DB_RECORDCOUNT);
4974 ADD_INT(d, DB_SET);
4975 ADD_INT(d, DB_SET_RANGE);
4976 ADD_INT(d, DB_SET_RECNO);
4977 ADD_INT(d, DB_WRITECURSOR);
4978
4979 ADD_INT(d, DB_OPFLAGS_MASK);
4980 ADD_INT(d, DB_RMW);
4981#if (DBVER >= 33)
4982 ADD_INT(d, DB_DIRTY_READ);
4983 ADD_INT(d, DB_MULTIPLE);
4984 ADD_INT(d, DB_MULTIPLE_KEY);
4985#endif
4986
4987#if (DBVER >= 33)
4988 ADD_INT(d, DB_DONOTINDEX);
4989#endif
4990
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004991#if (DBVER >= 41)
4992 _addIntToDict(d, "DB_INCOMPLETE", 0);
4993#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004994 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004996 ADD_INT(d, DB_KEYEMPTY);
4997 ADD_INT(d, DB_KEYEXIST);
4998 ADD_INT(d, DB_LOCK_DEADLOCK);
4999 ADD_INT(d, DB_LOCK_NOTGRANTED);
5000 ADD_INT(d, DB_NOSERVER);
5001 ADD_INT(d, DB_NOSERVER_HOME);
5002 ADD_INT(d, DB_NOSERVER_ID);
5003 ADD_INT(d, DB_NOTFOUND);
5004 ADD_INT(d, DB_OLD_VERSION);
5005 ADD_INT(d, DB_RUNRECOVERY);
5006 ADD_INT(d, DB_VERIFY_BAD);
5007#if (DBVER >= 33)
5008 ADD_INT(d, DB_PAGE_NOTFOUND);
5009 ADD_INT(d, DB_SECONDARY_BAD);
5010#endif
5011#if (DBVER >= 40)
5012 ADD_INT(d, DB_STAT_CLEAR);
5013 ADD_INT(d, DB_REGION_INIT);
5014 ADD_INT(d, DB_NOLOCKING);
5015 ADD_INT(d, DB_YIELDCPU);
5016 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5017 ADD_INT(d, DB_NOPANIC);
5018#endif
5019
Gregory P. Smith41631e82003-09-21 00:08:14 +00005020#if (DBVER >= 42)
5021 ADD_INT(d, DB_TIME_NOTGRANTED);
5022 ADD_INT(d, DB_TXN_NOT_DURABLE);
5023 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5024 ADD_INT(d, DB_LOG_AUTOREMOVE);
5025 ADD_INT(d, DB_DIRECT_LOG);
5026 ADD_INT(d, DB_DIRECT_DB);
5027 ADD_INT(d, DB_INIT_REP);
5028 ADD_INT(d, DB_ENCRYPT);
5029 ADD_INT(d, DB_CHKSUM);
5030#endif
5031
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005032#if (DBVER >= 41)
5033 ADD_INT(d, DB_ENCRYPT_AES);
5034 ADD_INT(d, DB_AUTO_COMMIT);
5035#else
5036 /* allow berkeleydb 4.1 aware apps to run on older versions */
5037 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5038#endif
5039
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005040 ADD_INT(d, EINVAL);
5041 ADD_INT(d, EACCES);
5042 ADD_INT(d, ENOSPC);
5043 ADD_INT(d, ENOMEM);
5044 ADD_INT(d, EAGAIN);
5045 ADD_INT(d, EBUSY);
5046 ADD_INT(d, EEXIST);
5047 ADD_INT(d, ENOENT);
5048 ADD_INT(d, EPERM);
5049
Barry Warsaw1baa9822003-03-31 19:51:29 +00005050#if (DBVER >= 40)
5051 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5052 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5053#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005054
5055 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005056 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005057 PyDict_SetItemString(d, "DBError", DBError);
5058
5059 /* Some magic to make DBNotFoundError derive from both DBError and
5060 KeyError, since the API only supports using one base class. */
5061 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5062 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
5063 Py_file_input, d, d);
5064 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5065 PyDict_DelItemString(d, "KeyError");
5066
5067
5068 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005069#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005070 PyDict_SetItemString(d, #name, name)
5071
5072#if !INCOMPLETE_IS_WARNING
5073 MAKE_EX(DBIncompleteError);
5074#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005075 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005076 MAKE_EX(DBKeyEmptyError);
5077 MAKE_EX(DBKeyExistError);
5078 MAKE_EX(DBLockDeadlockError);
5079 MAKE_EX(DBLockNotGrantedError);
5080 MAKE_EX(DBOldVersionError);
5081 MAKE_EX(DBRunRecoveryError);
5082 MAKE_EX(DBVerifyBadError);
5083 MAKE_EX(DBNoServerError);
5084 MAKE_EX(DBNoServerHomeError);
5085 MAKE_EX(DBNoServerIDError);
5086#if (DBVER >= 33)
5087 MAKE_EX(DBPageNotFoundError);
5088 MAKE_EX(DBSecondaryBadError);
5089#endif
5090
5091 MAKE_EX(DBInvalidArgError);
5092 MAKE_EX(DBAccessError);
5093 MAKE_EX(DBNoSpaceError);
5094 MAKE_EX(DBNoMemoryError);
5095 MAKE_EX(DBAgainError);
5096 MAKE_EX(DBBusyError);
5097 MAKE_EX(DBFileExistsError);
5098 MAKE_EX(DBNoSuchFileError);
5099 MAKE_EX(DBPermissionsError);
5100
5101#undef MAKE_EX
5102
5103 /* Check for errors */
5104 if (PyErr_Occurred()) {
5105 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005106 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005107 }
5108}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005109
5110/* allow this module to be named _pybsddb so that it can be installed
5111 * and imported on top of python >= 2.3 that includes its own older
5112 * copy of the library named _bsddb without importing the old version. */
5113DL_EXPORT(void) init_pybsddb(void)
5114{
5115 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5116 init_bsddb();
5117}