blob: 2712e3d15a2b453af3cf648ff9d0915f191edaf6 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
Gregory P. Smitha703a212003-11-03 01:04:41 +000087#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000088#include <Python.h>
89#include <db.h>
90
91/* --------------------------------------------------------------------- */
92/* Various macro definitions */
93
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000094/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
95#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000096#if DB_VERSION_MINOR > 9
97#error "eek! DBVER can't handle minor versions > 9"
98#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000100#define PY_BSDDB_VERSION "4.3.0"
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 */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000179static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180static PyObject* DBAgainError; /* EAGAIN */
181static PyObject* DBBusyError; /* EBUSY */
182static PyObject* DBFileExistsError; /* EEXIST */
183static PyObject* DBNoSuchFileError; /* ENOENT */
184static PyObject* DBPermissionsError; /* EPERM */
185
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000186#if (DBVER < 43)
187#define DB_BUFFER_SMALL ENOMEM
188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000189
190
191/* --------------------------------------------------------------------- */
192/* Structure definitions */
193
Gregory P. Smitha703a212003-11-03 01:04:41 +0000194#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
195#define HAVE_WEAKREF
196#else
197#undef HAVE_WEAKREF
198#endif
199
Gregory P. Smith31c50652004-06-28 01:20:40 +0000200/* if Python >= 2.1 better support warnings */
201#if PYTHON_API_VERSION >= 1010
202#define HAVE_WARNINGS
203#else
204#undef HAVE_WARNINGS
205#endif
206
Neal Norwitzb4a55812004-07-09 23:30:57 +0000207#if PYTHON_API_VERSION <= 1007
208 /* 1.5 compatibility */
209#define PyObject_New PyObject_NEW
210#define PyObject_Del PyMem_DEL
211#endif
212
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000213struct behaviourFlags {
214 /* What is the default behaviour when DB->get or DBCursor->get returns a
215 DB_NOTFOUND error? Return None or raise an exception? */
216 unsigned int getReturnsNone : 1;
217 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
218 * returns a DB_NOTFOUND error? Return None or raise an exception? */
219 unsigned int cursorSetReturnsNone : 1;
220};
221
222#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000223#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000225typedef struct {
226 PyObject_HEAD
227 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000228 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000231#ifdef HAVE_WEAKREF
232 PyObject *in_weakreflist; /* List of weak references */
233#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234} DBEnvObject;
235
236
237typedef struct {
238 PyObject_HEAD
239 DB* db;
240 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000241 u_int32_t flags; /* saved flags from open() */
242 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000243 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000244 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245#if (DBVER >= 33)
246 PyObject* associateCallback;
247 int primaryDBType;
248#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000249#ifdef HAVE_WEAKREF
250 PyObject *in_weakreflist; /* List of weak references */
251#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000252} DBObject;
253
254
255typedef struct {
256 PyObject_HEAD
257 DBC* dbc;
258 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000259#ifdef HAVE_WEAKREF
260 PyObject *in_weakreflist; /* List of weak references */
261#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000262} DBCursorObject;
263
264
265typedef struct {
266 PyObject_HEAD
267 DB_TXN* txn;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000268#ifdef HAVE_WEAKREF
269 PyObject *in_weakreflist; /* List of weak references */
270#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000271} DBTxnObject;
272
273
274typedef struct {
275 PyObject_HEAD
276 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000277#ifdef HAVE_WEAKREF
278 PyObject *in_weakreflist; /* List of weak references */
279#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000280} DBLockObject;
281
282
283
284staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
285
286#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
287#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
288#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
289#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
290#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
291
292
293/* --------------------------------------------------------------------- */
294/* Utility macros and functions */
295
296#define RETURN_IF_ERR() \
297 if (makeDBError(err)) { \
298 return NULL; \
299 }
300
301#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
302
Gregory P. Smithe2767172003-11-02 08:06:29 +0000303#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
304 if ((nonNull) == NULL) { \
305 PyObject *errTuple = NULL; \
306 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
307 PyErr_SetObject((pyErrObj), errTuple); \
308 Py_DECREF(errTuple); \
309 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000310 }
311
Gregory P. Smithe2767172003-11-02 08:06:29 +0000312#define CHECK_DB_NOT_CLOSED(dbobj) \
313 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
314
315#define CHECK_ENV_NOT_CLOSED(env) \
316 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000317
318#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000319 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000320
321
322#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
323 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
324
325#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
326
327#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000328 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000329
330
331static int makeDBError(int err);
332
333
334/* Return the access method type of the DBObject */
335static int _DB_get_type(DBObject* self)
336{
337#if (DBVER >= 33)
338 DBTYPE type;
339 int err;
340 err = self->db->get_type(self->db, &type);
341 if (makeDBError(err)) {
342 return -1;
343 }
344 return type;
345#else
346 return self->db->get_type(self->db);
347#endif
348}
349
350
351/* Create a DBT structure (containing key and data values) from Python
352 strings. Returns 1 on success, 0 on an error. */
353static int make_dbt(PyObject* obj, DBT* dbt)
354{
355 CLEAR_DBT(*dbt);
356 if (obj == Py_None) {
357 /* no need to do anything, the structure has already been zeroed */
358 }
359 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
360 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000361 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362 return 0;
363 }
364 return 1;
365}
366
367
368/* Recno and Queue DBs can have integer keys. This function figures out
369 what's been given, verifies that it's allowed, and then makes the DBT.
370
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000371 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000372static int
373make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000374{
375 db_recno_t recno;
376 int type;
377
378 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000379 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000380 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000381 if (type == -1)
382 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000383 if (type == DB_RECNO || type == DB_QUEUE) {
384 PyErr_SetString(
385 PyExc_TypeError,
386 "None keys not allowed for Recno and Queue DB's");
387 return 0;
388 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000389 /* no need to do anything, the structure has already been zeroed */
390 }
391
392 else if (PyString_Check(keyobj)) {
393 /* verify access method type */
394 type = _DB_get_type(self);
395 if (type == -1)
396 return 0;
397 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000398 PyErr_SetString(
399 PyExc_TypeError,
400 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000401 return 0;
402 }
403
404 key->data = PyString_AS_STRING(keyobj);
405 key->size = PyString_GET_SIZE(keyobj);
406 }
407
408 else if (PyInt_Check(keyobj)) {
409 /* verify access method type */
410 type = _DB_get_type(self);
411 if (type == -1)
412 return 0;
413 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414 /* if BTREE then an Integer key is allowed with the
415 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416 *pflags |= DB_SET_RECNO;
417 }
418 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000419 PyErr_SetString(
420 PyExc_TypeError,
421 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000422 return 0;
423 }
424
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000425 /* Make a key out of the requested recno, use allocated space so DB
426 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000427 recno = PyInt_AS_LONG(keyobj);
428 key->data = malloc(sizeof(db_recno_t));
429 if (key->data == NULL) {
430 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
431 return 0;
432 }
433 key->ulen = key->size = sizeof(db_recno_t);
434 memcpy(key->data, &recno, sizeof(db_recno_t));
435 key->flags = DB_DBT_REALLOC;
436 }
437 else {
438 PyErr_Format(PyExc_TypeError,
439 "String or Integer object expected for key, %s found",
440 keyobj->ob_type->tp_name);
441 return 0;
442 }
443
444 return 1;
445}
446
447
448/* Add partial record access to an existing DBT data struct.
449 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
450 and the data storage/retrieval will be done using dlen and doff. */
451static int add_partial_dbt(DBT* d, int dlen, int doff) {
452 /* if neither were set we do nothing (-1 is the default value) */
453 if ((dlen == -1) && (doff == -1)) {
454 return 1;
455 }
456
457 if ((dlen < 0) || (doff < 0)) {
458 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
459 return 0;
460 }
461
462 d->flags = d->flags | DB_DBT_PARTIAL;
463 d->dlen = (unsigned int) dlen;
464 d->doff = (unsigned int) doff;
465 return 1;
466}
467
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000468/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
469/* TODO: make this use the native libc strlcpy() when available (BSD) */
470unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
471{
472 unsigned int srclen, copylen;
473
474 srclen = strlen(src);
475 if (n <= 0)
476 return srclen;
477 copylen = (srclen > n-1) ? n-1 : srclen;
478 /* populate dest[0] thru dest[copylen-1] */
479 memcpy(dest, src, copylen);
480 /* guarantee null termination */
481 dest[copylen] = 0;
482
483 return srclen;
484}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000485
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000486/* Callback used to save away more information about errors from the DB
487 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000488static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000489#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000490static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491#else
492static void _db_errorCallback(const DB_ENV *db_env,
493 const char* prefix, const char* msg)
494#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000495{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000496 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000497}
498
499
500/* make a nice exception object to raise for errors. */
501static int makeDBError(int err)
502{
503 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000504 PyObject *errObj = NULL;
505 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000506 int exceptionRaised = 0;
507
508 switch (err) {
509 case 0: /* successful, no error */ break;
510
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000511#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512 case DB_INCOMPLETE:
513#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000515 if (_db_errmsg[0]) {
516 strcat(errTxt, " -- ");
517 strcat(errTxt, _db_errmsg);
518 _db_errmsg[0] = 0;
519 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000520#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
522#else
523 fprintf(stderr, errTxt);
524 fprintf(stderr, "\n");
525#endif
526
527#else /* do an exception instead */
528 errObj = DBIncompleteError;
529#endif
530 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000531#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000532
533 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
534 case DB_KEYEXIST: errObj = DBKeyExistError; break;
535 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
536 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
537 case DB_NOTFOUND: errObj = DBNotFoundError; break;
538 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
539 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
540 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
541 case DB_NOSERVER: errObj = DBNoServerError; break;
542 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
543 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
544#if (DBVER >= 33)
545 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
546 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
547#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000548 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000550#if (DBVER >= 43)
551 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
552 case ENOMEM: errObj = PyExc_MemoryError; break;
553#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000554 case EINVAL: errObj = DBInvalidArgError; break;
555 case EACCES: errObj = DBAccessError; break;
556 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000557 case EAGAIN: errObj = DBAgainError; break;
558 case EBUSY : errObj = DBBusyError; break;
559 case EEXIST: errObj = DBFileExistsError; break;
560 case ENOENT: errObj = DBNoSuchFileError; break;
561 case EPERM : errObj = DBPermissionsError; break;
562
563 default: errObj = DBError; break;
564 }
565
566 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000567 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000568 if (_db_errmsg[0]) {
569 strcat(errTxt, " -- ");
570 strcat(errTxt, _db_errmsg);
571 _db_errmsg[0] = 0;
572 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000573
574 errTuple = Py_BuildValue("(is)", err, errTxt);
575 PyErr_SetObject(errObj, errTuple);
576 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000577 }
578
579 return ((errObj != NULL) || exceptionRaised);
580}
581
582
583
584/* set a type exception */
585static void makeTypeError(char* expected, PyObject* found)
586{
587 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
588 expected, found->ob_type->tp_name);
589}
590
591
592/* verify that an obj is either None or a DBTxn, and set the txn pointer */
593static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
594{
595 if (txnobj == Py_None || txnobj == NULL) {
596 *txn = NULL;
597 return 1;
598 }
599 if (DBTxnObject_Check(txnobj)) {
600 *txn = ((DBTxnObject*)txnobj)->txn;
601 return 1;
602 }
603 else
604 makeTypeError("DBTxn", txnobj);
605 return 0;
606}
607
608
609/* Delete a key from a database
610 Returns 0 on success, -1 on an error. */
611static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
612{
613 int err;
614
615 MYDB_BEGIN_ALLOW_THREADS;
616 err = self->db->del(self->db, txn, key, 0);
617 MYDB_END_ALLOW_THREADS;
618 if (makeDBError(err)) {
619 return -1;
620 }
621 self->haveStat = 0;
622 return 0;
623}
624
625
626/* Store a key into a database
627 Returns 0 on success, -1 on an error. */
628static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
629{
630 int err;
631
632 MYDB_BEGIN_ALLOW_THREADS;
633 err = self->db->put(self->db, txn, key, data, flags);
634 MYDB_END_ALLOW_THREADS;
635 if (makeDBError(err)) {
636 return -1;
637 }
638 self->haveStat = 0;
639 return 0;
640}
641
642/* Get a key/data pair from a cursor */
643static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
644 PyObject *args, PyObject *kwargs, char *format)
645{
646 int err;
647 PyObject* retval = NULL;
648 DBT key, data;
649 int dlen = -1;
650 int doff = -1;
651 int flags = 0;
652 char* kwnames[] = { "flags", "dlen", "doff", NULL };
653
654 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
655 &flags, &dlen, &doff))
656 return NULL;
657
658 CHECK_CURSOR_NOT_CLOSED(self);
659
660 flags |= extra_flags;
661 CLEAR_DBT(key);
662 CLEAR_DBT(data);
663 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
664 /* Tell BerkeleyDB to malloc the return value (thread safe) */
665 data.flags = DB_DBT_MALLOC;
666 key.flags = DB_DBT_MALLOC;
667 }
668 if (!add_partial_dbt(&data, dlen, doff))
669 return NULL;
670
671 MYDB_BEGIN_ALLOW_THREADS;
672 err = self->dbc->c_get(self->dbc, &key, &data, flags);
673 MYDB_END_ALLOW_THREADS;
674
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000675 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000676 Py_INCREF(Py_None);
677 retval = Py_None;
678 }
679 else if (makeDBError(err)) {
680 retval = NULL;
681 }
682 else { /* otherwise, success! */
683
684 /* if Recno or Queue, return the key as an Int */
685 switch (_DB_get_type(self->mydb)) {
686 case -1:
687 retval = NULL;
688 break;
689
690 case DB_RECNO:
691 case DB_QUEUE:
692 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
693 data.data, data.size);
694 break;
695 case DB_HASH:
696 case DB_BTREE:
697 default:
698 retval = Py_BuildValue("s#s#", key.data, key.size,
699 data.data, data.size);
700 break;
701 }
702 }
703 if (!err) {
704 FREE_DBT(key);
705 FREE_DBT(data);
706 }
707 return retval;
708}
709
710
711/* add an integer to a dictionary using the given name as a key */
712static void _addIntToDict(PyObject* dict, char *name, int value)
713{
714 PyObject* v = PyInt_FromLong((long) value);
715 if (!v || PyDict_SetItemString(dict, name, v))
716 PyErr_Clear();
717
718 Py_XDECREF(v);
719}
720
721
722
723
724/* --------------------------------------------------------------------- */
725/* Allocators and deallocators */
726
727static DBObject*
728newDBObject(DBEnvObject* arg, int flags)
729{
730 DBObject* self;
731 DB_ENV* db_env = NULL;
732 int err;
733
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000734 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 if (self == NULL)
736 return NULL;
737
738 self->haveStat = 0;
739 self->flags = 0;
740 self->setflags = 0;
741 self->myenvobj = NULL;
742#if (DBVER >= 33)
743 self->associateCallback = NULL;
744 self->primaryDBType = 0;
745#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000746#ifdef HAVE_WEAKREF
747 self->in_weakreflist = NULL;
748#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000749
750 /* keep a reference to our python DBEnv object */
751 if (arg) {
752 Py_INCREF(arg);
753 self->myenvobj = arg;
754 db_env = arg->db_env;
755 }
756
757 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000758 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000760 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
761 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000762
763 MYDB_BEGIN_ALLOW_THREADS;
764 err = db_create(&self->db, db_env, flags);
765 self->db->set_errcall(self->db, _db_errorCallback);
766#if (DBVER >= 33)
767 self->db->app_private = (void*)self;
768#endif
769 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000770 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
771 * list so that a DBEnv can refuse to close without aborting any open
772 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000773 if (makeDBError(err)) {
774 if (self->myenvobj) {
775 Py_DECREF(self->myenvobj);
776 self->myenvobj = NULL;
777 }
778 self = NULL;
779 }
780 return self;
781}
782
783
784static void
785DB_dealloc(DBObject* self)
786{
787 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000788 /* avoid closing a DB when its DBEnv has been closed out from under
789 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000791 (self->myenvobj && self->myenvobj->db_env))
792 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000793 MYDB_BEGIN_ALLOW_THREADS;
794 self->db->close(self->db, 0);
795 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000796#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797 } else {
798 PyErr_Warn(PyExc_RuntimeWarning,
799 "DB could not be closed in destructor: DBEnv already closed");
800#endif
801 }
802 self->db = NULL;
803 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000804#ifdef HAVE_WEAKREF
805 if (self->in_weakreflist != NULL) {
806 PyObject_ClearWeakRefs((PyObject *) self);
807 }
808#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809 if (self->myenvobj) {
810 Py_DECREF(self->myenvobj);
811 self->myenvobj = NULL;
812 }
813#if (DBVER >= 33)
814 if (self->associateCallback != NULL) {
815 Py_DECREF(self->associateCallback);
816 self->associateCallback = NULL;
817 }
818#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000819 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000820}
821
822
823static DBCursorObject*
824newDBCursorObject(DBC* dbc, DBObject* db)
825{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000826 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827 if (self == NULL)
828 return NULL;
829
830 self->dbc = dbc;
831 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000832#ifdef HAVE_WEAKREF
833 self->in_weakreflist = NULL;
834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 Py_INCREF(self->mydb);
836 return self;
837}
838
839
840static void
841DBCursor_dealloc(DBCursorObject* self)
842{
843 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000844
845#ifdef HAVE_WEAKREF
846 if (self->in_weakreflist != NULL) {
847 PyObject_ClearWeakRefs((PyObject *) self);
848 }
849#endif
850
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 if (self->dbc != NULL) {
852 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000853 /* If the underlying database has been closed, we don't
854 need to do anything. If the environment has been closed
855 we need to leak, as BerkeleyDB will crash trying to access
856 the environment. There was an exception when the
857 user closed the environment even though there still was
858 a database open. */
859 if (self->mydb->db && self->mydb->myenvobj &&
860 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000861 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862 self->dbc = NULL;
863 MYDB_END_ALLOW_THREADS;
864 }
865 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000866 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867}
868
869
870static DBEnvObject*
871newDBEnvObject(int flags)
872{
873 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000874 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (self == NULL)
876 return NULL;
877
878 self->closed = 1;
879 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000880 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
881 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000882#ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885
886 MYDB_BEGIN_ALLOW_THREADS;
887 err = db_env_create(&self->db_env, flags);
888 MYDB_END_ALLOW_THREADS;
889 if (makeDBError(err)) {
890 self = NULL;
891 }
892 else {
893 self->db_env->set_errcall(self->db_env, _db_errorCallback);
894 }
895 return self;
896}
897
898
899static void
900DBEnv_dealloc(DBEnvObject* self)
901{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000902#ifdef HAVE_WEAKREF
903 if (self->in_weakreflist != NULL) {
904 PyObject_ClearWeakRefs((PyObject *) self);
905 }
906#endif
907
Neal Norwitz37b0c1d2004-07-09 23:33:06 +0000908 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909 MYDB_BEGIN_ALLOW_THREADS;
910 self->db_env->close(self->db_env, 0);
911 MYDB_END_ALLOW_THREADS;
912 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000913 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000914}
915
916
917static DBTxnObject*
918newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
919{
920 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000921 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922 if (self == NULL)
923 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000924#ifdef HAVE_WEAKREF
925 self->in_weakreflist = NULL;
926#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927
928 MYDB_BEGIN_ALLOW_THREADS;
929#if (DBVER >= 40)
930 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
931#else
932 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
933#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000934 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
935 * list so that a DBEnv can refuse to close without aborting any open
936 * open DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937 MYDB_END_ALLOW_THREADS;
938 if (makeDBError(err)) {
939 self = NULL;
940 }
941 return self;
942}
943
944
945static void
946DBTxn_dealloc(DBTxnObject* self)
947{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000948#ifdef HAVE_WEAKREF
949 if (self->in_weakreflist != NULL) {
950 PyObject_ClearWeakRefs((PyObject *) self);
951 }
952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953
Gregory P. Smith31c50652004-06-28 01:20:40 +0000954#ifdef HAVE_WARNINGS
955 if (self->txn) {
956 /* it hasn't been finalized, abort it! */
957 MYDB_BEGIN_ALLOW_THREADS;
958#if (DBVER >= 40)
959 self->txn->abort(self->txn);
960#else
961 txn_abort(self->txn);
962#endif
963 MYDB_END_ALLOW_THREADS;
964 PyErr_Warn(PyExc_RuntimeWarning,
965 "DBTxn aborted in destructor. No prior commit() or abort().");
966 }
967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970}
971
972
973static DBLockObject*
974newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
975 db_lockmode_t lock_mode, int flags)
976{
977 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000978 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 if (self == NULL)
980 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000981#ifdef HAVE_WEAKREF
982 self->in_weakreflist = NULL;
983#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000984
985 MYDB_BEGIN_ALLOW_THREADS;
986#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000987 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
988 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000989#else
990 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
991#endif
992 MYDB_END_ALLOW_THREADS;
993 if (makeDBError(err)) {
994 self = NULL;
995 }
996
997 return self;
998}
999
1000
1001static void
1002DBLock_dealloc(DBLockObject* self)
1003{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001004#ifdef HAVE_WEAKREF
1005 if (self->in_weakreflist != NULL) {
1006 PyObject_ClearWeakRefs((PyObject *) self);
1007 }
1008#endif
1009 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001012}
1013
1014
1015/* --------------------------------------------------------------------- */
1016/* DB methods */
1017
1018static PyObject*
1019DB_append(DBObject* self, PyObject* args)
1020{
1021 PyObject* txnobj = NULL;
1022 PyObject* dataobj;
1023 db_recno_t recno;
1024 DBT key, data;
1025 DB_TXN *txn = NULL;
1026
1027 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1028 return NULL;
1029
1030 CHECK_DB_NOT_CLOSED(self);
1031
1032 /* make a dummy key out of a recno */
1033 recno = 0;
1034 CLEAR_DBT(key);
1035 key.data = &recno;
1036 key.size = sizeof(recno);
1037 key.ulen = key.size;
1038 key.flags = DB_DBT_USERMEM;
1039
1040 if (!make_dbt(dataobj, &data)) return NULL;
1041 if (!checkTxnObj(txnobj, &txn)) return NULL;
1042
1043 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1044 return NULL;
1045
1046 return PyInt_FromLong(recno);
1047}
1048
1049
1050#if (DBVER >= 33)
1051
1052static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001053_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1054 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055{
1056 int retval = DB_DONOTINDEX;
1057 DBObject* secondaryDB = (DBObject*)db->app_private;
1058 PyObject* callback = secondaryDB->associateCallback;
1059 int type = secondaryDB->primaryDBType;
1060 PyObject* key;
1061 PyObject* data;
1062 PyObject* args;
1063 PyObject* result;
1064
1065
1066 if (callback != NULL) {
1067 MYDB_BEGIN_BLOCK_THREADS;
1068
1069 if (type == DB_RECNO || type == DB_QUEUE) {
1070 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1071 }
1072 else {
1073 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1074 }
1075 data = PyString_FromStringAndSize(priData->data, priData->size);
1076 args = PyTuple_New(2);
1077 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1078 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1079
1080 result = PyEval_CallObject(callback, args);
1081
1082 if (result == NULL) {
1083 PyErr_Print();
1084 }
1085 else if (result == Py_None) {
1086 retval = DB_DONOTINDEX;
1087 }
1088 else if (PyInt_Check(result)) {
1089 retval = PyInt_AsLong(result);
1090 }
1091 else if (PyString_Check(result)) {
1092 char* data;
1093 int size;
1094
1095 CLEAR_DBT(*secKey);
1096#if PYTHON_API_VERSION <= 1007
1097 /* 1.5 compatibility */
1098 size = PyString_Size(result);
1099 data = PyString_AsString(result);
1100#else
1101 PyString_AsStringAndSize(result, &data, &size);
1102#endif
1103 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1104 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001105 if (secKey->data) {
1106 memcpy(secKey->data, data, size);
1107 secKey->size = size;
1108 retval = 0;
1109 }
1110 else {
1111 PyErr_SetString(PyExc_MemoryError,
1112 "malloc failed in _db_associateCallback");
1113 PyErr_Print();
1114 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001115 }
1116 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001117 PyErr_SetString(
1118 PyExc_TypeError,
1119 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001120 PyErr_Print();
1121 }
1122
1123 Py_DECREF(args);
1124 if (result) {
1125 Py_DECREF(result);
1126 }
1127
1128 MYDB_END_BLOCK_THREADS;
1129 }
1130 return retval;
1131}
1132
1133
1134static PyObject*
1135DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1136{
1137 int err, flags=0;
1138 DBObject* secondaryDB;
1139 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001140#if (DBVER >= 41)
1141 PyObject *txnobj = NULL;
1142 DB_TXN *txn = NULL;
1143 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1144#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001145 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001146#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001148#if (DBVER >= 41)
1149 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1150 &secondaryDB, &callback, &flags,
1151 &txnobj)) {
1152#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001154 &secondaryDB, &callback, &flags)) {
1155#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001156 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001157 }
1158
1159#if (DBVER >= 41)
1160 if (!checkTxnObj(txnobj, &txn)) return NULL;
1161#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001162
1163 CHECK_DB_NOT_CLOSED(self);
1164 if (!DBObject_Check(secondaryDB)) {
1165 makeTypeError("DB", (PyObject*)secondaryDB);
1166 return NULL;
1167 }
1168 if (callback == Py_None) {
1169 callback = NULL;
1170 }
1171 else if (!PyCallable_Check(callback)) {
1172 makeTypeError("Callable", callback);
1173 return NULL;
1174 }
1175
1176 /* Save a reference to the callback in the secondary DB. */
1177 if (self->associateCallback != NULL) {
1178 Py_DECREF(self->associateCallback);
1179 }
1180 Py_INCREF(callback);
1181 secondaryDB->associateCallback = callback;
1182 secondaryDB->primaryDBType = _DB_get_type(self);
1183
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001184 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1185 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1186 * The global interepreter lock is not initialized until the first
1187 * thread is created using thread.start_new_thread() or fork() is
1188 * called. that would cause the ALLOW_THREADS here to segfault due
1189 * to a null pointer reference if no threads or child processes
1190 * have been created. This works around that and is a no-op if
1191 * threads have already been initialized.
1192 * (see pybsddb-users mailing list post on 2002-08-07)
1193 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001194#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001195 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001196#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001197 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001198#if (DBVER >= 41)
1199 err = self->db->associate(self->db,
1200 txn,
1201 secondaryDB->db,
1202 _db_associateCallback,
1203 flags);
1204#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 err = self->db->associate(self->db,
1206 secondaryDB->db,
1207 _db_associateCallback,
1208 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001209#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001210 MYDB_END_ALLOW_THREADS;
1211
1212 if (err) {
1213 Py_DECREF(self->associateCallback);
1214 self->associateCallback = NULL;
1215 secondaryDB->primaryDBType = 0;
1216 }
1217
1218 RETURN_IF_ERR();
1219 RETURN_NONE();
1220}
1221
1222
1223#endif
1224
1225
1226static PyObject*
1227DB_close(DBObject* self, PyObject* args)
1228{
1229 int err, flags=0;
1230 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1231 return NULL;
1232 if (self->db != NULL) {
1233 if (self->myenvobj)
1234 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001235 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236 self->db = NULL;
1237 RETURN_IF_ERR();
1238 }
1239 RETURN_NONE();
1240}
1241
1242
1243#if (DBVER >= 32)
1244static PyObject*
1245_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1246{
1247 int err, flags=0, type;
1248 PyObject* txnobj = NULL;
1249 PyObject* retval = NULL;
1250 DBT key, data;
1251 DB_TXN *txn = NULL;
1252 char* kwnames[] = { "txn", "flags", NULL };
1253
1254 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1255 &txnobj, &flags))
1256 return NULL;
1257
1258 CHECK_DB_NOT_CLOSED(self);
1259 type = _DB_get_type(self);
1260 if (type == -1)
1261 return NULL;
1262 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001263 PyErr_SetString(PyExc_TypeError,
1264 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265 return NULL;
1266 }
1267 if (!checkTxnObj(txnobj, &txn))
1268 return NULL;
1269
1270 CLEAR_DBT(key);
1271 CLEAR_DBT(data);
1272 if (CHECK_DBFLAG(self, DB_THREAD)) {
1273 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1274 data.flags = DB_DBT_MALLOC;
1275 key.flags = DB_DBT_MALLOC;
1276 }
1277
1278 MYDB_BEGIN_ALLOW_THREADS;
1279 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1280 MYDB_END_ALLOW_THREADS;
1281
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001282 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001283 err = 0;
1284 Py_INCREF(Py_None);
1285 retval = Py_None;
1286 }
1287 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001288 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1289 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290 FREE_DBT(key);
1291 FREE_DBT(data);
1292 }
1293
1294 RETURN_IF_ERR();
1295 return retval;
1296}
1297
1298static PyObject*
1299DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1300{
1301 return _DB_consume(self, args, kwargs, DB_CONSUME);
1302}
1303
1304static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001305DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1306 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001307{
1308 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1309}
1310#endif
1311
1312
1313
1314static PyObject*
1315DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1316{
1317 int err, flags=0;
1318 DBC* dbc;
1319 PyObject* txnobj = NULL;
1320 DB_TXN *txn = NULL;
1321 char* kwnames[] = { "txn", "flags", NULL };
1322
1323 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1324 &txnobj, &flags))
1325 return NULL;
1326 CHECK_DB_NOT_CLOSED(self);
1327 if (!checkTxnObj(txnobj, &txn))
1328 return NULL;
1329
1330 MYDB_BEGIN_ALLOW_THREADS;
1331 err = self->db->cursor(self->db, txn, &dbc, flags);
1332 MYDB_END_ALLOW_THREADS;
1333 RETURN_IF_ERR();
1334 return (PyObject*) newDBCursorObject(dbc, self);
1335}
1336
1337
1338static PyObject*
1339DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1340{
1341 PyObject* txnobj = NULL;
1342 int flags = 0;
1343 PyObject* keyobj;
1344 DBT key;
1345 DB_TXN *txn = NULL;
1346 char* kwnames[] = { "key", "txn", "flags", NULL };
1347
1348 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1349 &keyobj, &txnobj, &flags))
1350 return NULL;
1351 CHECK_DB_NOT_CLOSED(self);
1352 if (!make_key_dbt(self, keyobj, &key, NULL))
1353 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001354 if (!checkTxnObj(txnobj, &txn)) {
1355 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001356 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001357 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001358
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001359 if (-1 == _DB_delete(self, txn, &key, 0)) {
1360 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001361 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001362 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363
1364 FREE_DBT(key);
1365 RETURN_NONE();
1366}
1367
1368
1369static PyObject*
1370DB_fd(DBObject* self, PyObject* args)
1371{
1372 int err, the_fd;
1373
1374 if (!PyArg_ParseTuple(args,":fd"))
1375 return NULL;
1376 CHECK_DB_NOT_CLOSED(self);
1377
1378 MYDB_BEGIN_ALLOW_THREADS;
1379 err = self->db->fd(self->db, &the_fd);
1380 MYDB_END_ALLOW_THREADS;
1381 RETURN_IF_ERR();
1382 return PyInt_FromLong(the_fd);
1383}
1384
1385
1386static PyObject*
1387DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1388{
1389 int err, flags=0;
1390 PyObject* txnobj = NULL;
1391 PyObject* keyobj;
1392 PyObject* dfltobj = NULL;
1393 PyObject* retval = NULL;
1394 int dlen = -1;
1395 int doff = -1;
1396 DBT key, data;
1397 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001398 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001399
1400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001401 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1402 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403 return NULL;
1404
1405 CHECK_DB_NOT_CLOSED(self);
1406 if (!make_key_dbt(self, keyobj, &key, &flags))
1407 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001408 if (!checkTxnObj(txnobj, &txn)) {
1409 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001411 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412
1413 CLEAR_DBT(data);
1414 if (CHECK_DBFLAG(self, DB_THREAD)) {
1415 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1416 data.flags = DB_DBT_MALLOC;
1417 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001418 if (!add_partial_dbt(&data, dlen, doff)) {
1419 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001420 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001421 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422
1423 MYDB_BEGIN_ALLOW_THREADS;
1424 err = self->db->get(self->db, txn, &key, &data, flags);
1425 MYDB_END_ALLOW_THREADS;
1426
1427 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1428 err = 0;
1429 Py_INCREF(dfltobj);
1430 retval = dfltobj;
1431 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001432 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001433 err = 0;
1434 Py_INCREF(Py_None);
1435 retval = Py_None;
1436 }
1437 else if (!err) {
1438 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001439 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1440 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441 else /* return just the data */
1442 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443 FREE_DBT(data);
1444 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001445 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001446
1447 RETURN_IF_ERR();
1448 return retval;
1449}
1450
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001451#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001452static PyObject*
1453DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1454{
1455 int err, flags=0;
1456 PyObject* txnobj = NULL;
1457 PyObject* keyobj;
1458 PyObject* dfltobj = NULL;
1459 PyObject* retval = NULL;
1460 int dlen = -1;
1461 int doff = -1;
1462 DBT key, pkey, data;
1463 DB_TXN *txn = NULL;
1464 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1465
1466 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1467 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1468 &doff))
1469 return NULL;
1470
1471 CHECK_DB_NOT_CLOSED(self);
1472 if (!make_key_dbt(self, keyobj, &key, &flags))
1473 return NULL;
1474 if (!checkTxnObj(txnobj, &txn)) {
1475 FREE_DBT(key);
1476 return NULL;
1477 }
1478
1479 CLEAR_DBT(data);
1480 if (CHECK_DBFLAG(self, DB_THREAD)) {
1481 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1482 data.flags = DB_DBT_MALLOC;
1483 }
1484 if (!add_partial_dbt(&data, dlen, doff)) {
1485 FREE_DBT(key);
1486 return NULL;
1487 }
1488
1489 CLEAR_DBT(pkey);
1490 pkey.flags = DB_DBT_MALLOC;
1491
1492 MYDB_BEGIN_ALLOW_THREADS;
1493 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1494 MYDB_END_ALLOW_THREADS;
1495
1496 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1497 err = 0;
1498 Py_INCREF(dfltobj);
1499 retval = dfltobj;
1500 }
1501 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1502 err = 0;
1503 Py_INCREF(Py_None);
1504 retval = Py_None;
1505 }
1506 else if (!err) {
1507 PyObject *pkeyObj;
1508 PyObject *dataObj;
1509 dataObj = PyString_FromStringAndSize(data.data, data.size);
1510
1511 if (self->primaryDBType == DB_RECNO ||
1512 self->primaryDBType == DB_QUEUE)
1513 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1514 else
1515 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1516
1517 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1518 {
1519 PyObject *keyObj;
1520 int type = _DB_get_type(self);
1521 if (type == DB_RECNO || type == DB_QUEUE)
1522 keyObj = PyInt_FromLong(*(long *)key.data);
1523 else
1524 keyObj = PyString_FromStringAndSize(key.data, key.size);
1525 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1526 }
1527 else /* return just the pkey and data */
1528 {
1529 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1530 }
1531 FREE_DBT(pkey);
1532 FREE_DBT(data);
1533 }
1534 FREE_DBT(key);
1535
1536 RETURN_IF_ERR();
1537 return retval;
1538}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001539#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001540
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001541
1542/* Return size of entry */
1543static PyObject*
1544DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1545{
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* retval = NULL;
1550 DBT key, data;
1551 DB_TXN *txn = NULL;
1552 char* kwnames[] = { "key", "txn", NULL };
1553
1554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1555 &keyobj, &txnobj))
1556 return NULL;
1557 CHECK_DB_NOT_CLOSED(self);
1558 if (!make_key_dbt(self, keyobj, &key, &flags))
1559 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001560 if (!checkTxnObj(txnobj, &txn)) {
1561 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001562 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001563 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001564 CLEAR_DBT(data);
1565
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001566 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1567 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001568 data.flags = DB_DBT_USERMEM;
1569 data.ulen = 0;
1570 MYDB_BEGIN_ALLOW_THREADS;
1571 err = self->db->get(self->db, txn, &key, &data, flags);
1572 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001573 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001574 retval = PyInt_FromLong((long)data.size);
1575 err = 0;
1576 }
1577
1578 FREE_DBT(key);
1579 FREE_DBT(data);
1580 RETURN_IF_ERR();
1581 return retval;
1582}
1583
1584
1585static PyObject*
1586DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1587{
1588 int err, flags=0;
1589 PyObject* txnobj = NULL;
1590 PyObject* keyobj;
1591 PyObject* dataobj;
1592 PyObject* retval = NULL;
1593 DBT key, data;
1594 DB_TXN *txn = NULL;
1595 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1596
1597
1598 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1599 &keyobj, &dataobj, &txnobj, &flags))
1600 return NULL;
1601
1602 CHECK_DB_NOT_CLOSED(self);
1603 if (!make_key_dbt(self, keyobj, &key, NULL))
1604 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001605 if ( !make_dbt(dataobj, &data) ||
1606 !checkTxnObj(txnobj, &txn) )
1607 {
1608 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001609 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001611
1612 flags |= DB_GET_BOTH;
1613
1614 if (CHECK_DBFLAG(self, DB_THREAD)) {
1615 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1616 data.flags = DB_DBT_MALLOC;
1617 /* TODO: Is this flag needed? We're passing a data object that should
1618 match what's in the DB, so there should be no need to malloc.
1619 We run the risk of freeing something twice! Check this. */
1620 }
1621
1622 MYDB_BEGIN_ALLOW_THREADS;
1623 err = self->db->get(self->db, txn, &key, &data, flags);
1624 MYDB_END_ALLOW_THREADS;
1625
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001626 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001627 err = 0;
1628 Py_INCREF(Py_None);
1629 retval = Py_None;
1630 }
1631 else if (!err) {
1632 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1633 FREE_DBT(data); /* Only if retrieval was successful */
1634 }
1635
1636 FREE_DBT(key);
1637 RETURN_IF_ERR();
1638 return retval;
1639}
1640
1641
1642static PyObject*
1643DB_get_byteswapped(DBObject* self, PyObject* args)
1644{
1645#if (DBVER >= 33)
1646 int err = 0;
1647#endif
1648 int retval = -1;
1649
1650 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1651 return NULL;
1652 CHECK_DB_NOT_CLOSED(self);
1653
1654#if (DBVER >= 33)
1655 MYDB_BEGIN_ALLOW_THREADS;
1656 err = self->db->get_byteswapped(self->db, &retval);
1657 MYDB_END_ALLOW_THREADS;
1658 RETURN_IF_ERR();
1659#else
1660 MYDB_BEGIN_ALLOW_THREADS;
1661 retval = self->db->get_byteswapped(self->db);
1662 MYDB_END_ALLOW_THREADS;
1663#endif
1664 return PyInt_FromLong(retval);
1665}
1666
1667
1668static PyObject*
1669DB_get_type(DBObject* self, PyObject* args)
1670{
1671 int type;
1672
1673 if (!PyArg_ParseTuple(args,":get_type"))
1674 return NULL;
1675 CHECK_DB_NOT_CLOSED(self);
1676
1677 MYDB_BEGIN_ALLOW_THREADS;
1678 type = _DB_get_type(self);
1679 MYDB_END_ALLOW_THREADS;
1680 if (type == -1)
1681 return NULL;
1682 return PyInt_FromLong(type);
1683}
1684
1685
1686static PyObject*
1687DB_join(DBObject* self, PyObject* args)
1688{
1689 int err, flags=0;
1690 int length, x;
1691 PyObject* cursorsObj;
1692 DBC** cursors;
1693 DBC* dbc;
1694
1695
1696 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1697 return NULL;
1698
1699 CHECK_DB_NOT_CLOSED(self);
1700
1701 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001702 PyErr_SetString(PyExc_TypeError,
1703 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
1705 }
1706
1707 length = PyObject_Length(cursorsObj);
1708 cursors = malloc((length+1) * sizeof(DBC*));
1709 cursors[length] = NULL;
1710 for (x=0; x<length; x++) {
1711 PyObject* item = PySequence_GetItem(cursorsObj, x);
1712 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001713 PyErr_SetString(PyExc_TypeError,
1714 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001715 free(cursors);
1716 return NULL;
1717 }
1718 cursors[x] = ((DBCursorObject*)item)->dbc;
1719 }
1720
1721 MYDB_BEGIN_ALLOW_THREADS;
1722 err = self->db->join(self->db, cursors, &dbc, flags);
1723 MYDB_END_ALLOW_THREADS;
1724 free(cursors);
1725 RETURN_IF_ERR();
1726
Gregory P. Smith7441e652003-11-03 21:35:31 +00001727 /* FIXME: this is a buggy interface. The returned cursor
1728 contains internal references to the passed in cursors
1729 but does not hold python references to them or prevent
1730 them from being closed prematurely. This can cause
1731 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732 return (PyObject*) newDBCursorObject(dbc, self);
1733}
1734
1735
1736static PyObject*
1737DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1738{
1739 int err, flags=0;
1740 PyObject* txnobj = NULL;
1741 PyObject* keyobj;
1742 DBT key;
1743 DB_TXN *txn = NULL;
1744 DB_KEY_RANGE range;
1745 char* kwnames[] = { "key", "txn", "flags", NULL };
1746
1747 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1748 &keyobj, &txnobj, &flags))
1749 return NULL;
1750 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001751 if (!make_dbt(keyobj, &key))
1752 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001753 return NULL;
1754 if (!checkTxnObj(txnobj, &txn))
1755 return NULL;
1756
1757 MYDB_BEGIN_ALLOW_THREADS;
1758 err = self->db->key_range(self->db, txn, &key, &range, flags);
1759 MYDB_END_ALLOW_THREADS;
1760
1761 RETURN_IF_ERR();
1762 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1763}
1764
1765
1766static PyObject*
1767DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1768{
1769 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1770 char* filename = NULL;
1771 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001772#if (DBVER >= 41)
1773 PyObject *txnobj = NULL;
1774 DB_TXN *txn = NULL;
1775 /* with dbname */
1776 char* kwnames[] = {
1777 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1778 /* without dbname */
1779 char* kwnames_basic[] = {
1780 "filename", "dbtype", "flags", "mode", "txn", NULL};
1781#else
1782 /* with dbname */
1783 char* kwnames[] = {
1784 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1785 /* without dbname */
1786 char* kwnames_basic[] = {
1787 "filename", "dbtype", "flags", "mode", NULL};
1788#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001789
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001790#if (DBVER >= 41)
1791 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1792 &filename, &dbname, &type, &flags, &mode,
1793 &txnobj))
1794#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001795 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001796 &filename, &dbname, &type, &flags,
1797 &mode))
1798#endif
1799 {
1800 PyErr_Clear();
1801 type = DB_UNKNOWN; flags = 0; mode = 0660;
1802 filename = NULL; dbname = NULL;
1803#if (DBVER >= 41)
1804 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1805 kwnames_basic,
1806 &filename, &type, &flags, &mode,
1807 &txnobj))
1808 return NULL;
1809#else
1810 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1811 kwnames_basic,
1812 &filename, &type, &flags, &mode))
1813 return NULL;
1814#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001815 }
1816
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001817#if (DBVER >= 41)
1818 if (!checkTxnObj(txnobj, &txn)) return NULL;
1819#endif
1820
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 if (NULL == self->db) {
1822 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1823 "Cannot call open() twice for DB object"));
1824 return NULL;
1825 }
1826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001827#if 0 && (DBVER >= 41)
1828 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1829 && (self->myenvobj->flags & DB_INIT_TXN))
1830 {
1831 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1832 * explicitly passed) but we are in a transaction ready environment:
1833 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1834 * to work on BerkeleyDB 4.1 without needing to modify their
1835 * DBEnv or DB open calls.
1836 * TODO make this behaviour of the library configurable.
1837 */
1838 flags |= DB_AUTO_COMMIT;
1839 }
1840#endif
1841
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001843#if (DBVER >= 41)
1844 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1845#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001847#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848 MYDB_END_ALLOW_THREADS;
1849 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001850 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001851 self->db = NULL;
1852 return NULL;
1853 }
1854
1855 self->flags = flags;
1856 RETURN_NONE();
1857}
1858
1859
1860static PyObject*
1861DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1862{
1863 int flags=0;
1864 PyObject* txnobj = NULL;
1865 int dlen = -1;
1866 int doff = -1;
1867 PyObject* keyobj, *dataobj, *retval;
1868 DBT key, data;
1869 DB_TXN *txn = NULL;
1870 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1871
1872 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1873 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1874 return NULL;
1875
1876 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001877 if (!make_key_dbt(self, keyobj, &key, NULL))
1878 return NULL;
1879 if ( !make_dbt(dataobj, &data) ||
1880 !add_partial_dbt(&data, dlen, doff) ||
1881 !checkTxnObj(txnobj, &txn) )
1882 {
1883 FREE_DBT(key);
1884 return NULL;
1885 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001886
1887 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1888 FREE_DBT(key);
1889 return NULL;
1890 }
1891
1892 if (flags & DB_APPEND)
1893 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1894 else {
1895 retval = Py_None;
1896 Py_INCREF(retval);
1897 }
1898 FREE_DBT(key);
1899 return retval;
1900}
1901
1902
1903
1904static PyObject*
1905DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1906{
1907 char* filename;
1908 char* database = NULL;
1909 int err, flags=0;
1910 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1911
1912 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1913 &filename, &database, &flags))
1914 return NULL;
1915 CHECK_DB_NOT_CLOSED(self);
1916
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001918 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001919 RETURN_IF_ERR();
1920 RETURN_NONE();
1921}
1922
1923
1924
1925static PyObject*
1926DB_rename(DBObject* self, PyObject* args)
1927{
1928 char* filename;
1929 char* database;
1930 char* newname;
1931 int err, flags=0;
1932
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001933 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1934 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001935 return NULL;
1936 CHECK_DB_NOT_CLOSED(self);
1937
1938 MYDB_BEGIN_ALLOW_THREADS;
1939 err = self->db->rename(self->db, filename, database, newname, flags);
1940 MYDB_END_ALLOW_THREADS;
1941 RETURN_IF_ERR();
1942 RETURN_NONE();
1943}
1944
1945
1946static PyObject*
1947DB_set_bt_minkey(DBObject* self, PyObject* args)
1948{
1949 int err, minkey;
1950
1951 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1952 return NULL;
1953 CHECK_DB_NOT_CLOSED(self);
1954
1955 MYDB_BEGIN_ALLOW_THREADS;
1956 err = self->db->set_bt_minkey(self->db, minkey);
1957 MYDB_END_ALLOW_THREADS;
1958 RETURN_IF_ERR();
1959 RETURN_NONE();
1960}
1961
1962
1963static PyObject*
1964DB_set_cachesize(DBObject* self, PyObject* args)
1965{
1966 int err;
1967 int gbytes = 0, bytes = 0, ncache = 0;
1968
1969 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1970 &gbytes,&bytes,&ncache))
1971 return NULL;
1972 CHECK_DB_NOT_CLOSED(self);
1973
1974 MYDB_BEGIN_ALLOW_THREADS;
1975 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1976 MYDB_END_ALLOW_THREADS;
1977 RETURN_IF_ERR();
1978 RETURN_NONE();
1979}
1980
1981
1982static PyObject*
1983DB_set_flags(DBObject* self, PyObject* args)
1984{
1985 int err, flags;
1986
1987 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1988 return NULL;
1989 CHECK_DB_NOT_CLOSED(self);
1990
1991 MYDB_BEGIN_ALLOW_THREADS;
1992 err = self->db->set_flags(self->db, flags);
1993 MYDB_END_ALLOW_THREADS;
1994 RETURN_IF_ERR();
1995
1996 self->setflags |= flags;
1997 RETURN_NONE();
1998}
1999
2000
2001static PyObject*
2002DB_set_h_ffactor(DBObject* self, PyObject* args)
2003{
2004 int err, ffactor;
2005
2006 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2007 return NULL;
2008 CHECK_DB_NOT_CLOSED(self);
2009
2010 MYDB_BEGIN_ALLOW_THREADS;
2011 err = self->db->set_h_ffactor(self->db, ffactor);
2012 MYDB_END_ALLOW_THREADS;
2013 RETURN_IF_ERR();
2014 RETURN_NONE();
2015}
2016
2017
2018static PyObject*
2019DB_set_h_nelem(DBObject* self, PyObject* args)
2020{
2021 int err, nelem;
2022
2023 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2024 return NULL;
2025 CHECK_DB_NOT_CLOSED(self);
2026
2027 MYDB_BEGIN_ALLOW_THREADS;
2028 err = self->db->set_h_nelem(self->db, nelem);
2029 MYDB_END_ALLOW_THREADS;
2030 RETURN_IF_ERR();
2031 RETURN_NONE();
2032}
2033
2034
2035static PyObject*
2036DB_set_lorder(DBObject* self, PyObject* args)
2037{
2038 int err, lorder;
2039
2040 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2041 return NULL;
2042 CHECK_DB_NOT_CLOSED(self);
2043
2044 MYDB_BEGIN_ALLOW_THREADS;
2045 err = self->db->set_lorder(self->db, lorder);
2046 MYDB_END_ALLOW_THREADS;
2047 RETURN_IF_ERR();
2048 RETURN_NONE();
2049}
2050
2051
2052static PyObject*
2053DB_set_pagesize(DBObject* self, PyObject* args)
2054{
2055 int err, pagesize;
2056
2057 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2058 return NULL;
2059 CHECK_DB_NOT_CLOSED(self);
2060
2061 MYDB_BEGIN_ALLOW_THREADS;
2062 err = self->db->set_pagesize(self->db, pagesize);
2063 MYDB_END_ALLOW_THREADS;
2064 RETURN_IF_ERR();
2065 RETURN_NONE();
2066}
2067
2068
2069static PyObject*
2070DB_set_re_delim(DBObject* self, PyObject* args)
2071{
2072 int err;
2073 char delim;
2074
2075 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2076 PyErr_Clear();
2077 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2078 return NULL;
2079 }
2080
2081 CHECK_DB_NOT_CLOSED(self);
2082
2083 MYDB_BEGIN_ALLOW_THREADS;
2084 err = self->db->set_re_delim(self->db, delim);
2085 MYDB_END_ALLOW_THREADS;
2086 RETURN_IF_ERR();
2087 RETURN_NONE();
2088}
2089
2090static PyObject*
2091DB_set_re_len(DBObject* self, PyObject* args)
2092{
2093 int err, len;
2094
2095 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2096 return NULL;
2097 CHECK_DB_NOT_CLOSED(self);
2098
2099 MYDB_BEGIN_ALLOW_THREADS;
2100 err = self->db->set_re_len(self->db, len);
2101 MYDB_END_ALLOW_THREADS;
2102 RETURN_IF_ERR();
2103 RETURN_NONE();
2104}
2105
2106
2107static PyObject*
2108DB_set_re_pad(DBObject* self, PyObject* args)
2109{
2110 int err;
2111 char pad;
2112
2113 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2114 PyErr_Clear();
2115 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2116 return NULL;
2117 }
2118 CHECK_DB_NOT_CLOSED(self);
2119
2120 MYDB_BEGIN_ALLOW_THREADS;
2121 err = self->db->set_re_pad(self->db, pad);
2122 MYDB_END_ALLOW_THREADS;
2123 RETURN_IF_ERR();
2124 RETURN_NONE();
2125}
2126
2127
2128static PyObject*
2129DB_set_re_source(DBObject* self, PyObject* args)
2130{
2131 int err;
2132 char *re_source;
2133
2134 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2135 return NULL;
2136 CHECK_DB_NOT_CLOSED(self);
2137
2138 MYDB_BEGIN_ALLOW_THREADS;
2139 err = self->db->set_re_source(self->db, re_source);
2140 MYDB_END_ALLOW_THREADS;
2141 RETURN_IF_ERR();
2142 RETURN_NONE();
2143}
2144
2145
2146#if (DBVER >= 32)
2147static PyObject*
2148DB_set_q_extentsize(DBObject* self, PyObject* args)
2149{
2150 int err;
2151 int extentsize;
2152
2153 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2154 return NULL;
2155 CHECK_DB_NOT_CLOSED(self);
2156
2157 MYDB_BEGIN_ALLOW_THREADS;
2158 err = self->db->set_q_extentsize(self->db, extentsize);
2159 MYDB_END_ALLOW_THREADS;
2160 RETURN_IF_ERR();
2161 RETURN_NONE();
2162}
2163#endif
2164
2165static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002166DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002167{
2168 int err, flags = 0, type;
2169 void* sp;
2170 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002171#if (DBVER >= 43)
2172 PyObject* txnobj = NULL;
2173 DB_TXN *txn = NULL;
2174 char* kwnames[] = { "txn", "flags", NULL };
2175#else
2176 char* kwnames[] = { "flags", NULL };
2177#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002178
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002179#if (DBVER >= 43)
2180 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2181 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002182 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002183 if (!checkTxnObj(txnobj, &txn))
2184 return NULL;
2185#else
2186 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2187 return NULL;
2188#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002189 CHECK_DB_NOT_CLOSED(self);
2190
2191 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002192#if (DBVER >= 43)
2193 err = self->db->stat(self->db, txn, &sp, flags);
2194#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002195 err = self->db->stat(self->db, &sp, flags);
2196#else
2197 err = self->db->stat(self->db, &sp, NULL, flags);
2198#endif
2199 MYDB_END_ALLOW_THREADS;
2200 RETURN_IF_ERR();
2201
2202 self->haveStat = 1;
2203
2204 /* Turn the stat structure into a dictionary */
2205 type = _DB_get_type(self);
2206 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2207 free(sp);
2208 return NULL;
2209 }
2210
2211#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2212#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2213#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2214
2215 switch (type) {
2216 case DB_HASH:
2217 MAKE_HASH_ENTRY(magic);
2218 MAKE_HASH_ENTRY(version);
2219 MAKE_HASH_ENTRY(nkeys);
2220 MAKE_HASH_ENTRY(ndata);
2221 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002222#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002223 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002224#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002225 MAKE_HASH_ENTRY(ffactor);
2226 MAKE_HASH_ENTRY(buckets);
2227 MAKE_HASH_ENTRY(free);
2228 MAKE_HASH_ENTRY(bfree);
2229 MAKE_HASH_ENTRY(bigpages);
2230 MAKE_HASH_ENTRY(big_bfree);
2231 MAKE_HASH_ENTRY(overflows);
2232 MAKE_HASH_ENTRY(ovfl_free);
2233 MAKE_HASH_ENTRY(dup);
2234 MAKE_HASH_ENTRY(dup_free);
2235 break;
2236
2237 case DB_BTREE:
2238 case DB_RECNO:
2239 MAKE_BT_ENTRY(magic);
2240 MAKE_BT_ENTRY(version);
2241 MAKE_BT_ENTRY(nkeys);
2242 MAKE_BT_ENTRY(ndata);
2243 MAKE_BT_ENTRY(pagesize);
2244 MAKE_BT_ENTRY(minkey);
2245 MAKE_BT_ENTRY(re_len);
2246 MAKE_BT_ENTRY(re_pad);
2247 MAKE_BT_ENTRY(levels);
2248 MAKE_BT_ENTRY(int_pg);
2249 MAKE_BT_ENTRY(leaf_pg);
2250 MAKE_BT_ENTRY(dup_pg);
2251 MAKE_BT_ENTRY(over_pg);
2252 MAKE_BT_ENTRY(free);
2253 MAKE_BT_ENTRY(int_pgfree);
2254 MAKE_BT_ENTRY(leaf_pgfree);
2255 MAKE_BT_ENTRY(dup_pgfree);
2256 MAKE_BT_ENTRY(over_pgfree);
2257 break;
2258
2259 case DB_QUEUE:
2260 MAKE_QUEUE_ENTRY(magic);
2261 MAKE_QUEUE_ENTRY(version);
2262 MAKE_QUEUE_ENTRY(nkeys);
2263 MAKE_QUEUE_ENTRY(ndata);
2264 MAKE_QUEUE_ENTRY(pagesize);
2265 MAKE_QUEUE_ENTRY(pages);
2266 MAKE_QUEUE_ENTRY(re_len);
2267 MAKE_QUEUE_ENTRY(re_pad);
2268 MAKE_QUEUE_ENTRY(pgfree);
2269#if (DBVER == 31)
2270 MAKE_QUEUE_ENTRY(start);
2271#endif
2272 MAKE_QUEUE_ENTRY(first_recno);
2273 MAKE_QUEUE_ENTRY(cur_recno);
2274 break;
2275
2276 default:
2277 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2278 Py_DECREF(d);
2279 d = NULL;
2280 }
2281
2282#undef MAKE_HASH_ENTRY
2283#undef MAKE_BT_ENTRY
2284#undef MAKE_QUEUE_ENTRY
2285
2286 free(sp);
2287 return d;
2288}
2289
2290static PyObject*
2291DB_sync(DBObject* self, PyObject* args)
2292{
2293 int err;
2294 int flags = 0;
2295
2296 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2297 return NULL;
2298 CHECK_DB_NOT_CLOSED(self);
2299
2300 MYDB_BEGIN_ALLOW_THREADS;
2301 err = self->db->sync(self->db, flags);
2302 MYDB_END_ALLOW_THREADS;
2303 RETURN_IF_ERR();
2304 RETURN_NONE();
2305}
2306
2307
2308#if (DBVER >= 33)
2309static PyObject*
2310DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2311{
2312 int err, flags=0;
2313 u_int32_t count=0;
2314 PyObject* txnobj = NULL;
2315 DB_TXN *txn = NULL;
2316 char* kwnames[] = { "txn", "flags", NULL };
2317
2318 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2319 &txnobj, &flags))
2320 return NULL;
2321 CHECK_DB_NOT_CLOSED(self);
2322 if (!checkTxnObj(txnobj, &txn))
2323 return NULL;
2324
2325 MYDB_BEGIN_ALLOW_THREADS;
2326 err = self->db->truncate(self->db, txn, &count, flags);
2327 MYDB_END_ALLOW_THREADS;
2328 RETURN_IF_ERR();
2329 return PyInt_FromLong(count);
2330}
2331#endif
2332
2333
2334static PyObject*
2335DB_upgrade(DBObject* self, PyObject* args)
2336{
2337 int err, flags=0;
2338 char *filename;
2339
2340 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2341 return NULL;
2342 CHECK_DB_NOT_CLOSED(self);
2343
2344 MYDB_BEGIN_ALLOW_THREADS;
2345 err = self->db->upgrade(self->db, filename, flags);
2346 MYDB_END_ALLOW_THREADS;
2347 RETURN_IF_ERR();
2348 RETURN_NONE();
2349}
2350
2351
2352static PyObject*
2353DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2354{
2355 int err, flags=0;
2356 char* fileName;
2357 char* dbName=NULL;
2358 char* outFileName=NULL;
2359 FILE* outFile=NULL;
2360 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2361
2362 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2363 &fileName, &dbName, &outFileName, &flags))
2364 return NULL;
2365
2366 CHECK_DB_NOT_CLOSED(self);
2367 if (outFileName)
2368 outFile = fopen(outFileName, "w");
2369
2370 MYDB_BEGIN_ALLOW_THREADS;
2371 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2372 MYDB_END_ALLOW_THREADS;
2373 if (outFileName)
2374 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002375
2376 /* DB.verify acts as a DB handle destructor (like close); this was
2377 * documented in BerkeleyDB 4.2 but had the undocumented effect
2378 * of not being safe in prior versions while still requiring an explicit
2379 * DB.close call afterwards. Lets call close for the user to emulate
2380 * the safe 4.2 behaviour. */
2381#if (DBVER <= 41)
2382 self->db->close(self->db, 0);
2383#endif
2384 self->db = NULL;
2385
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002386 RETURN_IF_ERR();
2387 RETURN_NONE();
2388}
2389
2390
2391static PyObject*
2392DB_set_get_returns_none(DBObject* self, PyObject* args)
2393{
2394 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002395 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002396
2397 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2398 return NULL;
2399 CHECK_DB_NOT_CLOSED(self);
2400
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002401 if (self->moduleFlags.getReturnsNone)
2402 ++oldValue;
2403 if (self->moduleFlags.cursorSetReturnsNone)
2404 ++oldValue;
2405 self->moduleFlags.getReturnsNone = (flags >= 1);
2406 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002407 return PyInt_FromLong(oldValue);
2408}
2409
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002410#if (DBVER >= 41)
2411static PyObject*
2412DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2413{
2414 int err;
2415 u_int32_t flags=0;
2416 char *passwd = NULL;
2417 char* kwnames[] = { "passwd", "flags", NULL };
2418
2419 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2420 &passwd, &flags)) {
2421 return NULL;
2422 }
2423
2424 MYDB_BEGIN_ALLOW_THREADS;
2425 err = self->db->set_encrypt(self->db, passwd, flags);
2426 MYDB_END_ALLOW_THREADS;
2427
2428 RETURN_IF_ERR();
2429 RETURN_NONE();
2430}
2431#endif /* DBVER >= 41 */
2432
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002433
2434/*-------------------------------------------------------------- */
2435/* Mapping and Dictionary-like access routines */
2436
2437int DB_length(DBObject* self)
2438{
2439 int err;
2440 long size = 0;
2441 int flags = 0;
2442 void* sp;
2443
2444 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002445 PyErr_SetObject(DBError,
2446 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002447 return -1;
2448 }
2449
2450 if (self->haveStat) { /* Has the stat function been called recently? If
2451 so, we can use the cached value. */
2452 flags = DB_CACHED_COUNTS;
2453 }
2454
2455 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002456#if (DBVER >= 43)
2457 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2458#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002459 err = self->db->stat(self->db, &sp, flags);
2460#else
2461 err = self->db->stat(self->db, &sp, NULL, flags);
2462#endif
2463 MYDB_END_ALLOW_THREADS;
2464
2465 if (err)
2466 return -1;
2467
2468 self->haveStat = 1;
2469
2470 /* All the stat structures have matching fields upto the ndata field,
2471 so we can use any of them for the type cast */
2472 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2473 free(sp);
2474 return size;
2475}
2476
2477
2478PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2479{
2480 int err;
2481 PyObject* retval;
2482 DBT key;
2483 DBT data;
2484
2485 CHECK_DB_NOT_CLOSED(self);
2486 if (!make_key_dbt(self, keyobj, &key, NULL))
2487 return NULL;
2488
2489 CLEAR_DBT(data);
2490 if (CHECK_DBFLAG(self, DB_THREAD)) {
2491 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2492 data.flags = DB_DBT_MALLOC;
2493 }
2494 MYDB_BEGIN_ALLOW_THREADS;
2495 err = self->db->get(self->db, NULL, &key, &data, 0);
2496 MYDB_END_ALLOW_THREADS;
2497 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2498 PyErr_SetObject(PyExc_KeyError, keyobj);
2499 retval = NULL;
2500 }
2501 else if (makeDBError(err)) {
2502 retval = NULL;
2503 }
2504 else {
2505 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2506 FREE_DBT(data);
2507 }
2508
2509 FREE_DBT(key);
2510 return retval;
2511}
2512
2513
2514static int
2515DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2516{
2517 DBT key, data;
2518 int retval;
2519 int flags = 0;
2520
2521 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002522 PyErr_SetObject(DBError,
2523 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002524 return -1;
2525 }
2526
2527 if (!make_key_dbt(self, keyobj, &key, NULL))
2528 return -1;
2529
2530 if (dataobj != NULL) {
2531 if (!make_dbt(dataobj, &data))
2532 retval = -1;
2533 else {
2534 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002535 /* dictionaries shouldn't have duplicate keys */
2536 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002537 retval = _DB_put(self, NULL, &key, &data, flags);
2538
2539 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002540 /* try deleting any old record that matches and then PUT it
2541 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002542 _DB_delete(self, NULL, &key, 0);
2543 PyErr_Clear();
2544 retval = _DB_put(self, NULL, &key, &data, flags);
2545 }
2546 }
2547 }
2548 else {
2549 /* dataobj == NULL, so delete the key */
2550 retval = _DB_delete(self, NULL, &key, 0);
2551 }
2552 FREE_DBT(key);
2553 return retval;
2554}
2555
2556
2557static PyObject*
2558DB_has_key(DBObject* self, PyObject* args)
2559{
2560 int err;
2561 PyObject* keyobj;
2562 DBT key, data;
2563 PyObject* txnobj = NULL;
2564 DB_TXN *txn = NULL;
2565
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002566 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002567 return NULL;
2568 CHECK_DB_NOT_CLOSED(self);
2569 if (!make_key_dbt(self, keyobj, &key, NULL))
2570 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002571 if (!checkTxnObj(txnobj, &txn)) {
2572 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002574 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002575
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002576 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002577 it has a record but can't allocate a buffer for the data. This saves
2578 having to deal with data we won't be using.
2579 */
2580 CLEAR_DBT(data);
2581 data.flags = DB_DBT_USERMEM;
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002584 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002585 MYDB_END_ALLOW_THREADS;
2586 FREE_DBT(key);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002587 return PyInt_FromLong((err == DB_BUFFER_SMALL) || (err == 0));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002588}
2589
2590
2591#define _KEYS_LIST 1
2592#define _VALUES_LIST 2
2593#define _ITEMS_LIST 3
2594
2595static PyObject*
2596_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2597{
2598 int err, dbtype;
2599 DBT key;
2600 DBT data;
2601 DBC *cursor;
2602 PyObject* list;
2603 PyObject* item = NULL;
2604
2605 CHECK_DB_NOT_CLOSED(self);
2606 CLEAR_DBT(key);
2607 CLEAR_DBT(data);
2608
2609 dbtype = _DB_get_type(self);
2610 if (dbtype == -1)
2611 return NULL;
2612
2613 list = PyList_New(0);
2614 if (list == NULL) {
2615 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2616 return NULL;
2617 }
2618
2619 /* get a cursor */
2620 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002621 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002622 MYDB_END_ALLOW_THREADS;
2623 RETURN_IF_ERR();
2624
2625 if (CHECK_DBFLAG(self, DB_THREAD)) {
2626 key.flags = DB_DBT_REALLOC;
2627 data.flags = DB_DBT_REALLOC;
2628 }
2629
2630 while (1) { /* use the cursor to traverse the DB, collecting items */
2631 MYDB_BEGIN_ALLOW_THREADS;
2632 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2633 MYDB_END_ALLOW_THREADS;
2634
2635 if (err) {
2636 /* for any error, break out of the loop */
2637 break;
2638 }
2639
2640 switch (type) {
2641 case _KEYS_LIST:
2642 switch(dbtype) {
2643 case DB_BTREE:
2644 case DB_HASH:
2645 default:
2646 item = PyString_FromStringAndSize((char*)key.data, key.size);
2647 break;
2648 case DB_RECNO:
2649 case DB_QUEUE:
2650 item = PyInt_FromLong(*((db_recno_t*)key.data));
2651 break;
2652 }
2653 break;
2654
2655 case _VALUES_LIST:
2656 item = PyString_FromStringAndSize((char*)data.data, data.size);
2657 break;
2658
2659 case _ITEMS_LIST:
2660 switch(dbtype) {
2661 case DB_BTREE:
2662 case DB_HASH:
2663 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002664 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2665 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002666 break;
2667 case DB_RECNO:
2668 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002669 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2670 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002671 break;
2672 }
2673 break;
2674 }
2675 if (item == NULL) {
2676 Py_DECREF(list);
2677 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2678 list = NULL;
2679 goto done;
2680 }
2681 PyList_Append(list, item);
2682 Py_DECREF(item);
2683 }
2684
2685 /* DB_NOTFOUND is okay, it just means we got to the end */
2686 if (err != DB_NOTFOUND && makeDBError(err)) {
2687 Py_DECREF(list);
2688 list = NULL;
2689 }
2690
2691 done:
2692 FREE_DBT(key);
2693 FREE_DBT(data);
2694 MYDB_BEGIN_ALLOW_THREADS;
2695 cursor->c_close(cursor);
2696 MYDB_END_ALLOW_THREADS;
2697 return list;
2698}
2699
2700
2701static PyObject*
2702DB_keys(DBObject* self, PyObject* args)
2703{
2704 PyObject* txnobj = NULL;
2705 DB_TXN *txn = NULL;
2706
2707 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2708 return NULL;
2709 if (!checkTxnObj(txnobj, &txn))
2710 return NULL;
2711 return _DB_make_list(self, txn, _KEYS_LIST);
2712}
2713
2714
2715static PyObject*
2716DB_items(DBObject* self, PyObject* args)
2717{
2718 PyObject* txnobj = NULL;
2719 DB_TXN *txn = NULL;
2720
2721 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2722 return NULL;
2723 if (!checkTxnObj(txnobj, &txn))
2724 return NULL;
2725 return _DB_make_list(self, txn, _ITEMS_LIST);
2726}
2727
2728
2729static PyObject*
2730DB_values(DBObject* self, PyObject* args)
2731{
2732 PyObject* txnobj = NULL;
2733 DB_TXN *txn = NULL;
2734
2735 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2736 return NULL;
2737 if (!checkTxnObj(txnobj, &txn))
2738 return NULL;
2739 return _DB_make_list(self, txn, _VALUES_LIST);
2740}
2741
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002742/* --------------------------------------------------------------------- */
2743/* DBCursor methods */
2744
2745
2746static PyObject*
2747DBC_close(DBCursorObject* self, PyObject* args)
2748{
2749 int err = 0;
2750
2751 if (!PyArg_ParseTuple(args, ":close"))
2752 return NULL;
2753
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002754 if (self->dbc != NULL) {
2755 MYDB_BEGIN_ALLOW_THREADS;
2756 err = self->dbc->c_close(self->dbc);
2757 self->dbc = NULL;
2758 MYDB_END_ALLOW_THREADS;
2759 }
2760 RETURN_IF_ERR();
2761 RETURN_NONE();
2762}
2763
2764
2765static PyObject*
2766DBC_count(DBCursorObject* self, PyObject* args)
2767{
2768 int err = 0;
2769 db_recno_t count;
2770 int flags = 0;
2771
2772 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2773 return NULL;
2774
2775 CHECK_CURSOR_NOT_CLOSED(self);
2776
2777 MYDB_BEGIN_ALLOW_THREADS;
2778 err = self->dbc->c_count(self->dbc, &count, flags);
2779 MYDB_END_ALLOW_THREADS;
2780 RETURN_IF_ERR();
2781
2782 return PyInt_FromLong(count);
2783}
2784
2785
2786static PyObject*
2787DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2788{
2789 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2790}
2791
2792
2793static PyObject*
2794DBC_delete(DBCursorObject* self, PyObject* args)
2795{
2796 int err, flags=0;
2797
2798 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2799 return NULL;
2800
2801 CHECK_CURSOR_NOT_CLOSED(self);
2802
2803 MYDB_BEGIN_ALLOW_THREADS;
2804 err = self->dbc->c_del(self->dbc, flags);
2805 MYDB_END_ALLOW_THREADS;
2806 RETURN_IF_ERR();
2807
2808 self->mydb->haveStat = 0;
2809 RETURN_NONE();
2810}
2811
2812
2813static PyObject*
2814DBC_dup(DBCursorObject* self, PyObject* args)
2815{
2816 int err, flags =0;
2817 DBC* dbc = NULL;
2818
2819 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2820 return NULL;
2821
2822 CHECK_CURSOR_NOT_CLOSED(self);
2823
2824 MYDB_BEGIN_ALLOW_THREADS;
2825 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2826 MYDB_END_ALLOW_THREADS;
2827 RETURN_IF_ERR();
2828
2829 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2830}
2831
2832static PyObject*
2833DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2834{
2835 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2836}
2837
2838
2839static PyObject*
2840DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2841{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002842 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843 PyObject* keyobj = NULL;
2844 PyObject* dataobj = NULL;
2845 PyObject* retval = NULL;
2846 int dlen = -1;
2847 int doff = -1;
2848 DBT key, data;
2849 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2850
2851 CLEAR_DBT(key);
2852 CLEAR_DBT(data);
2853 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002854 &flags, &dlen, &doff))
2855 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002856 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2858 &kwnames[1],
2859 &keyobj, &flags, &dlen, &doff))
2860 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002862 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2863 kwnames, &keyobj, &dataobj,
2864 &flags, &dlen, &doff))
2865 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 return NULL;
2867 }
2868 }
2869 }
2870
2871 CHECK_CURSOR_NOT_CLOSED(self);
2872
2873 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2874 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002875 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2876 (!add_partial_dbt(&data, dlen, doff)) )
2877 {
2878 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002880 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002881
2882 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2883 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002884 if (!(key.flags & DB_DBT_REALLOC)) {
2885 key.flags |= DB_DBT_MALLOC;
2886 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002887 }
2888
2889 MYDB_BEGIN_ALLOW_THREADS;
2890 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2891 MYDB_END_ALLOW_THREADS;
2892
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002893 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894 Py_INCREF(Py_None);
2895 retval = Py_None;
2896 }
2897 else if (makeDBError(err)) {
2898 retval = NULL;
2899 }
2900 else {
2901 switch (_DB_get_type(self->mydb)) {
2902 case -1:
2903 retval = NULL;
2904 break;
2905 case DB_BTREE:
2906 case DB_HASH:
2907 default:
2908 retval = Py_BuildValue("s#s#", key.data, key.size,
2909 data.data, data.size);
2910 break;
2911 case DB_RECNO:
2912 case DB_QUEUE:
2913 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2914 data.data, data.size);
2915 break;
2916 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002917 FREE_DBT(data);
2918 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002919 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002920 return retval;
2921}
2922
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00002923#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00002924static PyObject*
2925DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2926{
2927 int err, flags=0;
2928 PyObject* keyobj = NULL;
2929 PyObject* dataobj = NULL;
2930 PyObject* retval = NULL;
2931 int dlen = -1;
2932 int doff = -1;
2933 DBT key, pkey, data;
2934 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2935
2936 CLEAR_DBT(key);
2937 CLEAR_DBT(data);
2938 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
2939 &flags, &dlen, &doff))
2940 {
2941 PyErr_Clear();
2942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
2943 &kwnames[1],
2944 &keyobj, &flags, &dlen, &doff))
2945 {
2946 PyErr_Clear();
2947 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
2948 kwnames, &keyobj, &dataobj,
2949 &flags, &dlen, &doff))
2950 {
2951 return NULL;
2952 }
2953 }
2954 }
2955
2956 CHECK_CURSOR_NOT_CLOSED(self);
2957
2958 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2959 return NULL;
2960 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2961 (!add_partial_dbt(&data, dlen, doff)) ) {
2962 FREE_DBT(key);
2963 return NULL;
2964 }
2965
2966 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2967 data.flags = DB_DBT_MALLOC;
2968 if (!(key.flags & DB_DBT_REALLOC)) {
2969 key.flags |= DB_DBT_MALLOC;
2970 }
2971 }
2972
2973 CLEAR_DBT(pkey);
2974 pkey.flags = DB_DBT_MALLOC;
2975
2976 MYDB_BEGIN_ALLOW_THREADS;
2977 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
2978 MYDB_END_ALLOW_THREADS;
2979
2980 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2981 Py_INCREF(Py_None);
2982 retval = Py_None;
2983 }
2984 else if (makeDBError(err)) {
2985 retval = NULL;
2986 }
2987 else {
2988 PyObject *pkeyObj;
2989 PyObject *dataObj;
2990 dataObj = PyString_FromStringAndSize(data.data, data.size);
2991
2992 if (self->mydb->primaryDBType == DB_RECNO ||
2993 self->mydb->primaryDBType == DB_QUEUE)
2994 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
2995 else
2996 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
2997
2998 if (flags & DB_SET_RECNO) /* return key, pkey and data */
2999 {
3000 PyObject *keyObj;
3001 int type = _DB_get_type(self->mydb);
3002 if (type == DB_RECNO || type == DB_QUEUE)
3003 keyObj = PyInt_FromLong(*(long *)key.data);
3004 else
3005 keyObj = PyString_FromStringAndSize(key.data, key.size);
3006 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3007 FREE_DBT(key);
3008 }
3009 else /* return just the pkey and data */
3010 {
3011 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3012 }
3013 FREE_DBT(pkey);
3014 FREE_DBT(data);
3015 }
3016 /* the only time REALLOC should be set is if we used an integer
3017 * key that make_key_dbt malloc'd for us. always free these. */
3018 if (key.flags & DB_DBT_REALLOC) {
3019 FREE_DBT(key);
3020 }
3021 return retval;
3022}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003023#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003024
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003025
3026static PyObject*
3027DBC_get_recno(DBCursorObject* self, PyObject* args)
3028{
3029 int err;
3030 db_recno_t recno;
3031 DBT key;
3032 DBT data;
3033
3034 if (!PyArg_ParseTuple(args, ":get_recno"))
3035 return NULL;
3036
3037 CHECK_CURSOR_NOT_CLOSED(self);
3038
3039 CLEAR_DBT(key);
3040 CLEAR_DBT(data);
3041 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3042 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3043 data.flags = DB_DBT_MALLOC;
3044 key.flags = DB_DBT_MALLOC;
3045 }
3046
3047 MYDB_BEGIN_ALLOW_THREADS;
3048 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3049 MYDB_END_ALLOW_THREADS;
3050 RETURN_IF_ERR();
3051
3052 recno = *((db_recno_t*)data.data);
3053 FREE_DBT(key);
3054 FREE_DBT(data);
3055 return PyInt_FromLong(recno);
3056}
3057
3058
3059static PyObject*
3060DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3061{
3062 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3063}
3064
3065
3066static PyObject*
3067DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3068{
3069 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3070}
3071
3072
3073static PyObject*
3074DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3075{
3076 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3077}
3078
3079
3080static PyObject*
3081DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3082{
3083 int err, flags = 0;
3084 PyObject* keyobj, *dataobj;
3085 DBT key, data;
3086 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3087 int dlen = -1;
3088 int doff = -1;
3089
3090 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3091 &keyobj, &dataobj, &flags, &dlen, &doff))
3092 return NULL;
3093
3094 CHECK_CURSOR_NOT_CLOSED(self);
3095
3096 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3097 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003098 if (!make_dbt(dataobj, &data) ||
3099 !add_partial_dbt(&data, dlen, doff) )
3100 {
3101 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003103 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003104
3105 MYDB_BEGIN_ALLOW_THREADS;
3106 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3107 MYDB_END_ALLOW_THREADS;
3108 FREE_DBT(key);
3109 RETURN_IF_ERR();
3110 self->mydb->haveStat = 0;
3111 RETURN_NONE();
3112}
3113
3114
3115static PyObject*
3116DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3117{
3118 int err, flags = 0;
3119 DBT key, data;
3120 PyObject* retval, *keyobj;
3121 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3122 int dlen = -1;
3123 int doff = -1;
3124
3125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3126 &keyobj, &flags, &dlen, &doff))
3127 return NULL;
3128
3129 CHECK_CURSOR_NOT_CLOSED(self);
3130
3131 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3132 return NULL;
3133
3134 CLEAR_DBT(data);
3135 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3136 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3137 data.flags = DB_DBT_MALLOC;
3138 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003139 if (!add_partial_dbt(&data, dlen, doff)) {
3140 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003142 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003143
3144 MYDB_BEGIN_ALLOW_THREADS;
3145 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3146 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003147 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3148 Py_INCREF(Py_None);
3149 retval = Py_None;
3150 }
3151 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003152 retval = NULL;
3153 }
3154 else {
3155 switch (_DB_get_type(self->mydb)) {
3156 case -1:
3157 retval = NULL;
3158 break;
3159 case DB_BTREE:
3160 case DB_HASH:
3161 default:
3162 retval = Py_BuildValue("s#s#", key.data, key.size,
3163 data.data, data.size);
3164 break;
3165 case DB_RECNO:
3166 case DB_QUEUE:
3167 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3168 data.data, data.size);
3169 break;
3170 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003171 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003172 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003174 /* the only time REALLOC should be set is if we used an integer
3175 * key that make_key_dbt malloc'd for us. always free these. */
3176 if (key.flags & DB_DBT_REALLOC) {
3177 FREE_DBT(key);
3178 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179
3180 return retval;
3181}
3182
3183
3184static PyObject*
3185DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3186{
3187 int err, flags = 0;
3188 DBT key, data;
3189 PyObject* retval, *keyobj;
3190 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3191 int dlen = -1;
3192 int doff = -1;
3193
3194 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3195 &keyobj, &flags, &dlen, &doff))
3196 return NULL;
3197
3198 CHECK_CURSOR_NOT_CLOSED(self);
3199
3200 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3201 return NULL;
3202
3203 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003204 if (!add_partial_dbt(&data, dlen, doff)) {
3205 FREE_DBT(key);
3206 return NULL;
3207 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003208 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3209 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003210 data.flags |= DB_DBT_MALLOC;
3211 /* only BTREE databases will return anything in the key */
3212 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3213 key.flags |= DB_DBT_MALLOC;
3214 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003215 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003216 MYDB_BEGIN_ALLOW_THREADS;
3217 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3218 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003219 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3220 Py_INCREF(Py_None);
3221 retval = Py_None;
3222 }
3223 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003224 retval = NULL;
3225 }
3226 else {
3227 switch (_DB_get_type(self->mydb)) {
3228 case -1:
3229 retval = NULL;
3230 break;
3231 case DB_BTREE:
3232 case DB_HASH:
3233 default:
3234 retval = Py_BuildValue("s#s#", key.data, key.size,
3235 data.data, data.size);
3236 break;
3237 case DB_RECNO:
3238 case DB_QUEUE:
3239 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3240 data.data, data.size);
3241 break;
3242 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003243 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003244 FREE_DBT(data);
3245 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003246 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003247 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003248 if (key.flags & DB_DBT_REALLOC) {
3249 FREE_DBT(key);
3250 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003251
3252 return retval;
3253}
3254
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003255static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003256_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3257 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003258{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003259 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003260 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003261 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003262
Gregory P. Smith7441e652003-11-03 21:35:31 +00003263 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3265 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003266 if (!make_dbt(dataobj, &data)) {
3267 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003268 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003269 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003270
3271 MYDB_BEGIN_ALLOW_THREADS;
3272 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3273 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003274 if ((err == DB_NOTFOUND) && returnsNone) {
3275 Py_INCREF(Py_None);
3276 retval = Py_None;
3277 }
3278 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003279 retval = NULL;
3280 }
3281 else {
3282 switch (_DB_get_type(self->mydb)) {
3283 case -1:
3284 retval = NULL;
3285 break;
3286 case DB_BTREE:
3287 case DB_HASH:
3288 default:
3289 retval = Py_BuildValue("s#s#", key.data, key.size,
3290 data.data, data.size);
3291 break;
3292 case DB_RECNO:
3293 case DB_QUEUE:
3294 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3295 data.data, data.size);
3296 break;
3297 }
3298 }
3299
3300 FREE_DBT(key);
3301 return retval;
3302}
3303
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003304static PyObject*
3305DBC_get_both(DBCursorObject* self, PyObject* args)
3306{
3307 int flags=0;
3308 PyObject *keyobj, *dataobj;
3309
3310 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3311 return NULL;
3312
Gregory P. Smith7441e652003-11-03 21:35:31 +00003313 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003314 CHECK_CURSOR_NOT_CLOSED(self);
3315
3316 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3317 self->mydb->moduleFlags.getReturnsNone);
3318}
3319
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003320/* Return size of entry */
3321static PyObject*
3322DBC_get_current_size(DBCursorObject* self, PyObject* args)
3323{
3324 int err, flags=DB_CURRENT;
3325 PyObject* retval = NULL;
3326 DBT key, data;
3327
3328 if (!PyArg_ParseTuple(args, ":get_current_size"))
3329 return NULL;
3330 CHECK_CURSOR_NOT_CLOSED(self);
3331 CLEAR_DBT(key);
3332 CLEAR_DBT(data);
3333
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003334 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003335 getting the record size. */
3336 data.flags = DB_DBT_USERMEM;
3337 data.ulen = 0;
3338 MYDB_BEGIN_ALLOW_THREADS;
3339 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3340 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003341 if (err == DB_BUFFER_SMALL || !err) {
3342 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003343 retval = PyInt_FromLong((long)data.size);
3344 err = 0;
3345 }
3346
3347 FREE_DBT(key);
3348 FREE_DBT(data);
3349 RETURN_IF_ERR();
3350 return retval;
3351}
3352
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003353static PyObject*
3354DBC_set_both(DBCursorObject* self, PyObject* args)
3355{
3356 int flags=0;
3357 PyObject *keyobj, *dataobj;
3358
3359 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3360 return NULL;
3361
Gregory P. Smith7441e652003-11-03 21:35:31 +00003362 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003363 CHECK_CURSOR_NOT_CLOSED(self);
3364
3365 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3366 self->mydb->moduleFlags.cursorSetReturnsNone);
3367}
3368
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003369
3370static PyObject*
3371DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3372{
3373 int err, irecno, flags=0;
3374 db_recno_t recno;
3375 DBT key, data;
3376 PyObject* retval;
3377 int dlen = -1;
3378 int doff = -1;
3379 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3380
3381 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3382 &irecno, &flags, &dlen, &doff))
3383 return NULL;
3384
3385 CHECK_CURSOR_NOT_CLOSED(self);
3386
3387 CLEAR_DBT(key);
3388 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003389 /* use allocated space so DB will be able to realloc room for the real
3390 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 key.data = malloc(sizeof(db_recno_t));
3392 if (key.data == NULL) {
3393 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3394 return NULL;
3395 }
3396 key.size = sizeof(db_recno_t);
3397 key.ulen = key.size;
3398 memcpy(key.data, &recno, sizeof(db_recno_t));
3399 key.flags = DB_DBT_REALLOC;
3400
3401 CLEAR_DBT(data);
3402 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3403 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3404 data.flags = DB_DBT_MALLOC;
3405 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003406 if (!add_partial_dbt(&data, dlen, doff)) {
3407 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003408 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003409 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003410
3411 MYDB_BEGIN_ALLOW_THREADS;
3412 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3413 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003414 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3415 Py_INCREF(Py_None);
3416 retval = Py_None;
3417 }
3418 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419 retval = NULL;
3420 }
3421 else { /* Can only be used for BTrees, so no need to return int key */
3422 retval = Py_BuildValue("s#s#", key.data, key.size,
3423 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003424 FREE_DBT(data);
3425 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003426 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003427
3428 return retval;
3429}
3430
3431
3432static PyObject*
3433DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3434{
3435 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3436}
3437
3438
3439static PyObject*
3440DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3441{
3442 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3443}
3444
3445
3446static PyObject*
3447DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3448{
3449 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3450}
3451
3452
3453static PyObject*
3454DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3455{
3456 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3457}
3458
3459
3460static PyObject*
3461DBC_join_item(DBCursorObject* self, PyObject* args)
3462{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003463 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464 DBT key, data;
3465 PyObject* retval;
3466
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003467 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003468 return NULL;
3469
3470 CHECK_CURSOR_NOT_CLOSED(self);
3471
3472 CLEAR_DBT(key);
3473 CLEAR_DBT(data);
3474 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3475 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3476 key.flags = DB_DBT_MALLOC;
3477 }
3478
3479 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003480 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003482 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3483 Py_INCREF(Py_None);
3484 retval = Py_None;
3485 }
3486 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003487 retval = NULL;
3488 }
3489 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003490 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003491 FREE_DBT(key);
3492 }
3493
3494 return retval;
3495}
3496
3497
3498
3499/* --------------------------------------------------------------------- */
3500/* DBEnv methods */
3501
3502
3503static PyObject*
3504DBEnv_close(DBEnvObject* self, PyObject* args)
3505{
3506 int err, flags = 0;
3507
3508 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3509 return NULL;
3510 if (!self->closed) { /* Don't close more than once */
3511 MYDB_BEGIN_ALLOW_THREADS;
3512 err = self->db_env->close(self->db_env, flags);
3513 MYDB_END_ALLOW_THREADS;
3514 /* after calling DBEnv->close, regardless of error, this DBEnv
3515 * may not be accessed again (BerkeleyDB docs). */
3516 self->closed = 1;
3517 self->db_env = NULL;
3518 RETURN_IF_ERR();
3519 }
3520 RETURN_NONE();
3521}
3522
3523
3524static PyObject*
3525DBEnv_open(DBEnvObject* self, PyObject* args)
3526{
3527 int err, flags=0, mode=0660;
3528 char *db_home;
3529
3530 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3531 return NULL;
3532
3533 CHECK_ENV_NOT_CLOSED(self);
3534
3535 MYDB_BEGIN_ALLOW_THREADS;
3536 err = self->db_env->open(self->db_env, db_home, flags, mode);
3537 MYDB_END_ALLOW_THREADS;
3538 RETURN_IF_ERR();
3539 self->closed = 0;
3540 self->flags = flags;
3541 RETURN_NONE();
3542}
3543
3544
3545static PyObject*
3546DBEnv_remove(DBEnvObject* self, PyObject* args)
3547{
3548 int err, flags=0;
3549 char *db_home;
3550
3551 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3552 return NULL;
3553 CHECK_ENV_NOT_CLOSED(self);
3554 MYDB_BEGIN_ALLOW_THREADS;
3555 err = self->db_env->remove(self->db_env, db_home, flags);
3556 MYDB_END_ALLOW_THREADS;
3557 RETURN_IF_ERR();
3558 RETURN_NONE();
3559}
3560
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003561#if (DBVER >= 41)
3562static PyObject*
3563DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3564{
3565 int err;
3566 u_int32_t flags=0;
3567 char *file = NULL;
3568 char *database = NULL;
3569 PyObject *txnobj = NULL;
3570 DB_TXN *txn = NULL;
3571 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3572
3573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3574 &file, &database, &txnobj, &flags)) {
3575 return NULL;
3576 }
3577 if (!checkTxnObj(txnobj, &txn)) {
3578 return NULL;
3579 }
3580 CHECK_ENV_NOT_CLOSED(self);
3581 MYDB_BEGIN_ALLOW_THREADS;
3582 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3583 MYDB_END_ALLOW_THREADS;
3584 RETURN_IF_ERR();
3585 RETURN_NONE();
3586}
3587
3588static PyObject*
3589DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3590{
3591 int err;
3592 u_int32_t flags=0;
3593 char *file = NULL;
3594 char *database = NULL;
3595 char *newname = NULL;
3596 PyObject *txnobj = NULL;
3597 DB_TXN *txn = NULL;
3598 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3599
3600 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3601 &file, &database, &newname, &txnobj, &flags)) {
3602 return NULL;
3603 }
3604 if (!checkTxnObj(txnobj, &txn)) {
3605 return NULL;
3606 }
3607 CHECK_ENV_NOT_CLOSED(self);
3608 MYDB_BEGIN_ALLOW_THREADS;
3609 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3610 flags);
3611 MYDB_END_ALLOW_THREADS;
3612 RETURN_IF_ERR();
3613 RETURN_NONE();
3614}
3615
3616static PyObject*
3617DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3618{
3619 int err;
3620 u_int32_t flags=0;
3621 char *passwd = NULL;
3622 char* kwnames[] = { "passwd", "flags", NULL };
3623
3624 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3625 &passwd, &flags)) {
3626 return NULL;
3627 }
3628
3629 MYDB_BEGIN_ALLOW_THREADS;
3630 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3631 MYDB_END_ALLOW_THREADS;
3632
3633 RETURN_IF_ERR();
3634 RETURN_NONE();
3635}
3636#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003637
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003638#if (DBVER >= 40)
3639static PyObject*
3640DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3641{
3642 int err;
3643 u_int32_t flags=0;
3644 u_int32_t timeout = 0;
3645 char* kwnames[] = { "timeout", "flags", NULL };
3646
3647 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3648 &timeout, &flags)) {
3649 return NULL;
3650 }
3651
3652 MYDB_BEGIN_ALLOW_THREADS;
3653 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3654 MYDB_END_ALLOW_THREADS;
3655
3656 RETURN_IF_ERR();
3657 RETURN_NONE();
3658}
3659#endif /* DBVER >= 40 */
3660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003662DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3663{
3664 int err;
3665 long shm_key = 0;
3666
3667 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3668 return NULL;
3669 CHECK_ENV_NOT_CLOSED(self);
3670
3671 err = self->db_env->set_shm_key(self->db_env, shm_key);
3672 RETURN_IF_ERR();
3673 RETURN_NONE();
3674}
3675
3676static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3678{
3679 int err, gbytes=0, bytes=0, ncache=0;
3680
3681 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3682 &gbytes, &bytes, &ncache))
3683 return NULL;
3684 CHECK_ENV_NOT_CLOSED(self);
3685
3686 MYDB_BEGIN_ALLOW_THREADS;
3687 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3688 MYDB_END_ALLOW_THREADS;
3689 RETURN_IF_ERR();
3690 RETURN_NONE();
3691}
3692
3693
3694#if (DBVER >= 32)
3695static PyObject*
3696DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3697{
3698 int err, flags=0, onoff=0;
3699
3700 if (!PyArg_ParseTuple(args, "ii:set_flags",
3701 &flags, &onoff))
3702 return NULL;
3703 CHECK_ENV_NOT_CLOSED(self);
3704
3705 MYDB_BEGIN_ALLOW_THREADS;
3706 err = self->db_env->set_flags(self->db_env, flags, onoff);
3707 MYDB_END_ALLOW_THREADS;
3708 RETURN_IF_ERR();
3709 RETURN_NONE();
3710}
3711#endif
3712
3713
3714static PyObject*
3715DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3716{
3717 int err;
3718 char *dir;
3719
3720 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3721 return NULL;
3722 CHECK_ENV_NOT_CLOSED(self);
3723
3724 MYDB_BEGIN_ALLOW_THREADS;
3725 err = self->db_env->set_data_dir(self->db_env, dir);
3726 MYDB_END_ALLOW_THREADS;
3727 RETURN_IF_ERR();
3728 RETURN_NONE();
3729}
3730
3731
3732static PyObject*
3733DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3734{
3735 int err, lg_bsize;
3736
3737 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3738 return NULL;
3739 CHECK_ENV_NOT_CLOSED(self);
3740
3741 MYDB_BEGIN_ALLOW_THREADS;
3742 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3743 MYDB_END_ALLOW_THREADS;
3744 RETURN_IF_ERR();
3745 RETURN_NONE();
3746}
3747
3748
3749static PyObject*
3750DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3751{
3752 int err;
3753 char *dir;
3754
3755 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3756 return NULL;
3757 CHECK_ENV_NOT_CLOSED(self);
3758
3759 MYDB_BEGIN_ALLOW_THREADS;
3760 err = self->db_env->set_lg_dir(self->db_env, dir);
3761 MYDB_END_ALLOW_THREADS;
3762 RETURN_IF_ERR();
3763 RETURN_NONE();
3764}
3765
3766static PyObject*
3767DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3768{
3769 int err, lg_max;
3770
3771 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3772 return NULL;
3773 CHECK_ENV_NOT_CLOSED(self);
3774
3775 MYDB_BEGIN_ALLOW_THREADS;
3776 err = self->db_env->set_lg_max(self->db_env, lg_max);
3777 MYDB_END_ALLOW_THREADS;
3778 RETURN_IF_ERR();
3779 RETURN_NONE();
3780}
3781
3782
3783static PyObject*
3784DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3785{
3786 int err, lk_detect;
3787
3788 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3789 return NULL;
3790 CHECK_ENV_NOT_CLOSED(self);
3791
3792 MYDB_BEGIN_ALLOW_THREADS;
3793 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3794 MYDB_END_ALLOW_THREADS;
3795 RETURN_IF_ERR();
3796 RETURN_NONE();
3797}
3798
3799
3800static PyObject*
3801DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3802{
3803 int err, max;
3804
3805 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3806 return NULL;
3807 CHECK_ENV_NOT_CLOSED(self);
3808
3809 MYDB_BEGIN_ALLOW_THREADS;
3810 err = self->db_env->set_lk_max(self->db_env, max);
3811 MYDB_END_ALLOW_THREADS;
3812 RETURN_IF_ERR();
3813 RETURN_NONE();
3814}
3815
3816
3817#if (DBVER >= 32)
3818
3819static PyObject*
3820DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3821{
3822 int err, max;
3823
3824 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3825 return NULL;
3826 CHECK_ENV_NOT_CLOSED(self);
3827
3828 MYDB_BEGIN_ALLOW_THREADS;
3829 err = self->db_env->set_lk_max_locks(self->db_env, max);
3830 MYDB_END_ALLOW_THREADS;
3831 RETURN_IF_ERR();
3832 RETURN_NONE();
3833}
3834
3835
3836static PyObject*
3837DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3838{
3839 int err, max;
3840
3841 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3842 return NULL;
3843 CHECK_ENV_NOT_CLOSED(self);
3844
3845 MYDB_BEGIN_ALLOW_THREADS;
3846 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3847 MYDB_END_ALLOW_THREADS;
3848 RETURN_IF_ERR();
3849 RETURN_NONE();
3850}
3851
3852
3853static PyObject*
3854DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3855{
3856 int err, max;
3857
3858 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3859 return NULL;
3860 CHECK_ENV_NOT_CLOSED(self);
3861
3862 MYDB_BEGIN_ALLOW_THREADS;
3863 err = self->db_env->set_lk_max_objects(self->db_env, max);
3864 MYDB_END_ALLOW_THREADS;
3865 RETURN_IF_ERR();
3866 RETURN_NONE();
3867}
3868
3869#endif
3870
3871
3872static PyObject*
3873DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3874{
3875 int err, mp_mmapsize;
3876
3877 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3878 return NULL;
3879 CHECK_ENV_NOT_CLOSED(self);
3880
3881 MYDB_BEGIN_ALLOW_THREADS;
3882 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3883 MYDB_END_ALLOW_THREADS;
3884 RETURN_IF_ERR();
3885 RETURN_NONE();
3886}
3887
3888
3889static PyObject*
3890DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3891{
3892 int err;
3893 char *dir;
3894
3895 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3896 return NULL;
3897 CHECK_ENV_NOT_CLOSED(self);
3898
3899 MYDB_BEGIN_ALLOW_THREADS;
3900 err = self->db_env->set_tmp_dir(self->db_env, dir);
3901 MYDB_END_ALLOW_THREADS;
3902 RETURN_IF_ERR();
3903 RETURN_NONE();
3904}
3905
3906
3907static PyObject*
3908DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3909{
3910 int flags = 0;
3911 PyObject* txnobj = NULL;
3912 DB_TXN *txn = NULL;
3913 char* kwnames[] = { "parent", "flags", NULL };
3914
3915 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3916 &txnobj, &flags))
3917 return NULL;
3918
3919 if (!checkTxnObj(txnobj, &txn))
3920 return NULL;
3921 CHECK_ENV_NOT_CLOSED(self);
3922
3923 return (PyObject*)newDBTxnObject(self, txn, flags);
3924}
3925
3926
3927static PyObject*
3928DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3929{
3930 int err, kbyte=0, min=0, flags=0;
3931
3932 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3933 return NULL;
3934 CHECK_ENV_NOT_CLOSED(self);
3935
3936 MYDB_BEGIN_ALLOW_THREADS;
3937#if (DBVER >= 40)
3938 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3939#else
3940 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3941#endif
3942 MYDB_END_ALLOW_THREADS;
3943 RETURN_IF_ERR();
3944 RETURN_NONE();
3945}
3946
3947
3948static PyObject*
3949DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3950{
3951 int err, max;
3952
3953 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3954 return NULL;
3955 CHECK_ENV_NOT_CLOSED(self);
3956
3957 MYDB_BEGIN_ALLOW_THREADS;
3958 err = self->db_env->set_tx_max(self->db_env, max);
3959 MYDB_END_ALLOW_THREADS;
3960 RETURN_IF_ERR();
3961 RETURN_NONE();
3962}
3963
3964
3965static PyObject*
3966DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3967{
3968 int err, atype, flags=0;
3969 int aborted = 0;
3970
3971 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3972 return NULL;
3973 CHECK_ENV_NOT_CLOSED(self);
3974
3975 MYDB_BEGIN_ALLOW_THREADS;
3976#if (DBVER >= 40)
3977 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3978#else
3979 err = lock_detect(self->db_env, flags, atype, &aborted);
3980#endif
3981 MYDB_END_ALLOW_THREADS;
3982 RETURN_IF_ERR();
3983 return PyInt_FromLong(aborted);
3984}
3985
3986
3987static PyObject*
3988DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3989{
3990 int flags=0;
3991 int locker, lock_mode;
3992 DBT obj;
3993 PyObject* objobj;
3994
3995 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3996 return NULL;
3997
3998
3999 if (!make_dbt(objobj, &obj))
4000 return NULL;
4001
4002 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4003}
4004
4005
4006static PyObject*
4007DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4008{
4009 int err;
4010 u_int32_t theID;
4011
4012 if (!PyArg_ParseTuple(args, ":lock_id"))
4013 return NULL;
4014
4015 CHECK_ENV_NOT_CLOSED(self);
4016 MYDB_BEGIN_ALLOW_THREADS;
4017#if (DBVER >= 40)
4018 err = self->db_env->lock_id(self->db_env, &theID);
4019#else
4020 err = lock_id(self->db_env, &theID);
4021#endif
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024
4025 return PyInt_FromLong((long)theID);
4026}
4027
4028
4029static PyObject*
4030DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4031{
4032 int err;
4033 DBLockObject* dblockobj;
4034
4035 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4036 return NULL;
4037
4038 CHECK_ENV_NOT_CLOSED(self);
4039 MYDB_BEGIN_ALLOW_THREADS;
4040#if (DBVER >= 40)
4041 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4042#else
4043 err = lock_put(self->db_env, &dblockobj->lock);
4044#endif
4045 MYDB_END_ALLOW_THREADS;
4046 RETURN_IF_ERR();
4047 RETURN_NONE();
4048}
4049
4050
4051static PyObject*
4052DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4053{
4054 int err;
4055 DB_LOCK_STAT* sp;
4056 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004057 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004058
4059 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4060 return NULL;
4061 CHECK_ENV_NOT_CLOSED(self);
4062
4063 MYDB_BEGIN_ALLOW_THREADS;
4064#if (DBVER >= 40)
4065 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4066#else
4067#if (DBVER >= 33)
4068 err = lock_stat(self->db_env, &sp);
4069#else
4070 err = lock_stat(self->db_env, &sp, NULL);
4071#endif
4072#endif
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075
4076 /* Turn the stat structure into a dictionary */
4077 d = PyDict_New();
4078 if (d == NULL) {
4079 free(sp);
4080 return NULL;
4081 }
4082
4083#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4084
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004085#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004086 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004087#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004088 MAKE_ENTRY(nmodes);
4089#if (DBVER >= 32)
4090 MAKE_ENTRY(maxlocks);
4091 MAKE_ENTRY(maxlockers);
4092 MAKE_ENTRY(maxobjects);
4093 MAKE_ENTRY(nlocks);
4094 MAKE_ENTRY(maxnlocks);
4095#endif
4096 MAKE_ENTRY(nlockers);
4097 MAKE_ENTRY(maxnlockers);
4098#if (DBVER >= 32)
4099 MAKE_ENTRY(nobjects);
4100 MAKE_ENTRY(maxnobjects);
4101#endif
4102 MAKE_ENTRY(nrequests);
4103 MAKE_ENTRY(nreleases);
4104 MAKE_ENTRY(nnowaits);
4105 MAKE_ENTRY(nconflicts);
4106 MAKE_ENTRY(ndeadlocks);
4107 MAKE_ENTRY(regsize);
4108 MAKE_ENTRY(region_wait);
4109 MAKE_ENTRY(region_nowait);
4110
4111#undef MAKE_ENTRY
4112 free(sp);
4113 return d;
4114}
4115
4116
4117static PyObject*
4118DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4119{
4120 int flags=0;
4121 int err;
4122 char **log_list_start, **log_list;
4123 PyObject* list;
4124 PyObject* item = NULL;
4125
4126 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4127 return NULL;
4128
4129 CHECK_ENV_NOT_CLOSED(self);
4130 MYDB_BEGIN_ALLOW_THREADS;
4131#if (DBVER >= 40)
4132 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4133#elif (DBVER == 33)
4134 err = log_archive(self->db_env, &log_list, flags);
4135#else
4136 err = log_archive(self->db_env, &log_list, flags, NULL);
4137#endif
4138 MYDB_END_ALLOW_THREADS;
4139 RETURN_IF_ERR();
4140
4141 list = PyList_New(0);
4142 if (list == NULL) {
4143 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4144 return NULL;
4145 }
4146
4147 if (log_list) {
4148 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4149 item = PyString_FromString (*log_list);
4150 if (item == NULL) {
4151 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004152 PyErr_SetString(PyExc_MemoryError,
4153 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004154 list = NULL;
4155 break;
4156 }
4157 PyList_Append(list, item);
4158 Py_DECREF(item);
4159 }
4160 free(log_list_start);
4161 }
4162 return list;
4163}
4164
4165
4166static PyObject*
4167DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4168{
4169 int err;
4170 DB_TXN_STAT* sp;
4171 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004172 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004173
4174 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4177
4178 MYDB_BEGIN_ALLOW_THREADS;
4179#if (DBVER >= 40)
4180 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4181#elif (DBVER == 33)
4182 err = txn_stat(self->db_env, &sp);
4183#else
4184 err = txn_stat(self->db_env, &sp, NULL);
4185#endif
4186 MYDB_END_ALLOW_THREADS;
4187 RETURN_IF_ERR();
4188
4189 /* Turn the stat structure into a dictionary */
4190 d = PyDict_New();
4191 if (d == NULL) {
4192 free(sp);
4193 return NULL;
4194 }
4195
4196#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4197
4198 MAKE_ENTRY(time_ckp);
4199 MAKE_ENTRY(last_txnid);
4200 MAKE_ENTRY(maxtxns);
4201 MAKE_ENTRY(nactive);
4202 MAKE_ENTRY(maxnactive);
4203 MAKE_ENTRY(nbegins);
4204 MAKE_ENTRY(naborts);
4205 MAKE_ENTRY(ncommits);
4206 MAKE_ENTRY(regsize);
4207 MAKE_ENTRY(region_wait);
4208 MAKE_ENTRY(region_nowait);
4209
4210#undef MAKE_ENTRY
4211 free(sp);
4212 return d;
4213}
4214
4215
4216static PyObject*
4217DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4218{
4219 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004220 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004221
4222 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4223 return NULL;
4224 CHECK_ENV_NOT_CLOSED(self);
4225
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004226 if (self->moduleFlags.getReturnsNone)
4227 ++oldValue;
4228 if (self->moduleFlags.cursorSetReturnsNone)
4229 ++oldValue;
4230 self->moduleFlags.getReturnsNone = (flags >= 1);
4231 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004232 return PyInt_FromLong(oldValue);
4233}
4234
4235
4236/* --------------------------------------------------------------------- */
4237/* DBTxn methods */
4238
4239
4240static PyObject*
4241DBTxn_commit(DBTxnObject* self, PyObject* args)
4242{
4243 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004244 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004245
4246 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4247 return NULL;
4248
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004249 if (!self->txn) {
4250 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4251 "DBTxn must not be used after txn_commit or txn_abort"));
4252 return NULL;
4253 }
4254 txn = self->txn;
4255 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004256 MYDB_BEGIN_ALLOW_THREADS;
4257#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004258 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004259#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004260 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004261#endif
4262 MYDB_END_ALLOW_THREADS;
4263 RETURN_IF_ERR();
4264 RETURN_NONE();
4265}
4266
4267static PyObject*
4268DBTxn_prepare(DBTxnObject* self, PyObject* args)
4269{
4270#if (DBVER >= 33)
4271 int err;
4272 char* gid=NULL;
4273 int gid_size=0;
4274
4275 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4276 return NULL;
4277
4278 if (gid_size != DB_XIDDATASIZE) {
4279 PyErr_SetString(PyExc_TypeError,
4280 "gid must be DB_XIDDATASIZE bytes long");
4281 return NULL;
4282 }
4283
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004284 if (!self->txn) {
4285 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4286 "DBTxn must not be used after txn_commit or txn_abort"));
4287 return NULL;
4288 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004289 MYDB_BEGIN_ALLOW_THREADS;
4290#if (DBVER >= 40)
4291 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4292#else
4293 err = txn_prepare(self->txn, (u_int8_t*)gid);
4294#endif
4295 MYDB_END_ALLOW_THREADS;
4296 RETURN_IF_ERR();
4297 RETURN_NONE();
4298#else
4299 int err;
4300
4301 if (!PyArg_ParseTuple(args, ":prepare"))
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 err = txn_prepare(self->txn);
4311 MYDB_END_ALLOW_THREADS;
4312 RETURN_IF_ERR();
4313 RETURN_NONE();
4314#endif
4315}
4316
4317
4318static PyObject*
4319DBTxn_abort(DBTxnObject* self, PyObject* args)
4320{
4321 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004322 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004323
4324 if (!PyArg_ParseTuple(args, ":abort"))
4325 return NULL;
4326
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004327 if (!self->txn) {
4328 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4329 "DBTxn must not be used after txn_commit or txn_abort"));
4330 return NULL;
4331 }
4332 txn = self->txn;
4333 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004334 MYDB_BEGIN_ALLOW_THREADS;
4335#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004336 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004337#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004338 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004339#endif
4340 MYDB_END_ALLOW_THREADS;
4341 RETURN_IF_ERR();
4342 RETURN_NONE();
4343}
4344
4345
4346static PyObject*
4347DBTxn_id(DBTxnObject* self, PyObject* args)
4348{
4349 int id;
4350
4351 if (!PyArg_ParseTuple(args, ":id"))
4352 return NULL;
4353
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004354 if (!self->txn) {
4355 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4356 "DBTxn must not be used after txn_commit or txn_abort"));
4357 return NULL;
4358 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004359 MYDB_BEGIN_ALLOW_THREADS;
4360#if (DBVER >= 40)
4361 id = self->txn->id(self->txn);
4362#else
4363 id = txn_id(self->txn);
4364#endif
4365 MYDB_END_ALLOW_THREADS;
4366 return PyInt_FromLong(id);
4367}
4368
4369/* --------------------------------------------------------------------- */
4370/* Method definition tables and type objects */
4371
4372static PyMethodDef DB_methods[] = {
4373 {"append", (PyCFunction)DB_append, METH_VARARGS},
4374#if (DBVER >= 33)
4375 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4376#endif
4377 {"close", (PyCFunction)DB_close, METH_VARARGS},
4378#if (DBVER >= 32)
4379 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4380 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4381#endif
4382 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4383 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4384 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4385 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004386#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004387 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004388#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004389 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4390 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4391 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4392 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4393 {"join", (PyCFunction)DB_join, METH_VARARGS},
4394 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4395 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4396 {"items", (PyCFunction)DB_items, METH_VARARGS},
4397 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4398 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4399 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4400 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4401 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4402 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4403 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004404#if (DBVER >= 41)
4405 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4406#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004407 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4408 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4409 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4410 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4411 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4412 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4413 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4414 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4415 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4416#if (DBVER >= 32)
4417 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4418#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004419 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004420 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4421#if (DBVER >= 33)
4422 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4423#endif
4424 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4425 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4426 {"values", (PyCFunction)DB_values, METH_VARARGS},
4427 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4428 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4429 {NULL, NULL} /* sentinel */
4430};
4431
4432
4433static PyMappingMethods DB_mapping = {
4434 (inquiry)DB_length, /*mp_length*/
4435 (binaryfunc)DB_subscript, /*mp_subscript*/
4436 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4437};
4438
4439
4440static PyMethodDef DBCursor_methods[] = {
4441 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4442 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4443 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4444 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4445 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4446 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4447 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004448#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00004449 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00004450#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004451 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4452 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4453 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4454 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4455 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4456 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4457 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4458 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004459 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004460 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004461 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4462 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4463 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4464 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4465 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4466 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4467 {NULL, NULL} /* sentinel */
4468};
4469
4470
4471static PyMethodDef DBEnv_methods[] = {
4472 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4473 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4474 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004475#if (DBVER >= 41)
4476 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4477 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4478 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4479#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004480#if (DBVER >= 40)
4481 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4482#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004483 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004484 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4485 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4486#if (DBVER >= 32)
4487 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4488#endif
4489 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4490 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4491 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4492 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4493 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4494#if (DBVER >= 32)
4495 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4496 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4497 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4498#endif
4499 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4500 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4501 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4502 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4503 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4504 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4505 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4506 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4507 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4508 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4509 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4510 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4511 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4512 {NULL, NULL} /* sentinel */
4513};
4514
4515
4516static PyMethodDef DBTxn_methods[] = {
4517 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4518 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4519 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4520 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4521 {NULL, NULL} /* sentinel */
4522};
4523
4524
4525static PyObject*
4526DB_getattr(DBObject* self, char *name)
4527{
4528 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4529}
4530
4531
4532static PyObject*
4533DBEnv_getattr(DBEnvObject* self, char *name)
4534{
4535 if (!strcmp(name, "db_home")) {
4536 CHECK_ENV_NOT_CLOSED(self);
4537 if (self->db_env->db_home == NULL) {
4538 RETURN_NONE();
4539 }
4540 return PyString_FromString(self->db_env->db_home);
4541 }
4542
4543 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4544}
4545
4546
4547static PyObject*
4548DBCursor_getattr(DBCursorObject* self, char *name)
4549{
4550 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4551}
4552
4553static PyObject*
4554DBTxn_getattr(DBTxnObject* self, char *name)
4555{
4556 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4557}
4558
4559static PyObject*
4560DBLock_getattr(DBLockObject* self, char *name)
4561{
4562 return NULL;
4563}
4564
4565statichere PyTypeObject DB_Type = {
4566 PyObject_HEAD_INIT(NULL)
4567 0, /*ob_size*/
4568 "DB", /*tp_name*/
4569 sizeof(DBObject), /*tp_basicsize*/
4570 0, /*tp_itemsize*/
4571 /* methods */
4572 (destructor)DB_dealloc, /*tp_dealloc*/
4573 0, /*tp_print*/
4574 (getattrfunc)DB_getattr, /*tp_getattr*/
4575 0, /*tp_setattr*/
4576 0, /*tp_compare*/
4577 0, /*tp_repr*/
4578 0, /*tp_as_number*/
4579 0, /*tp_as_sequence*/
4580 &DB_mapping,/*tp_as_mapping*/
4581 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004582#ifdef HAVE_WEAKREF
4583 0, /* tp_call */
4584 0, /* tp_str */
4585 0, /* tp_getattro */
4586 0, /* tp_setattro */
4587 0, /* tp_as_buffer */
4588 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4589 0, /* tp_doc */
4590 0, /* tp_traverse */
4591 0, /* tp_clear */
4592 0, /* tp_richcompare */
4593 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4594#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004595};
4596
4597
4598statichere PyTypeObject DBCursor_Type = {
4599 PyObject_HEAD_INIT(NULL)
4600 0, /*ob_size*/
4601 "DBCursor", /*tp_name*/
4602 sizeof(DBCursorObject), /*tp_basicsize*/
4603 0, /*tp_itemsize*/
4604 /* methods */
4605 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4606 0, /*tp_print*/
4607 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4608 0, /*tp_setattr*/
4609 0, /*tp_compare*/
4610 0, /*tp_repr*/
4611 0, /*tp_as_number*/
4612 0, /*tp_as_sequence*/
4613 0, /*tp_as_mapping*/
4614 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00004615#ifdef HAVE_WEAKREF
4616 0, /* tp_call */
4617 0, /* tp_str */
4618 0, /* tp_getattro */
4619 0, /* tp_setattro */
4620 0, /* tp_as_buffer */
4621 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4622 0, /* tp_doc */
4623 0, /* tp_traverse */
4624 0, /* tp_clear */
4625 0, /* tp_richcompare */
4626 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4627#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004628};
4629
4630
4631statichere PyTypeObject DBEnv_Type = {
4632 PyObject_HEAD_INIT(NULL)
4633 0, /*ob_size*/
4634 "DBEnv", /*tp_name*/
4635 sizeof(DBEnvObject), /*tp_basicsize*/
4636 0, /*tp_itemsize*/
4637 /* methods */
4638 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4639 0, /*tp_print*/
4640 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4641 0, /*tp_setattr*/
4642 0, /*tp_compare*/
4643 0, /*tp_repr*/
4644 0, /*tp_as_number*/
4645 0, /*tp_as_sequence*/
4646 0, /*tp_as_mapping*/
4647 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004648#ifdef HAVE_WEAKREF
4649 0, /* tp_call */
4650 0, /* tp_str */
4651 0, /* tp_getattro */
4652 0, /* tp_setattro */
4653 0, /* tp_as_buffer */
4654 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4655 0, /* tp_doc */
4656 0, /* tp_traverse */
4657 0, /* tp_clear */
4658 0, /* tp_richcompare */
4659 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4660#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004661};
4662
4663statichere PyTypeObject DBTxn_Type = {
4664 PyObject_HEAD_INIT(NULL)
4665 0, /*ob_size*/
4666 "DBTxn", /*tp_name*/
4667 sizeof(DBTxnObject), /*tp_basicsize*/
4668 0, /*tp_itemsize*/
4669 /* methods */
4670 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4671 0, /*tp_print*/
4672 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4673 0, /*tp_setattr*/
4674 0, /*tp_compare*/
4675 0, /*tp_repr*/
4676 0, /*tp_as_number*/
4677 0, /*tp_as_sequence*/
4678 0, /*tp_as_mapping*/
4679 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004680#ifdef HAVE_WEAKREF
4681 0, /* tp_call */
4682 0, /* tp_str */
4683 0, /* tp_getattro */
4684 0, /* tp_setattro */
4685 0, /* tp_as_buffer */
4686 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4687 0, /* tp_doc */
4688 0, /* tp_traverse */
4689 0, /* tp_clear */
4690 0, /* tp_richcompare */
4691 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4692#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004693};
4694
4695
4696statichere PyTypeObject DBLock_Type = {
4697 PyObject_HEAD_INIT(NULL)
4698 0, /*ob_size*/
4699 "DBLock", /*tp_name*/
4700 sizeof(DBLockObject), /*tp_basicsize*/
4701 0, /*tp_itemsize*/
4702 /* methods */
4703 (destructor)DBLock_dealloc, /*tp_dealloc*/
4704 0, /*tp_print*/
4705 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4706 0, /*tp_setattr*/
4707 0, /*tp_compare*/
4708 0, /*tp_repr*/
4709 0, /*tp_as_number*/
4710 0, /*tp_as_sequence*/
4711 0, /*tp_as_mapping*/
4712 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00004713#ifdef HAVE_WEAKREF
4714 0, /* tp_call */
4715 0, /* tp_str */
4716 0, /* tp_getattro */
4717 0, /* tp_setattro */
4718 0, /* tp_as_buffer */
4719 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4720 0, /* tp_doc */
4721 0, /* tp_traverse */
4722 0, /* tp_clear */
4723 0, /* tp_richcompare */
4724 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4725#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004726};
4727
4728
4729/* --------------------------------------------------------------------- */
4730/* Module-level functions */
4731
4732static PyObject*
4733DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4734{
4735 PyObject* dbenvobj = NULL;
4736 int flags = 0;
4737 char* kwnames[] = { "dbEnv", "flags", NULL};
4738
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004739 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4740 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004741 return NULL;
4742 if (dbenvobj == Py_None)
4743 dbenvobj = NULL;
4744 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4745 makeTypeError("DBEnv", dbenvobj);
4746 return NULL;
4747 }
4748
4749 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4750}
4751
4752
4753static PyObject*
4754DBEnv_construct(PyObject* self, PyObject* args)
4755{
4756 int flags = 0;
4757 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4758 return (PyObject* )newDBEnvObject(flags);
4759}
4760
4761
4762static char bsddb_version_doc[] =
4763"Returns a tuple of major, minor, and patch release numbers of the\n\
4764underlying DB library.";
4765
4766static PyObject*
4767bsddb_version(PyObject* self, PyObject* args)
4768{
4769 int major, minor, patch;
4770
4771 if (!PyArg_ParseTuple(args, ":version"))
4772 return NULL;
4773 db_version(&major, &minor, &patch);
4774 return Py_BuildValue("(iii)", major, minor, patch);
4775}
4776
4777
4778/* List of functions defined in the module */
4779
4780static PyMethodDef bsddb_methods[] = {
4781 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4782 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4783 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4784 {NULL, NULL} /* sentinel */
4785};
4786
4787
4788/* --------------------------------------------------------------------- */
4789/* Module initialization */
4790
4791
4792/* Convenience routine to export an integer value.
4793 * Errors are silently ignored, for better or for worse...
4794 */
4795#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4796
Gregory P. Smith41631e82003-09-21 00:08:14 +00004797#define MODULE_NAME_MAX_LEN 11
4798static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004799
4800DL_EXPORT(void) init_bsddb(void)
4801{
4802 PyObject* m;
4803 PyObject* d;
4804 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4805 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4806 PyObject* cvsid_s = PyString_FromString( rcs_id );
4807
4808 /* Initialize the type of the new type objects here; doing it here
4809 is required for portability to Windows without requiring C++. */
4810 DB_Type.ob_type = &PyType_Type;
4811 DBCursor_Type.ob_type = &PyType_Type;
4812 DBEnv_Type.ob_type = &PyType_Type;
4813 DBTxn_Type.ob_type = &PyType_Type;
4814 DBLock_Type.ob_type = &PyType_Type;
4815
4816
Mark Hammonda69d4092003-04-22 23:13:27 +00004817#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004818 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00004819 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004820#endif
4821
4822 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004823 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004824
4825 /* Add some symbolic constants to the module */
4826 d = PyModule_GetDict(m);
4827 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4828 PyDict_SetItemString(d, "cvsid", cvsid_s);
4829 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4830 Py_DECREF(pybsddb_version_s);
4831 pybsddb_version_s = NULL;
4832 Py_DECREF(cvsid_s);
4833 cvsid_s = NULL;
4834 Py_DECREF(db_version_s);
4835 db_version_s = NULL;
4836
4837 ADD_INT(d, DB_VERSION_MAJOR);
4838 ADD_INT(d, DB_VERSION_MINOR);
4839 ADD_INT(d, DB_VERSION_PATCH);
4840
4841 ADD_INT(d, DB_MAX_PAGES);
4842 ADD_INT(d, DB_MAX_RECORDS);
4843
Gregory P. Smith41631e82003-09-21 00:08:14 +00004844#if (DBVER >= 42)
4845 ADD_INT(d, DB_RPCCLIENT);
4846#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004847 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004848 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4849 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4850#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004851 ADD_INT(d, DB_XA_CREATE);
4852
4853 ADD_INT(d, DB_CREATE);
4854 ADD_INT(d, DB_NOMMAP);
4855 ADD_INT(d, DB_THREAD);
4856
4857 ADD_INT(d, DB_FORCE);
4858 ADD_INT(d, DB_INIT_CDB);
4859 ADD_INT(d, DB_INIT_LOCK);
4860 ADD_INT(d, DB_INIT_LOG);
4861 ADD_INT(d, DB_INIT_MPOOL);
4862 ADD_INT(d, DB_INIT_TXN);
4863#if (DBVER >= 32)
4864 ADD_INT(d, DB_JOINENV);
4865#endif
4866
4867 ADD_INT(d, DB_RECOVER);
4868 ADD_INT(d, DB_RECOVER_FATAL);
4869 ADD_INT(d, DB_TXN_NOSYNC);
4870 ADD_INT(d, DB_USE_ENVIRON);
4871 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4872
4873 ADD_INT(d, DB_LOCKDOWN);
4874 ADD_INT(d, DB_PRIVATE);
4875 ADD_INT(d, DB_SYSTEM_MEM);
4876
4877 ADD_INT(d, DB_TXN_SYNC);
4878 ADD_INT(d, DB_TXN_NOWAIT);
4879
4880 ADD_INT(d, DB_EXCL);
4881 ADD_INT(d, DB_FCNTL_LOCKING);
4882 ADD_INT(d, DB_ODDFILESIZE);
4883 ADD_INT(d, DB_RDWRMASTER);
4884 ADD_INT(d, DB_RDONLY);
4885 ADD_INT(d, DB_TRUNCATE);
4886#if (DBVER >= 32)
4887 ADD_INT(d, DB_EXTENT);
4888 ADD_INT(d, DB_CDB_ALLDB);
4889 ADD_INT(d, DB_VERIFY);
4890#endif
4891 ADD_INT(d, DB_UPGRADE);
4892
4893 ADD_INT(d, DB_AGGRESSIVE);
4894 ADD_INT(d, DB_NOORDERCHK);
4895 ADD_INT(d, DB_ORDERCHKONLY);
4896 ADD_INT(d, DB_PR_PAGE);
4897#if ! (DBVER >= 33)
4898 ADD_INT(d, DB_VRFY_FLAGMASK);
4899 ADD_INT(d, DB_PR_HEADERS);
4900#endif
4901 ADD_INT(d, DB_PR_RECOVERYTEST);
4902 ADD_INT(d, DB_SALVAGE);
4903
4904 ADD_INT(d, DB_LOCK_NORUN);
4905 ADD_INT(d, DB_LOCK_DEFAULT);
4906 ADD_INT(d, DB_LOCK_OLDEST);
4907 ADD_INT(d, DB_LOCK_RANDOM);
4908 ADD_INT(d, DB_LOCK_YOUNGEST);
4909#if (DBVER >= 33)
4910 ADD_INT(d, DB_LOCK_MAXLOCKS);
4911 ADD_INT(d, DB_LOCK_MINLOCKS);
4912 ADD_INT(d, DB_LOCK_MINWRITE);
4913#endif
4914
4915
4916#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004917 /* docs say to use zero instead */
4918 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004919#else
4920 ADD_INT(d, DB_LOCK_CONFLICT);
4921#endif
4922
4923 ADD_INT(d, DB_LOCK_DUMP);
4924 ADD_INT(d, DB_LOCK_GET);
4925 ADD_INT(d, DB_LOCK_INHERIT);
4926 ADD_INT(d, DB_LOCK_PUT);
4927 ADD_INT(d, DB_LOCK_PUT_ALL);
4928 ADD_INT(d, DB_LOCK_PUT_OBJ);
4929
4930 ADD_INT(d, DB_LOCK_NG);
4931 ADD_INT(d, DB_LOCK_READ);
4932 ADD_INT(d, DB_LOCK_WRITE);
4933 ADD_INT(d, DB_LOCK_NOWAIT);
4934#if (DBVER >= 32)
4935 ADD_INT(d, DB_LOCK_WAIT);
4936#endif
4937 ADD_INT(d, DB_LOCK_IWRITE);
4938 ADD_INT(d, DB_LOCK_IREAD);
4939 ADD_INT(d, DB_LOCK_IWR);
4940#if (DBVER >= 33)
4941 ADD_INT(d, DB_LOCK_DIRTY);
4942 ADD_INT(d, DB_LOCK_WWRITE);
4943#endif
4944
4945 ADD_INT(d, DB_LOCK_RECORD);
4946 ADD_INT(d, DB_LOCK_UPGRADE);
4947#if (DBVER >= 32)
4948 ADD_INT(d, DB_LOCK_SWITCH);
4949#endif
4950#if (DBVER >= 33)
4951 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4952#endif
4953
4954 ADD_INT(d, DB_LOCK_NOWAIT);
4955 ADD_INT(d, DB_LOCK_RECORD);
4956 ADD_INT(d, DB_LOCK_UPGRADE);
4957
4958#if (DBVER >= 33)
4959 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004960#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004961 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00004962#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004963 ADD_INT(d, DB_LSTAT_FREE);
4964 ADD_INT(d, DB_LSTAT_HELD);
4965#if (DBVER == 33)
4966 ADD_INT(d, DB_LSTAT_NOGRANT);
4967#endif
4968 ADD_INT(d, DB_LSTAT_PENDING);
4969 ADD_INT(d, DB_LSTAT_WAITING);
4970#endif
4971
4972 ADD_INT(d, DB_ARCH_ABS);
4973 ADD_INT(d, DB_ARCH_DATA);
4974 ADD_INT(d, DB_ARCH_LOG);
4975
4976 ADD_INT(d, DB_BTREE);
4977 ADD_INT(d, DB_HASH);
4978 ADD_INT(d, DB_RECNO);
4979 ADD_INT(d, DB_QUEUE);
4980 ADD_INT(d, DB_UNKNOWN);
4981
4982 ADD_INT(d, DB_DUP);
4983 ADD_INT(d, DB_DUPSORT);
4984 ADD_INT(d, DB_RECNUM);
4985 ADD_INT(d, DB_RENUMBER);
4986 ADD_INT(d, DB_REVSPLITOFF);
4987 ADD_INT(d, DB_SNAPSHOT);
4988
4989 ADD_INT(d, DB_JOIN_NOSORT);
4990
4991 ADD_INT(d, DB_AFTER);
4992 ADD_INT(d, DB_APPEND);
4993 ADD_INT(d, DB_BEFORE);
4994 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004995#if (DBVER >= 41)
4996 _addIntToDict(d, "DB_CHECKPOINT", 0);
4997#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004998 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004999 ADD_INT(d, DB_CURLSN);
5000#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005001#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005002 ADD_INT(d, DB_COMMIT);
5003#endif
5004 ADD_INT(d, DB_CONSUME);
5005#if (DBVER >= 32)
5006 ADD_INT(d, DB_CONSUME_WAIT);
5007#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005008 ADD_INT(d, DB_CURRENT);
5009#if (DBVER >= 33)
5010 ADD_INT(d, DB_FAST_STAT);
5011#endif
5012 ADD_INT(d, DB_FIRST);
5013 ADD_INT(d, DB_FLUSH);
5014 ADD_INT(d, DB_GET_BOTH);
5015 ADD_INT(d, DB_GET_RECNO);
5016 ADD_INT(d, DB_JOIN_ITEM);
5017 ADD_INT(d, DB_KEYFIRST);
5018 ADD_INT(d, DB_KEYLAST);
5019 ADD_INT(d, DB_LAST);
5020 ADD_INT(d, DB_NEXT);
5021 ADD_INT(d, DB_NEXT_DUP);
5022 ADD_INT(d, DB_NEXT_NODUP);
5023 ADD_INT(d, DB_NODUPDATA);
5024 ADD_INT(d, DB_NOOVERWRITE);
5025 ADD_INT(d, DB_NOSYNC);
5026 ADD_INT(d, DB_POSITION);
5027 ADD_INT(d, DB_PREV);
5028 ADD_INT(d, DB_PREV_NODUP);
5029 ADD_INT(d, DB_RECORDCOUNT);
5030 ADD_INT(d, DB_SET);
5031 ADD_INT(d, DB_SET_RANGE);
5032 ADD_INT(d, DB_SET_RECNO);
5033 ADD_INT(d, DB_WRITECURSOR);
5034
5035 ADD_INT(d, DB_OPFLAGS_MASK);
5036 ADD_INT(d, DB_RMW);
5037#if (DBVER >= 33)
5038 ADD_INT(d, DB_DIRTY_READ);
5039 ADD_INT(d, DB_MULTIPLE);
5040 ADD_INT(d, DB_MULTIPLE_KEY);
5041#endif
5042
5043#if (DBVER >= 33)
5044 ADD_INT(d, DB_DONOTINDEX);
5045#endif
5046
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005047#if (DBVER >= 41)
5048 _addIntToDict(d, "DB_INCOMPLETE", 0);
5049#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005050 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005051#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005052 ADD_INT(d, DB_KEYEMPTY);
5053 ADD_INT(d, DB_KEYEXIST);
5054 ADD_INT(d, DB_LOCK_DEADLOCK);
5055 ADD_INT(d, DB_LOCK_NOTGRANTED);
5056 ADD_INT(d, DB_NOSERVER);
5057 ADD_INT(d, DB_NOSERVER_HOME);
5058 ADD_INT(d, DB_NOSERVER_ID);
5059 ADD_INT(d, DB_NOTFOUND);
5060 ADD_INT(d, DB_OLD_VERSION);
5061 ADD_INT(d, DB_RUNRECOVERY);
5062 ADD_INT(d, DB_VERIFY_BAD);
5063#if (DBVER >= 33)
5064 ADD_INT(d, DB_PAGE_NOTFOUND);
5065 ADD_INT(d, DB_SECONDARY_BAD);
5066#endif
5067#if (DBVER >= 40)
5068 ADD_INT(d, DB_STAT_CLEAR);
5069 ADD_INT(d, DB_REGION_INIT);
5070 ADD_INT(d, DB_NOLOCKING);
5071 ADD_INT(d, DB_YIELDCPU);
5072 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5073 ADD_INT(d, DB_NOPANIC);
5074#endif
5075
Gregory P. Smith41631e82003-09-21 00:08:14 +00005076#if (DBVER >= 42)
5077 ADD_INT(d, DB_TIME_NOTGRANTED);
5078 ADD_INT(d, DB_TXN_NOT_DURABLE);
5079 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5080 ADD_INT(d, DB_LOG_AUTOREMOVE);
5081 ADD_INT(d, DB_DIRECT_LOG);
5082 ADD_INT(d, DB_DIRECT_DB);
5083 ADD_INT(d, DB_INIT_REP);
5084 ADD_INT(d, DB_ENCRYPT);
5085 ADD_INT(d, DB_CHKSUM);
5086#endif
5087
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005088#if (DBVER >= 43)
5089 ADD_INT(d, DB_LOG_INMEMORY);
5090 ADD_INT(d, DB_BUFFER_SMALL);
5091#endif
5092
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005093#if (DBVER >= 41)
5094 ADD_INT(d, DB_ENCRYPT_AES);
5095 ADD_INT(d, DB_AUTO_COMMIT);
5096#else
5097 /* allow berkeleydb 4.1 aware apps to run on older versions */
5098 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5099#endif
5100
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005101 ADD_INT(d, EINVAL);
5102 ADD_INT(d, EACCES);
5103 ADD_INT(d, ENOSPC);
5104 ADD_INT(d, ENOMEM);
5105 ADD_INT(d, EAGAIN);
5106 ADD_INT(d, EBUSY);
5107 ADD_INT(d, EEXIST);
5108 ADD_INT(d, ENOENT);
5109 ADD_INT(d, EPERM);
5110
Barry Warsaw1baa9822003-03-31 19:51:29 +00005111#if (DBVER >= 40)
5112 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5113 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5114#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005115
5116 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005117 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005118 PyDict_SetItemString(d, "DBError", DBError);
5119
5120 /* Some magic to make DBNotFoundError derive from both DBError and
5121 KeyError, since the API only supports using one base class. */
5122 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5123 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
5124 Py_file_input, d, d);
5125 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5126 PyDict_DelItemString(d, "KeyError");
5127
5128
5129 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005130#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005131 PyDict_SetItemString(d, #name, name)
5132
5133#if !INCOMPLETE_IS_WARNING
5134 MAKE_EX(DBIncompleteError);
5135#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005136 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005137 MAKE_EX(DBKeyEmptyError);
5138 MAKE_EX(DBKeyExistError);
5139 MAKE_EX(DBLockDeadlockError);
5140 MAKE_EX(DBLockNotGrantedError);
5141 MAKE_EX(DBOldVersionError);
5142 MAKE_EX(DBRunRecoveryError);
5143 MAKE_EX(DBVerifyBadError);
5144 MAKE_EX(DBNoServerError);
5145 MAKE_EX(DBNoServerHomeError);
5146 MAKE_EX(DBNoServerIDError);
5147#if (DBVER >= 33)
5148 MAKE_EX(DBPageNotFoundError);
5149 MAKE_EX(DBSecondaryBadError);
5150#endif
5151
5152 MAKE_EX(DBInvalidArgError);
5153 MAKE_EX(DBAccessError);
5154 MAKE_EX(DBNoSpaceError);
5155 MAKE_EX(DBNoMemoryError);
5156 MAKE_EX(DBAgainError);
5157 MAKE_EX(DBBusyError);
5158 MAKE_EX(DBFileExistsError);
5159 MAKE_EX(DBNoSuchFileError);
5160 MAKE_EX(DBPermissionsError);
5161
5162#undef MAKE_EX
5163
5164 /* Check for errors */
5165 if (PyErr_Occurred()) {
5166 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005167 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005168 }
5169}
Gregory P. Smith41631e82003-09-21 00:08:14 +00005170
5171/* allow this module to be named _pybsddb so that it can be installed
5172 * and imported on top of python >= 2.3 that includes its own older
5173 * copy of the library named _bsddb without importing the old version. */
5174DL_EXPORT(void) init_pybsddb(void)
5175{
5176 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5177 init_bsddb();
5178}