blob: a88f01fffab290c03a0c87942fe6df5973d73401 [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 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith372b5832006-06-05 18:48:21 +0000101#define PY_BSDDB_VERSION "4.4.4"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000107#endif
108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
Mark Hammonda69d4092003-04-22 23:13:27 +0000115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000120/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000142#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000143
144#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000145/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
Gregory P. Smitha703a212003-11-03 01:04:41 +0000199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
Neal Norwitzb4a55812004-07-09 23:30:57 +0000212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000229
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000233 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000234 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000235 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000249 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250#if (DBVER >= 33)
251 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000252 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000253 int primaryDBType;
254#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000274 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000287} DBLockObject;
288
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
Gregory P. Smithe2767172003-11-02 08:06:29 +0000323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330 }
331
Gregory P. Smithe2767172003-11-02 08:06:29 +0000332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000340
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000385 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000395 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000403 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000404 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000405 if (type == -1)
406 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000446 return 0;
447 }
448
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000510/* Callback used to save away more information about errors from the DB
511 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000512static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000513#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000514static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000530 int exceptionRaised = 0;
531
532 switch (err) {
533 case 0: /* successful, no error */ break;
534
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000535#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000536 case DB_INCOMPLETE:
537#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000538 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000539 if (_db_errmsg[0]) {
540 strcat(errTxt, " -- ");
541 strcat(errTxt, _db_errmsg);
542 _db_errmsg[0] = 0;
543 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000544#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000545 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
546#else
547 fprintf(stderr, errTxt);
548 fprintf(stderr, "\n");
549#endif
550
551#else /* do an exception instead */
552 errObj = DBIncompleteError;
553#endif
554 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000555#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556
557 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
558 case DB_KEYEXIST: errObj = DBKeyExistError; break;
559 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
560 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
561 case DB_NOTFOUND: errObj = DBNotFoundError; break;
562 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
563 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
564 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
565 case DB_NOSERVER: errObj = DBNoServerError; break;
566 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
567 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
568#if (DBVER >= 33)
569 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
570 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
571#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000572 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000573
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000574#if (DBVER >= 43)
575 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
576 case ENOMEM: errObj = PyExc_MemoryError; break;
577#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000578 case EINVAL: errObj = DBInvalidArgError; break;
579 case EACCES: errObj = DBAccessError; break;
580 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000581 case EAGAIN: errObj = DBAgainError; break;
582 case EBUSY : errObj = DBBusyError; break;
583 case EEXIST: errObj = DBFileExistsError; break;
584 case ENOENT: errObj = DBNoSuchFileError; break;
585 case EPERM : errObj = DBPermissionsError; break;
586
587 default: errObj = DBError; break;
588 }
589
590 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000591 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000592 if (_db_errmsg[0]) {
593 strcat(errTxt, " -- ");
594 strcat(errTxt, _db_errmsg);
595 _db_errmsg[0] = 0;
596 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000597
598 errTuple = Py_BuildValue("(is)", err, errTxt);
599 PyErr_SetObject(errObj, errTuple);
600 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000601 }
602
603 return ((errObj != NULL) || exceptionRaised);
604}
605
606
607
608/* set a type exception */
609static void makeTypeError(char* expected, PyObject* found)
610{
611 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
612 expected, found->ob_type->tp_name);
613}
614
615
616/* verify that an obj is either None or a DBTxn, and set the txn pointer */
617static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
618{
619 if (txnobj == Py_None || txnobj == NULL) {
620 *txn = NULL;
621 return 1;
622 }
623 if (DBTxnObject_Check(txnobj)) {
624 *txn = ((DBTxnObject*)txnobj)->txn;
625 return 1;
626 }
627 else
628 makeTypeError("DBTxn", txnobj);
629 return 0;
630}
631
632
633/* Delete a key from a database
634 Returns 0 on success, -1 on an error. */
635static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
636{
637 int err;
638
639 MYDB_BEGIN_ALLOW_THREADS;
640 err = self->db->del(self->db, txn, key, 0);
641 MYDB_END_ALLOW_THREADS;
642 if (makeDBError(err)) {
643 return -1;
644 }
645 self->haveStat = 0;
646 return 0;
647}
648
649
650/* Store a key into a database
651 Returns 0 on success, -1 on an error. */
652static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
653{
654 int err;
655
656 MYDB_BEGIN_ALLOW_THREADS;
657 err = self->db->put(self->db, txn, key, data, flags);
658 MYDB_END_ALLOW_THREADS;
659 if (makeDBError(err)) {
660 return -1;
661 }
662 self->haveStat = 0;
663 return 0;
664}
665
666/* Get a key/data pair from a cursor */
667static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
668 PyObject *args, PyObject *kwargs, char *format)
669{
670 int err;
671 PyObject* retval = NULL;
672 DBT key, data;
673 int dlen = -1;
674 int doff = -1;
675 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000676 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000677
678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
679 &flags, &dlen, &doff))
680 return NULL;
681
682 CHECK_CURSOR_NOT_CLOSED(self);
683
684 flags |= extra_flags;
685 CLEAR_DBT(key);
686 CLEAR_DBT(data);
687 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
688 /* Tell BerkeleyDB to malloc the return value (thread safe) */
689 data.flags = DB_DBT_MALLOC;
690 key.flags = DB_DBT_MALLOC;
691 }
692 if (!add_partial_dbt(&data, dlen, doff))
693 return NULL;
694
695 MYDB_BEGIN_ALLOW_THREADS;
696 err = self->dbc->c_get(self->dbc, &key, &data, flags);
697 MYDB_END_ALLOW_THREADS;
698
Gregory P. Smithe9477062005-06-04 06:46:59 +0000699 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
700 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000701 Py_INCREF(Py_None);
702 retval = Py_None;
703 }
704 else if (makeDBError(err)) {
705 retval = NULL;
706 }
707 else { /* otherwise, success! */
708
709 /* if Recno or Queue, return the key as an Int */
710 switch (_DB_get_type(self->mydb)) {
711 case -1:
712 retval = NULL;
713 break;
714
715 case DB_RECNO:
716 case DB_QUEUE:
717 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
718 data.data, data.size);
719 break;
720 case DB_HASH:
721 case DB_BTREE:
722 default:
723 retval = Py_BuildValue("s#s#", key.data, key.size,
724 data.data, data.size);
725 break;
726 }
727 }
728 if (!err) {
729 FREE_DBT(key);
730 FREE_DBT(data);
731 }
732 return retval;
733}
734
735
736/* add an integer to a dictionary using the given name as a key */
737static void _addIntToDict(PyObject* dict, char *name, int value)
738{
739 PyObject* v = PyInt_FromLong((long) value);
740 if (!v || PyDict_SetItemString(dict, name, v))
741 PyErr_Clear();
742
743 Py_XDECREF(v);
744}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000745#if (DBVER >= 43)
746/* add an db_seq_t to a dictionary using the given name as a key */
747static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
748{
749 PyObject* v = PyLong_FromLongLong(value);
750 if (!v || PyDict_SetItemString(dict, name, v))
751 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000753 Py_XDECREF(v);
754}
755#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000756
757
758
759/* --------------------------------------------------------------------- */
760/* Allocators and deallocators */
761
762static DBObject*
763newDBObject(DBEnvObject* arg, int flags)
764{
765 DBObject* self;
766 DB_ENV* db_env = NULL;
767 int err;
768
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000769 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770 if (self == NULL)
771 return NULL;
772
773 self->haveStat = 0;
774 self->flags = 0;
775 self->setflags = 0;
776 self->myenvobj = NULL;
777#if (DBVER >= 33)
778 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000779 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000780 self->primaryDBType = 0;
781#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000782#ifdef HAVE_WEAKREF
783 self->in_weakreflist = NULL;
784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000785
786 /* keep a reference to our python DBEnv object */
787 if (arg) {
788 Py_INCREF(arg);
789 self->myenvobj = arg;
790 db_env = arg->db_env;
791 }
792
793 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000794 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000795 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000796 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
797 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000798
799 MYDB_BEGIN_ALLOW_THREADS;
800 err = db_create(&self->db, db_env, flags);
801 self->db->set_errcall(self->db, _db_errorCallback);
802#if (DBVER >= 33)
803 self->db->app_private = (void*)self;
804#endif
805 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000806 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
807 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000808 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809 if (makeDBError(err)) {
810 if (self->myenvobj) {
811 Py_DECREF(self->myenvobj);
812 self->myenvobj = NULL;
813 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000814 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000815 self = NULL;
816 }
817 return self;
818}
819
820
821static void
822DB_dealloc(DBObject* self)
823{
824 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000825 /* avoid closing a DB when its DBEnv has been closed out from under
826 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000828 (self->myenvobj && self->myenvobj->db_env))
829 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000830 MYDB_BEGIN_ALLOW_THREADS;
831 self->db->close(self->db, 0);
832 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000833#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000834 } else {
835 PyErr_Warn(PyExc_RuntimeWarning,
836 "DB could not be closed in destructor: DBEnv already closed");
837#endif
838 }
839 self->db = NULL;
840 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000841#ifdef HAVE_WEAKREF
842 if (self->in_weakreflist != NULL) {
843 PyObject_ClearWeakRefs((PyObject *) self);
844 }
845#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846 if (self->myenvobj) {
847 Py_DECREF(self->myenvobj);
848 self->myenvobj = NULL;
849 }
850#if (DBVER >= 33)
851 if (self->associateCallback != NULL) {
852 Py_DECREF(self->associateCallback);
853 self->associateCallback = NULL;
854 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000855 if (self->btCompareCallback != NULL) {
856 Py_DECREF(self->btCompareCallback);
857 self->btCompareCallback = NULL;
858 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861}
862
863
864static DBCursorObject*
865newDBCursorObject(DBC* dbc, DBObject* db)
866{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000867 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868 if (self == NULL)
869 return NULL;
870
871 self->dbc = dbc;
872 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000873#ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876 Py_INCREF(self->mydb);
877 return self;
878}
879
880
881static void
882DBCursor_dealloc(DBCursorObject* self)
883{
884 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000885
886#ifdef HAVE_WEAKREF
887 if (self->in_weakreflist != NULL) {
888 PyObject_ClearWeakRefs((PyObject *) self);
889 }
890#endif
891
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000892 if (self->dbc != NULL) {
893 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000894 /* If the underlying database has been closed, we don't
895 need to do anything. If the environment has been closed
896 we need to leak, as BerkeleyDB will crash trying to access
897 the environment. There was an exception when the
898 user closed the environment even though there still was
899 a database open. */
900 if (self->mydb->db && self->mydb->myenvobj &&
901 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000902 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000903 self->dbc = NULL;
904 MYDB_END_ALLOW_THREADS;
905 }
906 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908}
909
910
911static DBEnvObject*
912newDBEnvObject(int flags)
913{
914 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000915 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916 if (self == NULL)
917 return NULL;
918
919 self->closed = 1;
920 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000921 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
922 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000923#ifdef HAVE_WEAKREF
924 self->in_weakreflist = NULL;
925#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000926
927 MYDB_BEGIN_ALLOW_THREADS;
928 err = db_env_create(&self->db_env, flags);
929 MYDB_END_ALLOW_THREADS;
930 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000931 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 self = NULL;
933 }
934 else {
935 self->db_env->set_errcall(self->db_env, _db_errorCallback);
936 }
937 return self;
938}
939
940
941static void
942DBEnv_dealloc(DBEnvObject* self)
943{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000944#ifdef HAVE_WEAKREF
945 if (self->in_weakreflist != NULL) {
946 PyObject_ClearWeakRefs((PyObject *) self);
947 }
948#endif
949
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000950 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 MYDB_BEGIN_ALLOW_THREADS;
952 self->db_env->close(self->db_env, 0);
953 MYDB_END_ALLOW_THREADS;
954 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000955 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956}
957
958
959static DBTxnObject*
960newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
961{
962 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000963 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 if (self == NULL)
965 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000966 Py_INCREF(myenv);
967 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000968#ifdef HAVE_WEAKREF
969 self->in_weakreflist = NULL;
970#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971
972 MYDB_BEGIN_ALLOW_THREADS;
973#if (DBVER >= 40)
974 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
975#else
976 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
977#endif
978 MYDB_END_ALLOW_THREADS;
979 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000980 Py_DECREF(self->env);
981 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000982 self = NULL;
983 }
984 return self;
985}
986
987
988static void
989DBTxn_dealloc(DBTxnObject* self)
990{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000991#ifdef HAVE_WEAKREF
992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
994 }
995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996
Gregory P. Smith31c50652004-06-28 01:20:40 +0000997#ifdef HAVE_WARNINGS
998 if (self->txn) {
999 /* it hasn't been finalized, abort it! */
1000 MYDB_BEGIN_ALLOW_THREADS;
1001#if (DBVER >= 40)
1002 self->txn->abort(self->txn);
1003#else
1004 txn_abort(self->txn);
1005#endif
1006 MYDB_END_ALLOW_THREADS;
1007 PyErr_Warn(PyExc_RuntimeWarning,
1008 "DBTxn aborted in destructor. No prior commit() or abort().");
1009 }
1010#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001011
Neal Norwitz62a21122006-01-25 05:21:55 +00001012 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014}
1015
1016
1017static DBLockObject*
1018newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1019 db_lockmode_t lock_mode, int flags)
1020{
1021 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001022 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023 if (self == NULL)
1024 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001025#ifdef HAVE_WEAKREF
1026 self->in_weakreflist = NULL;
1027#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001028
1029 MYDB_BEGIN_ALLOW_THREADS;
1030#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001031 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1032 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033#else
1034 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1035#endif
1036 MYDB_END_ALLOW_THREADS;
1037 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001038 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001039 self = NULL;
1040 }
1041
1042 return self;
1043}
1044
1045
1046static void
1047DBLock_dealloc(DBLockObject* self)
1048{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001049#ifdef HAVE_WEAKREF
1050 if (self->in_weakreflist != NULL) {
1051 PyObject_ClearWeakRefs((PyObject *) self);
1052 }
1053#endif
1054 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057}
1058
1059
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001060#if (DBVER >= 43)
1061static DBSequenceObject*
1062newDBSequenceObject(DBObject* mydb, int flags)
1063{
1064 int err;
1065 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1066 if (self == NULL)
1067 return NULL;
1068 Py_INCREF(mydb);
1069 self->mydb = mydb;
1070#ifdef HAVE_WEAKREF
1071 self->in_weakreflist = NULL;
1072#endif
1073
1074
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1082 }
1083
1084 return self;
1085}
1086
1087
1088static void
1089DBSequence_dealloc(DBSequenceObject* self)
1090{
1091#ifdef HAVE_WEAKREF
1092 if (self->in_weakreflist != NULL) {
1093 PyObject_ClearWeakRefs((PyObject *) self);
1094 }
1095#endif
1096
1097 Py_DECREF(self->mydb);
1098 PyObject_Del(self);
1099}
1100#endif
1101
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001102/* --------------------------------------------------------------------- */
1103/* DB methods */
1104
1105static PyObject*
1106DB_append(DBObject* self, PyObject* args)
1107{
1108 PyObject* txnobj = NULL;
1109 PyObject* dataobj;
1110 db_recno_t recno;
1111 DBT key, data;
1112 DB_TXN *txn = NULL;
1113
Georg Brandl96a8c392006-05-29 21:04:52 +00001114 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001115 return NULL;
1116
1117 CHECK_DB_NOT_CLOSED(self);
1118
1119 /* make a dummy key out of a recno */
1120 recno = 0;
1121 CLEAR_DBT(key);
1122 key.data = &recno;
1123 key.size = sizeof(recno);
1124 key.ulen = key.size;
1125 key.flags = DB_DBT_USERMEM;
1126
1127 if (!make_dbt(dataobj, &data)) return NULL;
1128 if (!checkTxnObj(txnobj, &txn)) return NULL;
1129
1130 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1131 return NULL;
1132
1133 return PyInt_FromLong(recno);
1134}
1135
1136
1137#if (DBVER >= 33)
1138
1139static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001140_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1141 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001142{
1143 int retval = DB_DONOTINDEX;
1144 DBObject* secondaryDB = (DBObject*)db->app_private;
1145 PyObject* callback = secondaryDB->associateCallback;
1146 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001148 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149
1150
1151 if (callback != NULL) {
1152 MYDB_BEGIN_BLOCK_THREADS;
1153
Thomas Woutersb3153832006-03-08 01:47:19 +00001154 if (type == DB_RECNO || type == DB_QUEUE)
1155 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1156 priData->data, priData->size);
1157 else
1158 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1159 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001160 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001161 result = PyEval_CallObject(callback, args);
1162 }
1163 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001164 PyErr_Print();
1165 }
1166 else if (result == Py_None) {
1167 retval = DB_DONOTINDEX;
1168 }
1169 else if (PyInt_Check(result)) {
1170 retval = PyInt_AsLong(result);
1171 }
1172 else if (PyString_Check(result)) {
1173 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001174 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175
1176 CLEAR_DBT(*secKey);
1177#if PYTHON_API_VERSION <= 1007
1178 /* 1.5 compatibility */
1179 size = PyString_Size(result);
1180 data = PyString_AsString(result);
1181#else
1182 PyString_AsStringAndSize(result, &data, &size);
1183#endif
1184 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1185 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001186 if (secKey->data) {
1187 memcpy(secKey->data, data, size);
1188 secKey->size = size;
1189 retval = 0;
1190 }
1191 else {
1192 PyErr_SetString(PyExc_MemoryError,
1193 "malloc failed in _db_associateCallback");
1194 PyErr_Print();
1195 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001196 }
1197 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001198 PyErr_SetString(
1199 PyExc_TypeError,
1200 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001201 PyErr_Print();
1202 }
1203
Thomas Woutersb3153832006-03-08 01:47:19 +00001204 Py_XDECREF(args);
1205 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206
1207 MYDB_END_BLOCK_THREADS;
1208 }
1209 return retval;
1210}
1211
1212
1213static PyObject*
1214DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1215{
1216 int err, flags=0;
1217 DBObject* secondaryDB;
1218 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001219#if (DBVER >= 41)
1220 PyObject *txnobj = NULL;
1221 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001222 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001223 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001224#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001225 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001226#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001227
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001228#if (DBVER >= 41)
1229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1230 &secondaryDB, &callback, &flags,
1231 &txnobj)) {
1232#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001234 &secondaryDB, &callback, &flags)) {
1235#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001236 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001237 }
1238
1239#if (DBVER >= 41)
1240 if (!checkTxnObj(txnobj, &txn)) return NULL;
1241#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242
1243 CHECK_DB_NOT_CLOSED(self);
1244 if (!DBObject_Check(secondaryDB)) {
1245 makeTypeError("DB", (PyObject*)secondaryDB);
1246 return NULL;
1247 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001248 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001249 if (callback == Py_None) {
1250 callback = NULL;
1251 }
1252 else if (!PyCallable_Check(callback)) {
1253 makeTypeError("Callable", callback);
1254 return NULL;
1255 }
1256
1257 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001258 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001259 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 secondaryDB->associateCallback = callback;
1261 secondaryDB->primaryDBType = _DB_get_type(self);
1262
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001263 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1264 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1265 * The global interepreter lock is not initialized until the first
1266 * thread is created using thread.start_new_thread() or fork() is
1267 * called. that would cause the ALLOW_THREADS here to segfault due
1268 * to a null pointer reference if no threads or child processes
1269 * have been created. This works around that and is a no-op if
1270 * threads have already been initialized.
1271 * (see pybsddb-users mailing list post on 2002-08-07)
1272 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001273#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001274 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001275#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001277#if (DBVER >= 41)
1278 err = self->db->associate(self->db,
1279 txn,
1280 secondaryDB->db,
1281 _db_associateCallback,
1282 flags);
1283#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001284 err = self->db->associate(self->db,
1285 secondaryDB->db,
1286 _db_associateCallback,
1287 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001288#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001289 MYDB_END_ALLOW_THREADS;
1290
1291 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001292 Py_XDECREF(secondaryDB->associateCallback);
1293 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001294 secondaryDB->primaryDBType = 0;
1295 }
1296
1297 RETURN_IF_ERR();
1298 RETURN_NONE();
1299}
1300
1301
1302#endif
1303
1304
1305static PyObject*
1306DB_close(DBObject* self, PyObject* args)
1307{
1308 int err, flags=0;
1309 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1310 return NULL;
1311 if (self->db != NULL) {
1312 if (self->myenvobj)
1313 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 self->db = NULL;
1316 RETURN_IF_ERR();
1317 }
1318 RETURN_NONE();
1319}
1320
1321
1322#if (DBVER >= 32)
1323static PyObject*
1324_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1325{
1326 int err, flags=0, type;
1327 PyObject* txnobj = NULL;
1328 PyObject* retval = NULL;
1329 DBT key, data;
1330 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001331 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1336
1337 CHECK_DB_NOT_CLOSED(self);
1338 type = _DB_get_type(self);
1339 if (type == -1)
1340 return NULL;
1341 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342 PyErr_SetString(PyExc_TypeError,
1343 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001344 return NULL;
1345 }
1346 if (!checkTxnObj(txnobj, &txn))
1347 return NULL;
1348
1349 CLEAR_DBT(key);
1350 CLEAR_DBT(data);
1351 if (CHECK_DBFLAG(self, DB_THREAD)) {
1352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1353 data.flags = DB_DBT_MALLOC;
1354 key.flags = DB_DBT_MALLOC;
1355 }
1356
1357 MYDB_BEGIN_ALLOW_THREADS;
1358 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1359 MYDB_END_ALLOW_THREADS;
1360
Gregory P. Smithe9477062005-06-04 06:46:59 +00001361 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1362 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1366 }
1367 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001368 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1369 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001370 FREE_DBT(key);
1371 FREE_DBT(data);
1372 }
1373
1374 RETURN_IF_ERR();
1375 return retval;
1376}
1377
1378static PyObject*
1379DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1380{
1381 return _DB_consume(self, args, kwargs, DB_CONSUME);
1382}
1383
1384static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001385DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1386 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001387{
1388 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1389}
1390#endif
1391
1392
1393
1394static PyObject*
1395DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1396{
1397 int err, flags=0;
1398 DBC* dbc;
1399 PyObject* txnobj = NULL;
1400 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001401 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402
1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1404 &txnobj, &flags))
1405 return NULL;
1406 CHECK_DB_NOT_CLOSED(self);
1407 if (!checkTxnObj(txnobj, &txn))
1408 return NULL;
1409
1410 MYDB_BEGIN_ALLOW_THREADS;
1411 err = self->db->cursor(self->db, txn, &dbc, flags);
1412 MYDB_END_ALLOW_THREADS;
1413 RETURN_IF_ERR();
1414 return (PyObject*) newDBCursorObject(dbc, self);
1415}
1416
1417
1418static PyObject*
1419DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1420{
1421 PyObject* txnobj = NULL;
1422 int flags = 0;
1423 PyObject* keyobj;
1424 DBT key;
1425 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001426 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1429 &keyobj, &txnobj, &flags))
1430 return NULL;
1431 CHECK_DB_NOT_CLOSED(self);
1432 if (!make_key_dbt(self, keyobj, &key, NULL))
1433 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001434 if (!checkTxnObj(txnobj, &txn)) {
1435 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001437 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001439 if (-1 == _DB_delete(self, txn, &key, 0)) {
1440 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001441 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001442 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443
1444 FREE_DBT(key);
1445 RETURN_NONE();
1446}
1447
1448
1449static PyObject*
1450DB_fd(DBObject* self, PyObject* args)
1451{
1452 int err, the_fd;
1453
1454 if (!PyArg_ParseTuple(args,":fd"))
1455 return NULL;
1456 CHECK_DB_NOT_CLOSED(self);
1457
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->fd(self->db, &the_fd);
1460 MYDB_END_ALLOW_THREADS;
1461 RETURN_IF_ERR();
1462 return PyInt_FromLong(the_fd);
1463}
1464
1465
1466static PyObject*
1467DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1468{
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, data;
1477 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001478 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001479 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001480
1481 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001482 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1483 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001484 return NULL;
1485
1486 CHECK_DB_NOT_CLOSED(self);
1487 if (!make_key_dbt(self, keyobj, &key, &flags))
1488 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001489 if (!checkTxnObj(txnobj, &txn)) {
1490 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001492 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493
1494 CLEAR_DBT(data);
1495 if (CHECK_DBFLAG(self, DB_THREAD)) {
1496 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1497 data.flags = DB_DBT_MALLOC;
1498 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001499 if (!add_partial_dbt(&data, dlen, doff)) {
1500 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001501 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001502 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503
1504 MYDB_BEGIN_ALLOW_THREADS;
1505 err = self->db->get(self->db, txn, &key, &data, flags);
1506 MYDB_END_ALLOW_THREADS;
1507
Gregory P. Smithe9477062005-06-04 06:46:59 +00001508 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001509 err = 0;
1510 Py_INCREF(dfltobj);
1511 retval = dfltobj;
1512 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001513 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1514 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515 err = 0;
1516 Py_INCREF(Py_None);
1517 retval = Py_None;
1518 }
1519 else if (!err) {
1520 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001521 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1522 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001523 else /* return just the data */
1524 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525 FREE_DBT(data);
1526 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001527 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528
1529 RETURN_IF_ERR();
1530 return retval;
1531}
1532
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001533#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001534static PyObject*
1535DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1536{
1537 int err, flags=0;
1538 PyObject* txnobj = NULL;
1539 PyObject* keyobj;
1540 PyObject* dfltobj = NULL;
1541 PyObject* retval = NULL;
1542 int dlen = -1;
1543 int doff = -1;
1544 DBT key, pkey, data;
1545 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001546 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001547 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001548
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1550 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1551 &doff))
1552 return NULL;
1553
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
1557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
1559 return NULL;
1560 }
1561
1562 CLEAR_DBT(data);
1563 if (CHECK_DBFLAG(self, DB_THREAD)) {
1564 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1565 data.flags = DB_DBT_MALLOC;
1566 }
1567 if (!add_partial_dbt(&data, dlen, doff)) {
1568 FREE_DBT(key);
1569 return NULL;
1570 }
1571
1572 CLEAR_DBT(pkey);
1573 pkey.flags = DB_DBT_MALLOC;
1574
1575 MYDB_BEGIN_ALLOW_THREADS;
1576 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1577 MYDB_END_ALLOW_THREADS;
1578
Gregory P. Smithe9477062005-06-04 06:46:59 +00001579 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001580 err = 0;
1581 Py_INCREF(dfltobj);
1582 retval = dfltobj;
1583 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001584 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1585 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001586 err = 0;
1587 Py_INCREF(Py_None);
1588 retval = Py_None;
1589 }
1590 else if (!err) {
1591 PyObject *pkeyObj;
1592 PyObject *dataObj;
1593 dataObj = PyString_FromStringAndSize(data.data, data.size);
1594
1595 if (self->primaryDBType == DB_RECNO ||
1596 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001597 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001598 else
1599 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1600
1601 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1602 {
1603 PyObject *keyObj;
1604 int type = _DB_get_type(self);
1605 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001606 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001607 else
1608 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001609#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001610 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001611#else
1612 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1613#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001614 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001615 }
1616 else /* return just the pkey and data */
1617 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001618#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001619 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001620#else
1621 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1622#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001623 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001624 Py_DECREF(dataObj);
1625 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001626 FREE_DBT(pkey);
1627 FREE_DBT(data);
1628 }
1629 FREE_DBT(key);
1630
1631 RETURN_IF_ERR();
1632 return retval;
1633}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001634#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001635
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636
1637/* Return size of entry */
1638static PyObject*
1639DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1640{
1641 int err, flags=0;
1642 PyObject* txnobj = NULL;
1643 PyObject* keyobj;
1644 PyObject* retval = NULL;
1645 DBT key, data;
1646 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001647 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648
1649 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1650 &keyobj, &txnobj))
1651 return NULL;
1652 CHECK_DB_NOT_CLOSED(self);
1653 if (!make_key_dbt(self, keyobj, &key, &flags))
1654 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001655 if (!checkTxnObj(txnobj, &txn)) {
1656 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001658 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 CLEAR_DBT(data);
1660
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001661 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1662 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663 data.flags = DB_DBT_USERMEM;
1664 data.ulen = 0;
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->get(self->db, txn, &key, &data, flags);
1667 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001668 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001669 retval = PyInt_FromLong((long)data.size);
1670 err = 0;
1671 }
1672
1673 FREE_DBT(key);
1674 FREE_DBT(data);
1675 RETURN_IF_ERR();
1676 return retval;
1677}
1678
1679
1680static PyObject*
1681DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1682{
1683 int err, flags=0;
1684 PyObject* txnobj = NULL;
1685 PyObject* keyobj;
1686 PyObject* dataobj;
1687 PyObject* retval = NULL;
1688 DBT key, data;
1689 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001690 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691
1692
1693 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1694 &keyobj, &dataobj, &txnobj, &flags))
1695 return NULL;
1696
1697 CHECK_DB_NOT_CLOSED(self);
1698 if (!make_key_dbt(self, keyobj, &key, NULL))
1699 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001700 if ( !make_dbt(dataobj, &data) ||
1701 !checkTxnObj(txnobj, &txn) )
1702 {
1703 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001704 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001705 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706
1707 flags |= DB_GET_BOTH;
1708
1709 if (CHECK_DBFLAG(self, DB_THREAD)) {
1710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1711 data.flags = DB_DBT_MALLOC;
1712 /* TODO: Is this flag needed? We're passing a data object that should
1713 match what's in the DB, so there should be no need to malloc.
1714 We run the risk of freeing something twice! Check this. */
1715 }
1716
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1720
Gregory P. Smithe9477062005-06-04 06:46:59 +00001721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1722 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 err = 0;
1724 Py_INCREF(Py_None);
1725 retval = Py_None;
1726 }
1727 else if (!err) {
1728 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1729 FREE_DBT(data); /* Only if retrieval was successful */
1730 }
1731
1732 FREE_DBT(key);
1733 RETURN_IF_ERR();
1734 return retval;
1735}
1736
1737
1738static PyObject*
1739DB_get_byteswapped(DBObject* self, PyObject* args)
1740{
1741#if (DBVER >= 33)
1742 int err = 0;
1743#endif
1744 int retval = -1;
1745
1746 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1747 return NULL;
1748 CHECK_DB_NOT_CLOSED(self);
1749
1750#if (DBVER >= 33)
1751 MYDB_BEGIN_ALLOW_THREADS;
1752 err = self->db->get_byteswapped(self->db, &retval);
1753 MYDB_END_ALLOW_THREADS;
1754 RETURN_IF_ERR();
1755#else
1756 MYDB_BEGIN_ALLOW_THREADS;
1757 retval = self->db->get_byteswapped(self->db);
1758 MYDB_END_ALLOW_THREADS;
1759#endif
1760 return PyInt_FromLong(retval);
1761}
1762
1763
1764static PyObject*
1765DB_get_type(DBObject* self, PyObject* args)
1766{
1767 int type;
1768
1769 if (!PyArg_ParseTuple(args,":get_type"))
1770 return NULL;
1771 CHECK_DB_NOT_CLOSED(self);
1772
1773 MYDB_BEGIN_ALLOW_THREADS;
1774 type = _DB_get_type(self);
1775 MYDB_END_ALLOW_THREADS;
1776 if (type == -1)
1777 return NULL;
1778 return PyInt_FromLong(type);
1779}
1780
1781
1782static PyObject*
1783DB_join(DBObject* self, PyObject* args)
1784{
1785 int err, flags=0;
1786 int length, x;
1787 PyObject* cursorsObj;
1788 DBC** cursors;
1789 DBC* dbc;
1790
1791
1792 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1793 return NULL;
1794
1795 CHECK_DB_NOT_CLOSED(self);
1796
1797 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001798 PyErr_SetString(PyExc_TypeError,
1799 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001800 return NULL;
1801 }
1802
1803 length = PyObject_Length(cursorsObj);
1804 cursors = malloc((length+1) * sizeof(DBC*));
1805 cursors[length] = NULL;
1806 for (x=0; x<length; x++) {
1807 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001808 if (item == NULL) {
1809 free(cursors);
1810 return NULL;
1811 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001812 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001813 PyErr_SetString(PyExc_TypeError,
1814 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001815 free(cursors);
1816 return NULL;
1817 }
1818 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001819 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001820 }
1821
1822 MYDB_BEGIN_ALLOW_THREADS;
1823 err = self->db->join(self->db, cursors, &dbc, flags);
1824 MYDB_END_ALLOW_THREADS;
1825 free(cursors);
1826 RETURN_IF_ERR();
1827
Gregory P. Smith7441e652003-11-03 21:35:31 +00001828 /* FIXME: this is a buggy interface. The returned cursor
1829 contains internal references to the passed in cursors
1830 but does not hold python references to them or prevent
1831 them from being closed prematurely. This can cause
1832 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001833 return (PyObject*) newDBCursorObject(dbc, self);
1834}
1835
1836
1837static PyObject*
1838DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1839{
1840 int err, flags=0;
1841 PyObject* txnobj = NULL;
1842 PyObject* keyobj;
1843 DBT key;
1844 DB_TXN *txn = NULL;
1845 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001846 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001847
1848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1849 &keyobj, &txnobj, &flags))
1850 return NULL;
1851 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001852 if (!make_dbt(keyobj, &key))
1853 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 return NULL;
1855 if (!checkTxnObj(txnobj, &txn))
1856 return NULL;
1857
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->key_range(self->db, txn, &key, &range, flags);
1860 MYDB_END_ALLOW_THREADS;
1861
1862 RETURN_IF_ERR();
1863 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1864}
1865
1866
1867static PyObject*
1868DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1869{
1870 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1871 char* filename = NULL;
1872 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001873#if (DBVER >= 41)
1874 PyObject *txnobj = NULL;
1875 DB_TXN *txn = NULL;
1876 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001877 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001878 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1879 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001880 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001881 "filename", "dbtype", "flags", "mode", "txn", NULL};
1882#else
1883 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001884 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001885 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1886 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001887 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001888 "filename", "dbtype", "flags", "mode", NULL};
1889#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001890
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001891#if (DBVER >= 41)
1892 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1893 &filename, &dbname, &type, &flags, &mode,
1894 &txnobj))
1895#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001897 &filename, &dbname, &type, &flags,
1898 &mode))
1899#endif
1900 {
1901 PyErr_Clear();
1902 type = DB_UNKNOWN; flags = 0; mode = 0660;
1903 filename = NULL; dbname = NULL;
1904#if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1906 kwnames_basic,
1907 &filename, &type, &flags, &mode,
1908 &txnobj))
1909 return NULL;
1910#else
1911 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1912 kwnames_basic,
1913 &filename, &type, &flags, &mode))
1914 return NULL;
1915#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 }
1917
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001918#if (DBVER >= 41)
1919 if (!checkTxnObj(txnobj, &txn)) return NULL;
1920#endif
1921
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001922 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001923 PyObject *t = Py_BuildValue("(is)", 0,
1924 "Cannot call open() twice for DB object");
1925 PyErr_SetObject(DBError, t);
1926 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001927 return NULL;
1928 }
1929
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001930#if 0 && (DBVER >= 41)
1931 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1932 && (self->myenvobj->flags & DB_INIT_TXN))
1933 {
1934 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1935 * explicitly passed) but we are in a transaction ready environment:
1936 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1937 * to work on BerkeleyDB 4.1 without needing to modify their
1938 * DBEnv or DB open calls.
1939 * TODO make this behaviour of the library configurable.
1940 */
1941 flags |= DB_AUTO_COMMIT;
1942 }
1943#endif
1944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001945 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001946#if (DBVER >= 41)
1947 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1948#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001949 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001950#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 MYDB_END_ALLOW_THREADS;
1952 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001953 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 self->db = NULL;
1955 return NULL;
1956 }
1957
1958 self->flags = flags;
1959 RETURN_NONE();
1960}
1961
1962
1963static PyObject*
1964DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1965{
1966 int flags=0;
1967 PyObject* txnobj = NULL;
1968 int dlen = -1;
1969 int doff = -1;
1970 PyObject* keyobj, *dataobj, *retval;
1971 DBT key, data;
1972 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001973 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001974 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001975
1976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1977 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1978 return NULL;
1979
1980 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001981 if (!make_key_dbt(self, keyobj, &key, NULL))
1982 return NULL;
1983 if ( !make_dbt(dataobj, &data) ||
1984 !add_partial_dbt(&data, dlen, doff) ||
1985 !checkTxnObj(txnobj, &txn) )
1986 {
1987 FREE_DBT(key);
1988 return NULL;
1989 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001990
1991 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1992 FREE_DBT(key);
1993 return NULL;
1994 }
1995
1996 if (flags & DB_APPEND)
1997 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1998 else {
1999 retval = Py_None;
2000 Py_INCREF(retval);
2001 }
2002 FREE_DBT(key);
2003 return retval;
2004}
2005
2006
2007
2008static PyObject*
2009DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2010{
2011 char* filename;
2012 char* database = NULL;
2013 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002014 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002015
2016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2017 &filename, &database, &flags))
2018 return NULL;
2019 CHECK_DB_NOT_CLOSED(self);
2020
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002021 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002022 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002023 RETURN_IF_ERR();
2024 RETURN_NONE();
2025}
2026
2027
2028
2029static PyObject*
2030DB_rename(DBObject* self, PyObject* args)
2031{
2032 char* filename;
2033 char* database;
2034 char* newname;
2035 int err, flags=0;
2036
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2038 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002039 return NULL;
2040 CHECK_DB_NOT_CLOSED(self);
2041
2042 MYDB_BEGIN_ALLOW_THREADS;
2043 err = self->db->rename(self->db, filename, database, newname, flags);
2044 MYDB_END_ALLOW_THREADS;
2045 RETURN_IF_ERR();
2046 RETURN_NONE();
2047}
2048
2049
2050static PyObject*
2051DB_set_bt_minkey(DBObject* self, PyObject* args)
2052{
2053 int err, minkey;
2054
2055 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2056 return NULL;
2057 CHECK_DB_NOT_CLOSED(self);
2058
2059 MYDB_BEGIN_ALLOW_THREADS;
2060 err = self->db->set_bt_minkey(self->db, minkey);
2061 MYDB_END_ALLOW_THREADS;
2062 RETURN_IF_ERR();
2063 RETURN_NONE();
2064}
2065
Neal Norwitz84562352005-10-20 04:30:15 +00002066#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002067static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002068_default_cmp(const DBT *leftKey,
2069 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002070{
2071 int res;
2072 int lsize = leftKey->size, rsize = rightKey->size;
2073
Georg Brandlef1701f2006-03-07 14:57:48 +00002074 res = memcmp(leftKey->data, rightKey->data,
2075 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002076
2077 if (res == 0) {
2078 if (lsize < rsize) {
2079 res = -1;
2080 }
2081 else if (lsize > rsize) {
2082 res = 1;
2083 }
2084 }
2085 return res;
2086}
2087
2088static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002089_db_compareCallback(DB* db,
2090 const DBT *leftKey,
2091 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002092{
2093 int res = 0;
2094 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002095 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002096 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002097
2098 if (self == NULL || self->btCompareCallback == NULL) {
2099 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002100 PyErr_SetString(PyExc_TypeError,
2101 (self == 0
2102 ? "DB_bt_compare db is NULL."
2103 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002104 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002105 PyErr_Print();
2106 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002107 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002108 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002109 MYDB_BEGIN_BLOCK_THREADS;
2110
Thomas Woutersb3153832006-03-08 01:47:19 +00002111 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2112 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002113 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002114 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002115 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002117 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002118 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002119 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002120 PyErr_Print();
2121 res = _default_cmp(leftKey, rightKey);
2122 } else if (PyInt_Check(result)) {
2123 res = PyInt_AsLong(result);
2124 } else {
2125 PyErr_SetString(PyExc_TypeError,
2126 "DB_bt_compare callback MUST return an int.");
2127 /* we're in a callback within the DB code, we can't raise */
2128 PyErr_Print();
2129 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002130 }
2131
Thomas Woutersb3153832006-03-08 01:47:19 +00002132 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002133 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002134
2135 MYDB_END_BLOCK_THREADS;
2136 }
2137 return res;
2138}
2139
2140static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002141DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002142{
2143 int err;
2144 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002145 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002146
Georg Brandlef1701f2006-03-07 14:57:48 +00002147 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002148 return NULL;
2149
Georg Brandlef1701f2006-03-07 14:57:48 +00002150 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002151
Georg Brandlef1701f2006-03-07 14:57:48 +00002152 if (!PyCallable_Check(comparator)) {
2153 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002154 return NULL;
2155 }
2156
2157 /*
2158 * Perform a test call of the comparator function with two empty
2159 * string objects here. verify that it returns an int (0).
2160 * err if not.
2161 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002162 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002163 result = PyEval_CallObject(comparator, tuple);
2164 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002165 if (result == NULL)
2166 return NULL;
2167 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002168 PyErr_SetString(PyExc_TypeError,
2169 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002170 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002171 } else if (PyInt_AsLong(result) != 0) {
2172 PyErr_SetString(PyExc_TypeError,
2173 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002174 return NULL;
2175 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002176 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002177
2178 /* We don't accept multiple set_bt_compare operations, in order to
2179 * simplify the code. This would have no real use, as one cannot
2180 * change the function once the db is opened anyway */
2181 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002182 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002183 return NULL;
2184 }
2185
Georg Brandlef1701f2006-03-07 14:57:48 +00002186 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002187 self->btCompareCallback = comparator;
2188
2189 /* This is to workaround a problem with un-initialized threads (see
2190 comment in DB_associate) */
2191#ifdef WITH_THREAD
2192 PyEval_InitThreads();
2193#endif
2194
Thomas Woutersb3153832006-03-08 01:47:19 +00002195 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002196
2197 if (err) {
2198 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002199 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002200 self->btCompareCallback = NULL;
2201 }
2202
Georg Brandlef1701f2006-03-07 14:57:48 +00002203 RETURN_IF_ERR();
2204 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002205}
Neal Norwitz84562352005-10-20 04:30:15 +00002206#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002207
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002208
2209static PyObject*
2210DB_set_cachesize(DBObject* self, PyObject* args)
2211{
2212 int err;
2213 int gbytes = 0, bytes = 0, ncache = 0;
2214
2215 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2216 &gbytes,&bytes,&ncache))
2217 return NULL;
2218 CHECK_DB_NOT_CLOSED(self);
2219
2220 MYDB_BEGIN_ALLOW_THREADS;
2221 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2222 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2225}
2226
2227
2228static PyObject*
2229DB_set_flags(DBObject* self, PyObject* args)
2230{
2231 int err, flags;
2232
2233 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2234 return NULL;
2235 CHECK_DB_NOT_CLOSED(self);
2236
2237 MYDB_BEGIN_ALLOW_THREADS;
2238 err = self->db->set_flags(self->db, flags);
2239 MYDB_END_ALLOW_THREADS;
2240 RETURN_IF_ERR();
2241
2242 self->setflags |= flags;
2243 RETURN_NONE();
2244}
2245
2246
2247static PyObject*
2248DB_set_h_ffactor(DBObject* self, PyObject* args)
2249{
2250 int err, ffactor;
2251
2252 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2253 return NULL;
2254 CHECK_DB_NOT_CLOSED(self);
2255
2256 MYDB_BEGIN_ALLOW_THREADS;
2257 err = self->db->set_h_ffactor(self->db, ffactor);
2258 MYDB_END_ALLOW_THREADS;
2259 RETURN_IF_ERR();
2260 RETURN_NONE();
2261}
2262
2263
2264static PyObject*
2265DB_set_h_nelem(DBObject* self, PyObject* args)
2266{
2267 int err, nelem;
2268
2269 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2270 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2272
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_h_nelem(self->db, nelem);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2278}
2279
2280
2281static PyObject*
2282DB_set_lorder(DBObject* self, PyObject* args)
2283{
2284 int err, lorder;
2285
2286 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2287 return NULL;
2288 CHECK_DB_NOT_CLOSED(self);
2289
2290 MYDB_BEGIN_ALLOW_THREADS;
2291 err = self->db->set_lorder(self->db, lorder);
2292 MYDB_END_ALLOW_THREADS;
2293 RETURN_IF_ERR();
2294 RETURN_NONE();
2295}
2296
2297
2298static PyObject*
2299DB_set_pagesize(DBObject* self, PyObject* args)
2300{
2301 int err, pagesize;
2302
2303 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2304 return NULL;
2305 CHECK_DB_NOT_CLOSED(self);
2306
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->set_pagesize(self->db, pagesize);
2309 MYDB_END_ALLOW_THREADS;
2310 RETURN_IF_ERR();
2311 RETURN_NONE();
2312}
2313
2314
2315static PyObject*
2316DB_set_re_delim(DBObject* self, PyObject* args)
2317{
2318 int err;
2319 char delim;
2320
2321 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2322 PyErr_Clear();
2323 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2324 return NULL;
2325 }
2326
2327 CHECK_DB_NOT_CLOSED(self);
2328
2329 MYDB_BEGIN_ALLOW_THREADS;
2330 err = self->db->set_re_delim(self->db, delim);
2331 MYDB_END_ALLOW_THREADS;
2332 RETURN_IF_ERR();
2333 RETURN_NONE();
2334}
2335
2336static PyObject*
2337DB_set_re_len(DBObject* self, PyObject* args)
2338{
2339 int err, len;
2340
2341 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2342 return NULL;
2343 CHECK_DB_NOT_CLOSED(self);
2344
2345 MYDB_BEGIN_ALLOW_THREADS;
2346 err = self->db->set_re_len(self->db, len);
2347 MYDB_END_ALLOW_THREADS;
2348 RETURN_IF_ERR();
2349 RETURN_NONE();
2350}
2351
2352
2353static PyObject*
2354DB_set_re_pad(DBObject* self, PyObject* args)
2355{
2356 int err;
2357 char pad;
2358
2359 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2360 PyErr_Clear();
2361 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2362 return NULL;
2363 }
2364 CHECK_DB_NOT_CLOSED(self);
2365
2366 MYDB_BEGIN_ALLOW_THREADS;
2367 err = self->db->set_re_pad(self->db, pad);
2368 MYDB_END_ALLOW_THREADS;
2369 RETURN_IF_ERR();
2370 RETURN_NONE();
2371}
2372
2373
2374static PyObject*
2375DB_set_re_source(DBObject* self, PyObject* args)
2376{
2377 int err;
2378 char *re_source;
2379
2380 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2381 return NULL;
2382 CHECK_DB_NOT_CLOSED(self);
2383
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_re_source(self->db, re_source);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388 RETURN_NONE();
2389}
2390
2391
2392#if (DBVER >= 32)
2393static PyObject*
2394DB_set_q_extentsize(DBObject* self, PyObject* args)
2395{
2396 int err;
2397 int extentsize;
2398
2399 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2400 return NULL;
2401 CHECK_DB_NOT_CLOSED(self);
2402
2403 MYDB_BEGIN_ALLOW_THREADS;
2404 err = self->db->set_q_extentsize(self->db, extentsize);
2405 MYDB_END_ALLOW_THREADS;
2406 RETURN_IF_ERR();
2407 RETURN_NONE();
2408}
2409#endif
2410
2411static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002412DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002413{
2414 int err, flags = 0, type;
2415 void* sp;
2416 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002417#if (DBVER >= 43)
2418 PyObject* txnobj = NULL;
2419 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002420 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002421#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002422 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002423#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002424
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002425#if (DBVER >= 43)
2426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2427 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002428 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002429 if (!checkTxnObj(txnobj, &txn))
2430 return NULL;
2431#else
2432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2433 return NULL;
2434#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002435 CHECK_DB_NOT_CLOSED(self);
2436
2437 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002438#if (DBVER >= 43)
2439 err = self->db->stat(self->db, txn, &sp, flags);
2440#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002441 err = self->db->stat(self->db, &sp, flags);
2442#else
2443 err = self->db->stat(self->db, &sp, NULL, flags);
2444#endif
2445 MYDB_END_ALLOW_THREADS;
2446 RETURN_IF_ERR();
2447
2448 self->haveStat = 1;
2449
2450 /* Turn the stat structure into a dictionary */
2451 type = _DB_get_type(self);
2452 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2453 free(sp);
2454 return NULL;
2455 }
2456
2457#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2458#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2459#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2460
2461 switch (type) {
2462 case DB_HASH:
2463 MAKE_HASH_ENTRY(magic);
2464 MAKE_HASH_ENTRY(version);
2465 MAKE_HASH_ENTRY(nkeys);
2466 MAKE_HASH_ENTRY(ndata);
2467 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002468#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002469 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002470#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002471 MAKE_HASH_ENTRY(ffactor);
2472 MAKE_HASH_ENTRY(buckets);
2473 MAKE_HASH_ENTRY(free);
2474 MAKE_HASH_ENTRY(bfree);
2475 MAKE_HASH_ENTRY(bigpages);
2476 MAKE_HASH_ENTRY(big_bfree);
2477 MAKE_HASH_ENTRY(overflows);
2478 MAKE_HASH_ENTRY(ovfl_free);
2479 MAKE_HASH_ENTRY(dup);
2480 MAKE_HASH_ENTRY(dup_free);
2481 break;
2482
2483 case DB_BTREE:
2484 case DB_RECNO:
2485 MAKE_BT_ENTRY(magic);
2486 MAKE_BT_ENTRY(version);
2487 MAKE_BT_ENTRY(nkeys);
2488 MAKE_BT_ENTRY(ndata);
2489 MAKE_BT_ENTRY(pagesize);
2490 MAKE_BT_ENTRY(minkey);
2491 MAKE_BT_ENTRY(re_len);
2492 MAKE_BT_ENTRY(re_pad);
2493 MAKE_BT_ENTRY(levels);
2494 MAKE_BT_ENTRY(int_pg);
2495 MAKE_BT_ENTRY(leaf_pg);
2496 MAKE_BT_ENTRY(dup_pg);
2497 MAKE_BT_ENTRY(over_pg);
2498 MAKE_BT_ENTRY(free);
2499 MAKE_BT_ENTRY(int_pgfree);
2500 MAKE_BT_ENTRY(leaf_pgfree);
2501 MAKE_BT_ENTRY(dup_pgfree);
2502 MAKE_BT_ENTRY(over_pgfree);
2503 break;
2504
2505 case DB_QUEUE:
2506 MAKE_QUEUE_ENTRY(magic);
2507 MAKE_QUEUE_ENTRY(version);
2508 MAKE_QUEUE_ENTRY(nkeys);
2509 MAKE_QUEUE_ENTRY(ndata);
2510 MAKE_QUEUE_ENTRY(pagesize);
2511 MAKE_QUEUE_ENTRY(pages);
2512 MAKE_QUEUE_ENTRY(re_len);
2513 MAKE_QUEUE_ENTRY(re_pad);
2514 MAKE_QUEUE_ENTRY(pgfree);
2515#if (DBVER == 31)
2516 MAKE_QUEUE_ENTRY(start);
2517#endif
2518 MAKE_QUEUE_ENTRY(first_recno);
2519 MAKE_QUEUE_ENTRY(cur_recno);
2520 break;
2521
2522 default:
2523 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2524 Py_DECREF(d);
2525 d = NULL;
2526 }
2527
2528#undef MAKE_HASH_ENTRY
2529#undef MAKE_BT_ENTRY
2530#undef MAKE_QUEUE_ENTRY
2531
2532 free(sp);
2533 return d;
2534}
2535
2536static PyObject*
2537DB_sync(DBObject* self, PyObject* args)
2538{
2539 int err;
2540 int flags = 0;
2541
2542 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2543 return NULL;
2544 CHECK_DB_NOT_CLOSED(self);
2545
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->db->sync(self->db, flags);
2548 MYDB_END_ALLOW_THREADS;
2549 RETURN_IF_ERR();
2550 RETURN_NONE();
2551}
2552
2553
2554#if (DBVER >= 33)
2555static PyObject*
2556DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2557{
2558 int err, flags=0;
2559 u_int32_t count=0;
2560 PyObject* txnobj = NULL;
2561 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002562 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002563
2564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2565 &txnobj, &flags))
2566 return NULL;
2567 CHECK_DB_NOT_CLOSED(self);
2568 if (!checkTxnObj(txnobj, &txn))
2569 return NULL;
2570
2571 MYDB_BEGIN_ALLOW_THREADS;
2572 err = self->db->truncate(self->db, txn, &count, flags);
2573 MYDB_END_ALLOW_THREADS;
2574 RETURN_IF_ERR();
2575 return PyInt_FromLong(count);
2576}
2577#endif
2578
2579
2580static PyObject*
2581DB_upgrade(DBObject* self, PyObject* args)
2582{
2583 int err, flags=0;
2584 char *filename;
2585
2586 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2587 return NULL;
2588 CHECK_DB_NOT_CLOSED(self);
2589
2590 MYDB_BEGIN_ALLOW_THREADS;
2591 err = self->db->upgrade(self->db, filename, flags);
2592 MYDB_END_ALLOW_THREADS;
2593 RETURN_IF_ERR();
2594 RETURN_NONE();
2595}
2596
2597
2598static PyObject*
2599DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2600{
2601 int err, flags=0;
2602 char* fileName;
2603 char* dbName=NULL;
2604 char* outFileName=NULL;
2605 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002606 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002607 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002608
2609 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2610 &fileName, &dbName, &outFileName, &flags))
2611 return NULL;
2612
2613 CHECK_DB_NOT_CLOSED(self);
2614 if (outFileName)
2615 outFile = fopen(outFileName, "w");
2616
2617 MYDB_BEGIN_ALLOW_THREADS;
2618 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2619 MYDB_END_ALLOW_THREADS;
2620 if (outFileName)
2621 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002622
2623 /* DB.verify acts as a DB handle destructor (like close); this was
2624 * documented in BerkeleyDB 4.2 but had the undocumented effect
2625 * of not being safe in prior versions while still requiring an explicit
2626 * DB.close call afterwards. Lets call close for the user to emulate
2627 * the safe 4.2 behaviour. */
2628#if (DBVER <= 41)
2629 self->db->close(self->db, 0);
2630#endif
2631 self->db = NULL;
2632
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002633 RETURN_IF_ERR();
2634 RETURN_NONE();
2635}
2636
2637
2638static PyObject*
2639DB_set_get_returns_none(DBObject* self, PyObject* args)
2640{
2641 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002642 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002643
2644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2645 return NULL;
2646 CHECK_DB_NOT_CLOSED(self);
2647
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002648 if (self->moduleFlags.getReturnsNone)
2649 ++oldValue;
2650 if (self->moduleFlags.cursorSetReturnsNone)
2651 ++oldValue;
2652 self->moduleFlags.getReturnsNone = (flags >= 1);
2653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654 return PyInt_FromLong(oldValue);
2655}
2656
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002657#if (DBVER >= 41)
2658static PyObject*
2659DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2660{
2661 int err;
2662 u_int32_t flags=0;
2663 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002664 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002665
2666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2667 &passwd, &flags)) {
2668 return NULL;
2669 }
2670
2671 MYDB_BEGIN_ALLOW_THREADS;
2672 err = self->db->set_encrypt(self->db, passwd, flags);
2673 MYDB_END_ALLOW_THREADS;
2674
2675 RETURN_IF_ERR();
2676 RETURN_NONE();
2677}
2678#endif /* DBVER >= 41 */
2679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002680
2681/*-------------------------------------------------------------- */
2682/* Mapping and Dictionary-like access routines */
2683
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002684Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002685{
2686 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002687 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 int flags = 0;
2689 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002690 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002691
2692 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002693 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2694 PyErr_SetObject(DBError, t);
2695 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 return -1;
2697 }
2698
2699 if (self->haveStat) { /* Has the stat function been called recently? If
2700 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002701 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 }
2703
2704 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002705redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002706#if (DBVER >= 43)
2707 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2708#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 err = self->db->stat(self->db, &sp, flags);
2710#else
2711 err = self->db->stat(self->db, &sp, NULL, flags);
2712#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002713
2714 /* All the stat structures have matching fields upto the ndata field,
2715 so we can use any of them for the type cast */
2716 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2717
2718 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2719 * redo a full stat to make sure.
2720 * Fixes SF python bug 1493322, pybsddb bug 1184012
2721 */
2722 if (size == 0 && (flags & DB_FAST_STAT)) {
2723 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002724 if (!err)
2725 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002726 goto redo_stat_for_length;
2727 }
2728
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002729 MYDB_END_ALLOW_THREADS;
2730
2731 if (err)
2732 return -1;
2733
2734 self->haveStat = 1;
2735
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 free(sp);
2737 return size;
2738}
2739
2740
2741PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2742{
2743 int err;
2744 PyObject* retval;
2745 DBT key;
2746 DBT data;
2747
2748 CHECK_DB_NOT_CLOSED(self);
2749 if (!make_key_dbt(self, keyobj, &key, NULL))
2750 return NULL;
2751
2752 CLEAR_DBT(data);
2753 if (CHECK_DBFLAG(self, DB_THREAD)) {
2754 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2755 data.flags = DB_DBT_MALLOC;
2756 }
2757 MYDB_BEGIN_ALLOW_THREADS;
2758 err = self->db->get(self->db, NULL, &key, &data, 0);
2759 MYDB_END_ALLOW_THREADS;
2760 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2761 PyErr_SetObject(PyExc_KeyError, keyobj);
2762 retval = NULL;
2763 }
2764 else if (makeDBError(err)) {
2765 retval = NULL;
2766 }
2767 else {
2768 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2769 FREE_DBT(data);
2770 }
2771
2772 FREE_DBT(key);
2773 return retval;
2774}
2775
2776
2777static int
2778DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2779{
2780 DBT key, data;
2781 int retval;
2782 int flags = 0;
2783
2784 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002785 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2786 PyErr_SetObject(DBError, t);
2787 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788 return -1;
2789 }
2790
2791 if (!make_key_dbt(self, keyobj, &key, NULL))
2792 return -1;
2793
2794 if (dataobj != NULL) {
2795 if (!make_dbt(dataobj, &data))
2796 retval = -1;
2797 else {
2798 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002799 /* dictionaries shouldn't have duplicate keys */
2800 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801 retval = _DB_put(self, NULL, &key, &data, flags);
2802
2803 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002804 /* try deleting any old record that matches and then PUT it
2805 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002806 _DB_delete(self, NULL, &key, 0);
2807 PyErr_Clear();
2808 retval = _DB_put(self, NULL, &key, &data, flags);
2809 }
2810 }
2811 }
2812 else {
2813 /* dataobj == NULL, so delete the key */
2814 retval = _DB_delete(self, NULL, &key, 0);
2815 }
2816 FREE_DBT(key);
2817 return retval;
2818}
2819
2820
2821static PyObject*
2822DB_has_key(DBObject* self, PyObject* args)
2823{
2824 int err;
2825 PyObject* keyobj;
2826 DBT key, data;
2827 PyObject* txnobj = NULL;
2828 DB_TXN *txn = NULL;
2829
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002830 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002831 return NULL;
2832 CHECK_DB_NOT_CLOSED(self);
2833 if (!make_key_dbt(self, keyobj, &key, NULL))
2834 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002835 if (!checkTxnObj(txnobj, &txn)) {
2836 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002837 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002838 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002840 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002841 it has a record but can't allocate a buffer for the data. This saves
2842 having to deal with data we won't be using.
2843 */
2844 CLEAR_DBT(data);
2845 data.flags = DB_DBT_USERMEM;
2846
2847 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002848 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849 MYDB_END_ALLOW_THREADS;
2850 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002851
2852 if (err == DB_BUFFER_SMALL || err == 0) {
2853 return PyInt_FromLong(1);
2854 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2855 return PyInt_FromLong(0);
2856 }
2857
2858 makeDBError(err);
2859 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860}
2861
2862
2863#define _KEYS_LIST 1
2864#define _VALUES_LIST 2
2865#define _ITEMS_LIST 3
2866
2867static PyObject*
2868_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2869{
2870 int err, dbtype;
2871 DBT key;
2872 DBT data;
2873 DBC *cursor;
2874 PyObject* list;
2875 PyObject* item = NULL;
2876
2877 CHECK_DB_NOT_CLOSED(self);
2878 CLEAR_DBT(key);
2879 CLEAR_DBT(data);
2880
2881 dbtype = _DB_get_type(self);
2882 if (dbtype == -1)
2883 return NULL;
2884
2885 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002886 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002887 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002888
2889 /* get a cursor */
2890 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002891 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002892 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002893 if (makeDBError(err)) {
2894 Py_DECREF(list);
2895 return NULL;
2896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002897
2898 if (CHECK_DBFLAG(self, DB_THREAD)) {
2899 key.flags = DB_DBT_REALLOC;
2900 data.flags = DB_DBT_REALLOC;
2901 }
2902
2903 while (1) { /* use the cursor to traverse the DB, collecting items */
2904 MYDB_BEGIN_ALLOW_THREADS;
2905 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2906 MYDB_END_ALLOW_THREADS;
2907
2908 if (err) {
2909 /* for any error, break out of the loop */
2910 break;
2911 }
2912
2913 switch (type) {
2914 case _KEYS_LIST:
2915 switch(dbtype) {
2916 case DB_BTREE:
2917 case DB_HASH:
2918 default:
2919 item = PyString_FromStringAndSize((char*)key.data, key.size);
2920 break;
2921 case DB_RECNO:
2922 case DB_QUEUE:
2923 item = PyInt_FromLong(*((db_recno_t*)key.data));
2924 break;
2925 }
2926 break;
2927
2928 case _VALUES_LIST:
2929 item = PyString_FromStringAndSize((char*)data.data, data.size);
2930 break;
2931
2932 case _ITEMS_LIST:
2933 switch(dbtype) {
2934 case DB_BTREE:
2935 case DB_HASH:
2936 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002937 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2938 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 break;
2940 case DB_RECNO:
2941 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002942 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2943 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002944 break;
2945 }
2946 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002947 default:
2948 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2949 item = NULL;
2950 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002951 }
2952 if (item == NULL) {
2953 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002954 list = NULL;
2955 goto done;
2956 }
2957 PyList_Append(list, item);
2958 Py_DECREF(item);
2959 }
2960
Gregory P. Smithe9477062005-06-04 06:46:59 +00002961 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2962 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002963 Py_DECREF(list);
2964 list = NULL;
2965 }
2966
2967 done:
2968 FREE_DBT(key);
2969 FREE_DBT(data);
2970 MYDB_BEGIN_ALLOW_THREADS;
2971 cursor->c_close(cursor);
2972 MYDB_END_ALLOW_THREADS;
2973 return list;
2974}
2975
2976
2977static PyObject*
2978DB_keys(DBObject* self, PyObject* args)
2979{
2980 PyObject* txnobj = NULL;
2981 DB_TXN *txn = NULL;
2982
Georg Brandl96a8c392006-05-29 21:04:52 +00002983 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002984 return NULL;
2985 if (!checkTxnObj(txnobj, &txn))
2986 return NULL;
2987 return _DB_make_list(self, txn, _KEYS_LIST);
2988}
2989
2990
2991static PyObject*
2992DB_items(DBObject* self, PyObject* args)
2993{
2994 PyObject* txnobj = NULL;
2995 DB_TXN *txn = NULL;
2996
Georg Brandl96a8c392006-05-29 21:04:52 +00002997 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998 return NULL;
2999 if (!checkTxnObj(txnobj, &txn))
3000 return NULL;
3001 return _DB_make_list(self, txn, _ITEMS_LIST);
3002}
3003
3004
3005static PyObject*
3006DB_values(DBObject* self, PyObject* args)
3007{
3008 PyObject* txnobj = NULL;
3009 DB_TXN *txn = NULL;
3010
Georg Brandl96a8c392006-05-29 21:04:52 +00003011 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003012 return NULL;
3013 if (!checkTxnObj(txnobj, &txn))
3014 return NULL;
3015 return _DB_make_list(self, txn, _VALUES_LIST);
3016}
3017
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003018/* --------------------------------------------------------------------- */
3019/* DBCursor methods */
3020
3021
3022static PyObject*
3023DBC_close(DBCursorObject* self, PyObject* args)
3024{
3025 int err = 0;
3026
3027 if (!PyArg_ParseTuple(args, ":close"))
3028 return NULL;
3029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030 if (self->dbc != NULL) {
3031 MYDB_BEGIN_ALLOW_THREADS;
3032 err = self->dbc->c_close(self->dbc);
3033 self->dbc = NULL;
3034 MYDB_END_ALLOW_THREADS;
3035 }
3036 RETURN_IF_ERR();
3037 RETURN_NONE();
3038}
3039
3040
3041static PyObject*
3042DBC_count(DBCursorObject* self, PyObject* args)
3043{
3044 int err = 0;
3045 db_recno_t count;
3046 int flags = 0;
3047
3048 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3049 return NULL;
3050
3051 CHECK_CURSOR_NOT_CLOSED(self);
3052
3053 MYDB_BEGIN_ALLOW_THREADS;
3054 err = self->dbc->c_count(self->dbc, &count, flags);
3055 MYDB_END_ALLOW_THREADS;
3056 RETURN_IF_ERR();
3057
3058 return PyInt_FromLong(count);
3059}
3060
3061
3062static PyObject*
3063DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3064{
3065 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3066}
3067
3068
3069static PyObject*
3070DBC_delete(DBCursorObject* self, PyObject* args)
3071{
3072 int err, flags=0;
3073
3074 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3075 return NULL;
3076
3077 CHECK_CURSOR_NOT_CLOSED(self);
3078
3079 MYDB_BEGIN_ALLOW_THREADS;
3080 err = self->dbc->c_del(self->dbc, flags);
3081 MYDB_END_ALLOW_THREADS;
3082 RETURN_IF_ERR();
3083
3084 self->mydb->haveStat = 0;
3085 RETURN_NONE();
3086}
3087
3088
3089static PyObject*
3090DBC_dup(DBCursorObject* self, PyObject* args)
3091{
3092 int err, flags =0;
3093 DBC* dbc = NULL;
3094
3095 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3096 return NULL;
3097
3098 CHECK_CURSOR_NOT_CLOSED(self);
3099
3100 MYDB_BEGIN_ALLOW_THREADS;
3101 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3102 MYDB_END_ALLOW_THREADS;
3103 RETURN_IF_ERR();
3104
3105 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3106}
3107
3108static PyObject*
3109DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3110{
3111 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3112}
3113
3114
3115static PyObject*
3116DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3117{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003118 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003119 PyObject* keyobj = NULL;
3120 PyObject* dataobj = NULL;
3121 PyObject* retval = NULL;
3122 int dlen = -1;
3123 int doff = -1;
3124 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003125 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003126 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003127
3128 CLEAR_DBT(key);
3129 CLEAR_DBT(data);
3130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003131 &flags, &dlen, &doff))
3132 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003133 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3135 &kwnames[1],
3136 &keyobj, &flags, &dlen, &doff))
3137 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003138 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3140 kwnames, &keyobj, &dataobj,
3141 &flags, &dlen, &doff))
3142 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003143 return NULL;
3144 }
3145 }
3146 }
3147
3148 CHECK_CURSOR_NOT_CLOSED(self);
3149
3150 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3151 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003152 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3153 (!add_partial_dbt(&data, dlen, doff)) )
3154 {
3155 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003157 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003158
3159 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3160 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003161 if (!(key.flags & DB_DBT_REALLOC)) {
3162 key.flags |= DB_DBT_MALLOC;
3163 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003164 }
3165
3166 MYDB_BEGIN_ALLOW_THREADS;
3167 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3168 MYDB_END_ALLOW_THREADS;
3169
Gregory P. Smithe9477062005-06-04 06:46:59 +00003170 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3171 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172 Py_INCREF(Py_None);
3173 retval = Py_None;
3174 }
3175 else if (makeDBError(err)) {
3176 retval = NULL;
3177 }
3178 else {
3179 switch (_DB_get_type(self->mydb)) {
3180 case -1:
3181 retval = NULL;
3182 break;
3183 case DB_BTREE:
3184 case DB_HASH:
3185 default:
3186 retval = Py_BuildValue("s#s#", key.data, key.size,
3187 data.data, data.size);
3188 break;
3189 case DB_RECNO:
3190 case DB_QUEUE:
3191 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3192 data.data, data.size);
3193 break;
3194 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003195 FREE_DBT(data);
3196 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003197 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003198 return retval;
3199}
3200
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003201#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003202static PyObject*
3203DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3204{
3205 int err, flags=0;
3206 PyObject* keyobj = NULL;
3207 PyObject* dataobj = NULL;
3208 PyObject* retval = NULL;
3209 int dlen = -1;
3210 int doff = -1;
3211 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003212 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3213 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003214
3215 CLEAR_DBT(key);
3216 CLEAR_DBT(data);
3217 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3218 &flags, &dlen, &doff))
3219 {
3220 PyErr_Clear();
3221 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003222 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003223 &keyobj, &flags, &dlen, &doff))
3224 {
3225 PyErr_Clear();
3226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3227 kwnames, &keyobj, &dataobj,
3228 &flags, &dlen, &doff))
3229 {
3230 return NULL;
3231 }
3232 }
3233 }
3234
3235 CHECK_CURSOR_NOT_CLOSED(self);
3236
3237 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3238 return NULL;
3239 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3240 (!add_partial_dbt(&data, dlen, doff)) ) {
3241 FREE_DBT(key);
3242 return NULL;
3243 }
3244
3245 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3246 data.flags = DB_DBT_MALLOC;
3247 if (!(key.flags & DB_DBT_REALLOC)) {
3248 key.flags |= DB_DBT_MALLOC;
3249 }
3250 }
3251
3252 CLEAR_DBT(pkey);
3253 pkey.flags = DB_DBT_MALLOC;
3254
3255 MYDB_BEGIN_ALLOW_THREADS;
3256 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3257 MYDB_END_ALLOW_THREADS;
3258
Gregory P. Smithe9477062005-06-04 06:46:59 +00003259 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3260 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003261 Py_INCREF(Py_None);
3262 retval = Py_None;
3263 }
3264 else if (makeDBError(err)) {
3265 retval = NULL;
3266 }
3267 else {
3268 PyObject *pkeyObj;
3269 PyObject *dataObj;
3270 dataObj = PyString_FromStringAndSize(data.data, data.size);
3271
3272 if (self->mydb->primaryDBType == DB_RECNO ||
3273 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003274 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003275 else
3276 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3277
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003278 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003279 {
3280 PyObject *keyObj;
3281 int type = _DB_get_type(self->mydb);
3282 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003283 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003284 else
3285 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003286#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003287 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003288#else
3289 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3290#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003291 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003292 FREE_DBT(key);
3293 }
3294 else /* return just the pkey and data */
3295 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003296#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003297 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003298#else
3299 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3300#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003302 Py_DECREF(dataObj);
3303 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003304 FREE_DBT(pkey);
3305 FREE_DBT(data);
3306 }
3307 /* the only time REALLOC should be set is if we used an integer
3308 * key that make_key_dbt malloc'd for us. always free these. */
3309 if (key.flags & DB_DBT_REALLOC) {
3310 FREE_DBT(key);
3311 }
3312 return retval;
3313}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003314#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003315
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003316
3317static PyObject*
3318DBC_get_recno(DBCursorObject* self, PyObject* args)
3319{
3320 int err;
3321 db_recno_t recno;
3322 DBT key;
3323 DBT data;
3324
3325 if (!PyArg_ParseTuple(args, ":get_recno"))
3326 return NULL;
3327
3328 CHECK_CURSOR_NOT_CLOSED(self);
3329
3330 CLEAR_DBT(key);
3331 CLEAR_DBT(data);
3332 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3333 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3334 data.flags = DB_DBT_MALLOC;
3335 key.flags = DB_DBT_MALLOC;
3336 }
3337
3338 MYDB_BEGIN_ALLOW_THREADS;
3339 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3340 MYDB_END_ALLOW_THREADS;
3341 RETURN_IF_ERR();
3342
3343 recno = *((db_recno_t*)data.data);
3344 FREE_DBT(key);
3345 FREE_DBT(data);
3346 return PyInt_FromLong(recno);
3347}
3348
3349
3350static PyObject*
3351DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3352{
3353 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3354}
3355
3356
3357static PyObject*
3358DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3359{
3360 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3361}
3362
3363
3364static PyObject*
3365DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3366{
3367 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3368}
3369
3370
3371static PyObject*
3372DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3373{
3374 int err, flags = 0;
3375 PyObject* keyobj, *dataobj;
3376 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003377 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003378 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379 int dlen = -1;
3380 int doff = -1;
3381
3382 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3383 &keyobj, &dataobj, &flags, &dlen, &doff))
3384 return NULL;
3385
3386 CHECK_CURSOR_NOT_CLOSED(self);
3387
3388 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3389 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003390 if (!make_dbt(dataobj, &data) ||
3391 !add_partial_dbt(&data, dlen, doff) )
3392 {
3393 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003395 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003396
3397 MYDB_BEGIN_ALLOW_THREADS;
3398 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3399 MYDB_END_ALLOW_THREADS;
3400 FREE_DBT(key);
3401 RETURN_IF_ERR();
3402 self->mydb->haveStat = 0;
3403 RETURN_NONE();
3404}
3405
3406
3407static PyObject*
3408DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3409{
3410 int err, flags = 0;
3411 DBT key, data;
3412 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003413 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003414 int dlen = -1;
3415 int doff = -1;
3416
3417 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3418 &keyobj, &flags, &dlen, &doff))
3419 return NULL;
3420
3421 CHECK_CURSOR_NOT_CLOSED(self);
3422
3423 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3424 return NULL;
3425
3426 CLEAR_DBT(data);
3427 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3428 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3429 data.flags = DB_DBT_MALLOC;
3430 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003431 if (!add_partial_dbt(&data, dlen, doff)) {
3432 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003434 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003435
3436 MYDB_BEGIN_ALLOW_THREADS;
3437 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3438 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003439 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3440 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003441 Py_INCREF(Py_None);
3442 retval = Py_None;
3443 }
3444 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 retval = NULL;
3446 }
3447 else {
3448 switch (_DB_get_type(self->mydb)) {
3449 case -1:
3450 retval = NULL;
3451 break;
3452 case DB_BTREE:
3453 case DB_HASH:
3454 default:
3455 retval = Py_BuildValue("s#s#", key.data, key.size,
3456 data.data, data.size);
3457 break;
3458 case DB_RECNO:
3459 case DB_QUEUE:
3460 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3461 data.data, data.size);
3462 break;
3463 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003465 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003466 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003467 /* the only time REALLOC should be set is if we used an integer
3468 * key that make_key_dbt malloc'd for us. always free these. */
3469 if (key.flags & DB_DBT_REALLOC) {
3470 FREE_DBT(key);
3471 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003472
3473 return retval;
3474}
3475
3476
3477static PyObject*
3478DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3479{
3480 int err, flags = 0;
3481 DBT key, data;
3482 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003483 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003484 int dlen = -1;
3485 int doff = -1;
3486
3487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3488 &keyobj, &flags, &dlen, &doff))
3489 return NULL;
3490
3491 CHECK_CURSOR_NOT_CLOSED(self);
3492
3493 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3494 return NULL;
3495
3496 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003497 if (!add_partial_dbt(&data, dlen, doff)) {
3498 FREE_DBT(key);
3499 return NULL;
3500 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003501 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3502 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003503 data.flags |= DB_DBT_MALLOC;
3504 /* only BTREE databases will return anything in the key */
3505 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3506 key.flags |= DB_DBT_MALLOC;
3507 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003508 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003509 MYDB_BEGIN_ALLOW_THREADS;
3510 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3511 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003512 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3513 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003514 Py_INCREF(Py_None);
3515 retval = Py_None;
3516 }
3517 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003518 retval = NULL;
3519 }
3520 else {
3521 switch (_DB_get_type(self->mydb)) {
3522 case -1:
3523 retval = NULL;
3524 break;
3525 case DB_BTREE:
3526 case DB_HASH:
3527 default:
3528 retval = Py_BuildValue("s#s#", key.data, key.size,
3529 data.data, data.size);
3530 break;
3531 case DB_RECNO:
3532 case DB_QUEUE:
3533 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3534 data.data, data.size);
3535 break;
3536 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003537 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 FREE_DBT(data);
3539 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003540 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003541 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003542 if (key.flags & DB_DBT_REALLOC) {
3543 FREE_DBT(key);
3544 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545
3546 return retval;
3547}
3548
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003550_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3551 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003553 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003555 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556
Gregory P. Smith7441e652003-11-03 21:35:31 +00003557 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3559 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003560 if (!make_dbt(dataobj, &data)) {
3561 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003563 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003564
3565 MYDB_BEGIN_ALLOW_THREADS;
3566 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3567 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003568 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003569 Py_INCREF(Py_None);
3570 retval = Py_None;
3571 }
3572 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003573 retval = NULL;
3574 }
3575 else {
3576 switch (_DB_get_type(self->mydb)) {
3577 case -1:
3578 retval = NULL;
3579 break;
3580 case DB_BTREE:
3581 case DB_HASH:
3582 default:
3583 retval = Py_BuildValue("s#s#", key.data, key.size,
3584 data.data, data.size);
3585 break;
3586 case DB_RECNO:
3587 case DB_QUEUE:
3588 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3589 data.data, data.size);
3590 break;
3591 }
3592 }
3593
3594 FREE_DBT(key);
3595 return retval;
3596}
3597
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003598static PyObject*
3599DBC_get_both(DBCursorObject* self, PyObject* args)
3600{
3601 int flags=0;
3602 PyObject *keyobj, *dataobj;
3603
3604 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3605 return NULL;
3606
Gregory P. Smith7441e652003-11-03 21:35:31 +00003607 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003608 CHECK_CURSOR_NOT_CLOSED(self);
3609
3610 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3611 self->mydb->moduleFlags.getReturnsNone);
3612}
3613
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003614/* Return size of entry */
3615static PyObject*
3616DBC_get_current_size(DBCursorObject* self, PyObject* args)
3617{
3618 int err, flags=DB_CURRENT;
3619 PyObject* retval = NULL;
3620 DBT key, data;
3621
3622 if (!PyArg_ParseTuple(args, ":get_current_size"))
3623 return NULL;
3624 CHECK_CURSOR_NOT_CLOSED(self);
3625 CLEAR_DBT(key);
3626 CLEAR_DBT(data);
3627
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003628 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003629 getting the record size. */
3630 data.flags = DB_DBT_USERMEM;
3631 data.ulen = 0;
3632 MYDB_BEGIN_ALLOW_THREADS;
3633 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3634 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003635 if (err == DB_BUFFER_SMALL || !err) {
3636 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003637 retval = PyInt_FromLong((long)data.size);
3638 err = 0;
3639 }
3640
3641 FREE_DBT(key);
3642 FREE_DBT(data);
3643 RETURN_IF_ERR();
3644 return retval;
3645}
3646
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003647static PyObject*
3648DBC_set_both(DBCursorObject* self, PyObject* args)
3649{
3650 int flags=0;
3651 PyObject *keyobj, *dataobj;
3652
3653 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3654 return NULL;
3655
Gregory P. Smith7441e652003-11-03 21:35:31 +00003656 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003657 CHECK_CURSOR_NOT_CLOSED(self);
3658
3659 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3660 self->mydb->moduleFlags.cursorSetReturnsNone);
3661}
3662
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003663
3664static PyObject*
3665DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3666{
3667 int err, irecno, flags=0;
3668 db_recno_t recno;
3669 DBT key, data;
3670 PyObject* retval;
3671 int dlen = -1;
3672 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003673 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003674
3675 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3676 &irecno, &flags, &dlen, &doff))
3677 return NULL;
3678
3679 CHECK_CURSOR_NOT_CLOSED(self);
3680
3681 CLEAR_DBT(key);
3682 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003683 /* use allocated space so DB will be able to realloc room for the real
3684 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 key.data = malloc(sizeof(db_recno_t));
3686 if (key.data == NULL) {
3687 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3688 return NULL;
3689 }
3690 key.size = sizeof(db_recno_t);
3691 key.ulen = key.size;
3692 memcpy(key.data, &recno, sizeof(db_recno_t));
3693 key.flags = DB_DBT_REALLOC;
3694
3695 CLEAR_DBT(data);
3696 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3697 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3698 data.flags = DB_DBT_MALLOC;
3699 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003700 if (!add_partial_dbt(&data, dlen, doff)) {
3701 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003703 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704
3705 MYDB_BEGIN_ALLOW_THREADS;
3706 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3707 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003708 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3709 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003710 Py_INCREF(Py_None);
3711 retval = Py_None;
3712 }
3713 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003714 retval = NULL;
3715 }
3716 else { /* Can only be used for BTrees, so no need to return int key */
3717 retval = Py_BuildValue("s#s#", key.data, key.size,
3718 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 FREE_DBT(data);
3720 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003721 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003722
3723 return retval;
3724}
3725
3726
3727static PyObject*
3728DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3729{
3730 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3731}
3732
3733
3734static PyObject*
3735DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3736{
3737 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3738}
3739
3740
3741static PyObject*
3742DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3743{
3744 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3745}
3746
3747
3748static PyObject*
3749DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3750{
3751 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3752}
3753
3754
3755static PyObject*
3756DBC_join_item(DBCursorObject* self, PyObject* args)
3757{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003758 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003759 DBT key, data;
3760 PyObject* retval;
3761
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003762 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003763 return NULL;
3764
3765 CHECK_CURSOR_NOT_CLOSED(self);
3766
3767 CLEAR_DBT(key);
3768 CLEAR_DBT(data);
3769 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3770 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3771 key.flags = DB_DBT_MALLOC;
3772 }
3773
3774 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003775 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003776 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003777 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3778 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003779 Py_INCREF(Py_None);
3780 retval = Py_None;
3781 }
3782 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003783 retval = NULL;
3784 }
3785 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003786 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787 FREE_DBT(key);
3788 }
3789
3790 return retval;
3791}
3792
3793
3794
3795/* --------------------------------------------------------------------- */
3796/* DBEnv methods */
3797
3798
3799static PyObject*
3800DBEnv_close(DBEnvObject* self, PyObject* args)
3801{
3802 int err, flags = 0;
3803
3804 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3805 return NULL;
3806 if (!self->closed) { /* Don't close more than once */
3807 MYDB_BEGIN_ALLOW_THREADS;
3808 err = self->db_env->close(self->db_env, flags);
3809 MYDB_END_ALLOW_THREADS;
3810 /* after calling DBEnv->close, regardless of error, this DBEnv
3811 * may not be accessed again (BerkeleyDB docs). */
3812 self->closed = 1;
3813 self->db_env = NULL;
3814 RETURN_IF_ERR();
3815 }
3816 RETURN_NONE();
3817}
3818
3819
3820static PyObject*
3821DBEnv_open(DBEnvObject* self, PyObject* args)
3822{
3823 int err, flags=0, mode=0660;
3824 char *db_home;
3825
3826 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3827 return NULL;
3828
3829 CHECK_ENV_NOT_CLOSED(self);
3830
3831 MYDB_BEGIN_ALLOW_THREADS;
3832 err = self->db_env->open(self->db_env, db_home, flags, mode);
3833 MYDB_END_ALLOW_THREADS;
3834 RETURN_IF_ERR();
3835 self->closed = 0;
3836 self->flags = flags;
3837 RETURN_NONE();
3838}
3839
3840
3841static PyObject*
3842DBEnv_remove(DBEnvObject* self, PyObject* args)
3843{
3844 int err, flags=0;
3845 char *db_home;
3846
3847 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3848 return NULL;
3849 CHECK_ENV_NOT_CLOSED(self);
3850 MYDB_BEGIN_ALLOW_THREADS;
3851 err = self->db_env->remove(self->db_env, db_home, flags);
3852 MYDB_END_ALLOW_THREADS;
3853 RETURN_IF_ERR();
3854 RETURN_NONE();
3855}
3856
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003857#if (DBVER >= 41)
3858static PyObject*
3859DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3860{
3861 int err;
3862 u_int32_t flags=0;
3863 char *file = NULL;
3864 char *database = NULL;
3865 PyObject *txnobj = NULL;
3866 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003867 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003868 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003869
3870 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3871 &file, &database, &txnobj, &flags)) {
3872 return NULL;
3873 }
3874 if (!checkTxnObj(txnobj, &txn)) {
3875 return NULL;
3876 }
3877 CHECK_ENV_NOT_CLOSED(self);
3878 MYDB_BEGIN_ALLOW_THREADS;
3879 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3880 MYDB_END_ALLOW_THREADS;
3881 RETURN_IF_ERR();
3882 RETURN_NONE();
3883}
3884
3885static PyObject*
3886DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3887{
3888 int err;
3889 u_int32_t flags=0;
3890 char *file = NULL;
3891 char *database = NULL;
3892 char *newname = NULL;
3893 PyObject *txnobj = NULL;
3894 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003895 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003896 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003897
3898 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3899 &file, &database, &newname, &txnobj, &flags)) {
3900 return NULL;
3901 }
3902 if (!checkTxnObj(txnobj, &txn)) {
3903 return NULL;
3904 }
3905 CHECK_ENV_NOT_CLOSED(self);
3906 MYDB_BEGIN_ALLOW_THREADS;
3907 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3908 flags);
3909 MYDB_END_ALLOW_THREADS;
3910 RETURN_IF_ERR();
3911 RETURN_NONE();
3912}
3913
3914static PyObject*
3915DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3916{
3917 int err;
3918 u_int32_t flags=0;
3919 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003920 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003921
3922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3923 &passwd, &flags)) {
3924 return NULL;
3925 }
3926
3927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3929 MYDB_END_ALLOW_THREADS;
3930
3931 RETURN_IF_ERR();
3932 RETURN_NONE();
3933}
3934#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003935
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003936#if (DBVER >= 40)
3937static PyObject*
3938DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3939{
3940 int err;
3941 u_int32_t flags=0;
3942 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003943 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003944
3945 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3946 &timeout, &flags)) {
3947 return NULL;
3948 }
3949
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3952 MYDB_END_ALLOW_THREADS;
3953
3954 RETURN_IF_ERR();
3955 RETURN_NONE();
3956}
3957#endif /* DBVER >= 40 */
3958
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003959static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003960DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3961{
3962 int err;
3963 long shm_key = 0;
3964
3965 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3966 return NULL;
3967 CHECK_ENV_NOT_CLOSED(self);
3968
3969 err = self->db_env->set_shm_key(self->db_env, shm_key);
3970 RETURN_IF_ERR();
3971 RETURN_NONE();
3972}
3973
3974static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003975DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3976{
3977 int err, gbytes=0, bytes=0, ncache=0;
3978
3979 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3980 &gbytes, &bytes, &ncache))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3986 MYDB_END_ALLOW_THREADS;
3987 RETURN_IF_ERR();
3988 RETURN_NONE();
3989}
3990
3991
3992#if (DBVER >= 32)
3993static PyObject*
3994DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3995{
3996 int err, flags=0, onoff=0;
3997
3998 if (!PyArg_ParseTuple(args, "ii:set_flags",
3999 &flags, &onoff))
4000 return NULL;
4001 CHECK_ENV_NOT_CLOSED(self);
4002
4003 MYDB_BEGIN_ALLOW_THREADS;
4004 err = self->db_env->set_flags(self->db_env, flags, onoff);
4005 MYDB_END_ALLOW_THREADS;
4006 RETURN_IF_ERR();
4007 RETURN_NONE();
4008}
4009#endif
4010
4011
4012static PyObject*
4013DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4014{
4015 int err;
4016 char *dir;
4017
4018 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4019 return NULL;
4020 CHECK_ENV_NOT_CLOSED(self);
4021
4022 MYDB_BEGIN_ALLOW_THREADS;
4023 err = self->db_env->set_data_dir(self->db_env, dir);
4024 MYDB_END_ALLOW_THREADS;
4025 RETURN_IF_ERR();
4026 RETURN_NONE();
4027}
4028
4029
4030static PyObject*
4031DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4032{
4033 int err, lg_bsize;
4034
4035 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4036 return NULL;
4037 CHECK_ENV_NOT_CLOSED(self);
4038
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4041 MYDB_END_ALLOW_THREADS;
4042 RETURN_IF_ERR();
4043 RETURN_NONE();
4044}
4045
4046
4047static PyObject*
4048DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4049{
4050 int err;
4051 char *dir;
4052
4053 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4056
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_lg_dir(self->db_env, dir);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063
4064static PyObject*
4065DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4066{
4067 int err, lg_max;
4068
4069 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4070 return NULL;
4071 CHECK_ENV_NOT_CLOSED(self);
4072
4073 MYDB_BEGIN_ALLOW_THREADS;
4074 err = self->db_env->set_lg_max(self->db_env, lg_max);
4075 MYDB_END_ALLOW_THREADS;
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079
4080
Neal Norwitz84562352005-10-20 04:30:15 +00004081#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004082static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004083DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4084{
4085 int err, lg_max;
4086
4087 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
Neal Norwitz84562352005-10-20 04:30:15 +00004097#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004098
4099
4100static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004101DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4102{
4103 int err, lk_detect;
4104
4105 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4108
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4114}
4115
4116
4117static PyObject*
4118DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4119{
4120 int err, max;
4121
4122 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4123 return NULL;
4124 CHECK_ENV_NOT_CLOSED(self);
4125
4126 MYDB_BEGIN_ALLOW_THREADS;
4127 err = self->db_env->set_lk_max(self->db_env, max);
4128 MYDB_END_ALLOW_THREADS;
4129 RETURN_IF_ERR();
4130 RETURN_NONE();
4131}
4132
4133
4134#if (DBVER >= 32)
4135
4136static PyObject*
4137DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4138{
4139 int err, max;
4140
4141 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4144
4145 MYDB_BEGIN_ALLOW_THREADS;
4146 err = self->db_env->set_lk_max_locks(self->db_env, max);
4147 MYDB_END_ALLOW_THREADS;
4148 RETURN_IF_ERR();
4149 RETURN_NONE();
4150}
4151
4152
4153static PyObject*
4154DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4155{
4156 int err, max;
4157
4158 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4159 return NULL;
4160 CHECK_ENV_NOT_CLOSED(self);
4161
4162 MYDB_BEGIN_ALLOW_THREADS;
4163 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4164 MYDB_END_ALLOW_THREADS;
4165 RETURN_IF_ERR();
4166 RETURN_NONE();
4167}
4168
4169
4170static PyObject*
4171DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4172{
4173 int err, max;
4174
4175 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4176 return NULL;
4177 CHECK_ENV_NOT_CLOSED(self);
4178
4179 MYDB_BEGIN_ALLOW_THREADS;
4180 err = self->db_env->set_lk_max_objects(self->db_env, max);
4181 MYDB_END_ALLOW_THREADS;
4182 RETURN_IF_ERR();
4183 RETURN_NONE();
4184}
4185
4186#endif
4187
4188
4189static PyObject*
4190DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4191{
4192 int err, mp_mmapsize;
4193
4194 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4195 return NULL;
4196 CHECK_ENV_NOT_CLOSED(self);
4197
4198 MYDB_BEGIN_ALLOW_THREADS;
4199 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4200 MYDB_END_ALLOW_THREADS;
4201 RETURN_IF_ERR();
4202 RETURN_NONE();
4203}
4204
4205
4206static PyObject*
4207DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4208{
4209 int err;
4210 char *dir;
4211
4212 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4213 return NULL;
4214 CHECK_ENV_NOT_CLOSED(self);
4215
4216 MYDB_BEGIN_ALLOW_THREADS;
4217 err = self->db_env->set_tmp_dir(self->db_env, dir);
4218 MYDB_END_ALLOW_THREADS;
4219 RETURN_IF_ERR();
4220 RETURN_NONE();
4221}
4222
4223
4224static PyObject*
4225DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4226{
4227 int flags = 0;
4228 PyObject* txnobj = NULL;
4229 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004230 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004231
4232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4233 &txnobj, &flags))
4234 return NULL;
4235
4236 if (!checkTxnObj(txnobj, &txn))
4237 return NULL;
4238 CHECK_ENV_NOT_CLOSED(self);
4239
4240 return (PyObject*)newDBTxnObject(self, txn, flags);
4241}
4242
4243
4244static PyObject*
4245DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4246{
4247 int err, kbyte=0, min=0, flags=0;
4248
4249 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4250 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4252
4253 MYDB_BEGIN_ALLOW_THREADS;
4254#if (DBVER >= 40)
4255 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4256#else
4257 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4258#endif
4259 MYDB_END_ALLOW_THREADS;
4260 RETURN_IF_ERR();
4261 RETURN_NONE();
4262}
4263
4264
4265static PyObject*
4266DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4267{
4268 int err, max;
4269
4270 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4271 return NULL;
4272 CHECK_ENV_NOT_CLOSED(self);
4273
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004274 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004275 RETURN_IF_ERR();
4276 RETURN_NONE();
4277}
4278
4279
4280static PyObject*
4281DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4282{
4283 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004284 long stamp;
4285 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004286
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004287 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004288 return NULL;
4289 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004290 timestamp = (time_t)stamp;
4291 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004292 RETURN_IF_ERR();
4293 RETURN_NONE();
4294}
4295
4296
4297static PyObject*
4298DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4299{
4300 int err, atype, flags=0;
4301 int aborted = 0;
4302
4303 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4304 return NULL;
4305 CHECK_ENV_NOT_CLOSED(self);
4306
4307 MYDB_BEGIN_ALLOW_THREADS;
4308#if (DBVER >= 40)
4309 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4310#else
4311 err = lock_detect(self->db_env, flags, atype, &aborted);
4312#endif
4313 MYDB_END_ALLOW_THREADS;
4314 RETURN_IF_ERR();
4315 return PyInt_FromLong(aborted);
4316}
4317
4318
4319static PyObject*
4320DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4321{
4322 int flags=0;
4323 int locker, lock_mode;
4324 DBT obj;
4325 PyObject* objobj;
4326
4327 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4328 return NULL;
4329
4330
4331 if (!make_dbt(objobj, &obj))
4332 return NULL;
4333
4334 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4335}
4336
4337
4338static PyObject*
4339DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4340{
4341 int err;
4342 u_int32_t theID;
4343
4344 if (!PyArg_ParseTuple(args, ":lock_id"))
4345 return NULL;
4346
4347 CHECK_ENV_NOT_CLOSED(self);
4348 MYDB_BEGIN_ALLOW_THREADS;
4349#if (DBVER >= 40)
4350 err = self->db_env->lock_id(self->db_env, &theID);
4351#else
4352 err = lock_id(self->db_env, &theID);
4353#endif
4354 MYDB_END_ALLOW_THREADS;
4355 RETURN_IF_ERR();
4356
4357 return PyInt_FromLong((long)theID);
4358}
4359
4360
4361static PyObject*
4362DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4363{
4364 int err;
4365 DBLockObject* dblockobj;
4366
4367 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4368 return NULL;
4369
4370 CHECK_ENV_NOT_CLOSED(self);
4371 MYDB_BEGIN_ALLOW_THREADS;
4372#if (DBVER >= 40)
4373 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4374#else
4375 err = lock_put(self->db_env, &dblockobj->lock);
4376#endif
4377 MYDB_END_ALLOW_THREADS;
4378 RETURN_IF_ERR();
4379 RETURN_NONE();
4380}
4381
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004382#if (DBVER >= 44)
4383static PyObject*
4384DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4385{
4386 int err;
4387 char *file;
4388 u_int32_t flags = 0;
4389 static char* kwnames[] = { "file", "flags", NULL};
4390
4391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4392 &file, &flags))
4393 return NULL;
4394 CHECK_ENV_NOT_CLOSED(self);
4395
4396 MYDB_BEGIN_ALLOW_THREADS;
4397 err = self->db_env->lsn_reset(self->db_env, file, flags);
4398 MYDB_END_ALLOW_THREADS;
4399 RETURN_IF_ERR();
4400 RETURN_NONE();
4401}
4402#endif /* DBVER >= 4.4 */
4403
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004404#if (DBVER >= 40)
4405static PyObject*
4406DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4407{
4408 int err;
4409 DB_LOG_STAT* statp = NULL;
4410 PyObject* d = NULL;
4411 u_int32_t flags = 0;
4412
4413 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4414 return NULL;
4415 CHECK_ENV_NOT_CLOSED(self);
4416
4417 MYDB_BEGIN_ALLOW_THREADS;
4418 err = self->db_env->log_stat(self->db_env, &statp, flags);
4419 MYDB_END_ALLOW_THREADS;
4420 RETURN_IF_ERR();
4421
4422 /* Turn the stat structure into a dictionary */
4423 d = PyDict_New();
4424 if (d == NULL) {
4425 if (statp)
4426 free(statp);
4427 return NULL;
4428 }
4429
4430#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4431
4432 MAKE_ENTRY(magic);
4433 MAKE_ENTRY(version);
4434 MAKE_ENTRY(mode);
4435 MAKE_ENTRY(lg_bsize);
4436#if (DBVER >= 44)
4437 MAKE_ENTRY(lg_size);
4438 MAKE_ENTRY(record);
4439#endif
4440#if (DBVER <= 40)
4441 MAKE_ENTRY(lg_max);
4442#endif
4443 MAKE_ENTRY(w_mbytes);
4444 MAKE_ENTRY(w_bytes);
4445 MAKE_ENTRY(wc_mbytes);
4446 MAKE_ENTRY(wc_bytes);
4447 MAKE_ENTRY(wcount);
4448 MAKE_ENTRY(wcount_fill);
4449#if (DBVER >= 44)
4450 MAKE_ENTRY(rcount);
4451#endif
4452 MAKE_ENTRY(scount);
4453 MAKE_ENTRY(cur_file);
4454 MAKE_ENTRY(cur_offset);
4455 MAKE_ENTRY(disk_file);
4456 MAKE_ENTRY(disk_offset);
4457 MAKE_ENTRY(maxcommitperflush);
4458 MAKE_ENTRY(mincommitperflush);
4459 MAKE_ENTRY(regsize);
4460 MAKE_ENTRY(region_wait);
4461 MAKE_ENTRY(region_nowait);
4462
4463#undef MAKE_ENTRY
4464 free(statp);
4465 return d;
4466} /* DBEnv_log_stat */
4467#endif /* DBVER >= 4.0 for log_stat method */
4468
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004469
4470static PyObject*
4471DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4472{
4473 int err;
4474 DB_LOCK_STAT* sp;
4475 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004476 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004477
4478 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4479 return NULL;
4480 CHECK_ENV_NOT_CLOSED(self);
4481
4482 MYDB_BEGIN_ALLOW_THREADS;
4483#if (DBVER >= 40)
4484 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4485#else
4486#if (DBVER >= 33)
4487 err = lock_stat(self->db_env, &sp);
4488#else
4489 err = lock_stat(self->db_env, &sp, NULL);
4490#endif
4491#endif
4492 MYDB_END_ALLOW_THREADS;
4493 RETURN_IF_ERR();
4494
4495 /* Turn the stat structure into a dictionary */
4496 d = PyDict_New();
4497 if (d == NULL) {
4498 free(sp);
4499 return NULL;
4500 }
4501
4502#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4503
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004504#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004505 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004506#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004507 MAKE_ENTRY(nmodes);
4508#if (DBVER >= 32)
4509 MAKE_ENTRY(maxlocks);
4510 MAKE_ENTRY(maxlockers);
4511 MAKE_ENTRY(maxobjects);
4512 MAKE_ENTRY(nlocks);
4513 MAKE_ENTRY(maxnlocks);
4514#endif
4515 MAKE_ENTRY(nlockers);
4516 MAKE_ENTRY(maxnlockers);
4517#if (DBVER >= 32)
4518 MAKE_ENTRY(nobjects);
4519 MAKE_ENTRY(maxnobjects);
4520#endif
4521 MAKE_ENTRY(nrequests);
4522 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004523#if (DBVER < 44)
4524 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004525 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004526#else
4527 MAKE_ENTRY(lock_nowait);
4528 MAKE_ENTRY(lock_wait);
4529#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004530 MAKE_ENTRY(ndeadlocks);
4531 MAKE_ENTRY(regsize);
4532 MAKE_ENTRY(region_wait);
4533 MAKE_ENTRY(region_nowait);
4534
4535#undef MAKE_ENTRY
4536 free(sp);
4537 return d;
4538}
4539
4540
4541static PyObject*
4542DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4543{
4544 int flags=0;
4545 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004546 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547 PyObject* list;
4548 PyObject* item = NULL;
4549
4550 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4551 return NULL;
4552
4553 CHECK_ENV_NOT_CLOSED(self);
4554 MYDB_BEGIN_ALLOW_THREADS;
4555#if (DBVER >= 40)
4556 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4557#elif (DBVER == 33)
4558 err = log_archive(self->db_env, &log_list, flags);
4559#else
4560 err = log_archive(self->db_env, &log_list, flags, NULL);
4561#endif
4562 MYDB_END_ALLOW_THREADS;
4563 RETURN_IF_ERR();
4564
Gregory P. Smithbad47452006-06-05 00:33:35 +00004565 list = PyList_New(0);
4566 if (list == NULL) {
4567 if (log_list)
4568 free(log_list);
4569 return NULL;
4570 }
4571
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004572 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004573 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004574 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4575 item = PyString_FromString (*log_list);
4576 if (item == NULL) {
4577 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004578 list = NULL;
4579 break;
4580 }
4581 PyList_Append(list, item);
4582 Py_DECREF(item);
4583 }
4584 free(log_list_start);
4585 }
4586 return list;
4587}
4588
4589
4590static PyObject*
4591DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4592{
4593 int err;
4594 DB_TXN_STAT* sp;
4595 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004596 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004597
4598 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4599 return NULL;
4600 CHECK_ENV_NOT_CLOSED(self);
4601
4602 MYDB_BEGIN_ALLOW_THREADS;
4603#if (DBVER >= 40)
4604 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4605#elif (DBVER == 33)
4606 err = txn_stat(self->db_env, &sp);
4607#else
4608 err = txn_stat(self->db_env, &sp, NULL);
4609#endif
4610 MYDB_END_ALLOW_THREADS;
4611 RETURN_IF_ERR();
4612
4613 /* Turn the stat structure into a dictionary */
4614 d = PyDict_New();
4615 if (d == NULL) {
4616 free(sp);
4617 return NULL;
4618 }
4619
4620#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4621
4622 MAKE_ENTRY(time_ckp);
4623 MAKE_ENTRY(last_txnid);
4624 MAKE_ENTRY(maxtxns);
4625 MAKE_ENTRY(nactive);
4626 MAKE_ENTRY(maxnactive);
4627 MAKE_ENTRY(nbegins);
4628 MAKE_ENTRY(naborts);
4629 MAKE_ENTRY(ncommits);
4630 MAKE_ENTRY(regsize);
4631 MAKE_ENTRY(region_wait);
4632 MAKE_ENTRY(region_nowait);
4633
4634#undef MAKE_ENTRY
4635 free(sp);
4636 return d;
4637}
4638
4639
4640static PyObject*
4641DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4642{
4643 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004644 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004645
4646 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4647 return NULL;
4648 CHECK_ENV_NOT_CLOSED(self);
4649
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004650 if (self->moduleFlags.getReturnsNone)
4651 ++oldValue;
4652 if (self->moduleFlags.cursorSetReturnsNone)
4653 ++oldValue;
4654 self->moduleFlags.getReturnsNone = (flags >= 1);
4655 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004656 return PyInt_FromLong(oldValue);
4657}
4658
4659
4660/* --------------------------------------------------------------------- */
4661/* DBTxn methods */
4662
4663
4664static PyObject*
4665DBTxn_commit(DBTxnObject* self, PyObject* args)
4666{
4667 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004668 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004669
4670 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4671 return NULL;
4672
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004673 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004674 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4675 "after txn_commit or txn_abort");
4676 PyErr_SetObject(DBError, t);
4677 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004678 return NULL;
4679 }
4680 txn = self->txn;
4681 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682 MYDB_BEGIN_ALLOW_THREADS;
4683#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004685#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004686 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687#endif
4688 MYDB_END_ALLOW_THREADS;
4689 RETURN_IF_ERR();
4690 RETURN_NONE();
4691}
4692
4693static PyObject*
4694DBTxn_prepare(DBTxnObject* self, PyObject* args)
4695{
4696#if (DBVER >= 33)
4697 int err;
4698 char* gid=NULL;
4699 int gid_size=0;
4700
4701 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4702 return NULL;
4703
4704 if (gid_size != DB_XIDDATASIZE) {
4705 PyErr_SetString(PyExc_TypeError,
4706 "gid must be DB_XIDDATASIZE bytes long");
4707 return NULL;
4708 }
4709
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004710 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004711 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4712 "after txn_commit or txn_abort");
4713 PyErr_SetObject(DBError, t);
4714 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004715 return NULL;
4716 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004717 MYDB_BEGIN_ALLOW_THREADS;
4718#if (DBVER >= 40)
4719 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4720#else
4721 err = txn_prepare(self->txn, (u_int8_t*)gid);
4722#endif
4723 MYDB_END_ALLOW_THREADS;
4724 RETURN_IF_ERR();
4725 RETURN_NONE();
4726#else
4727 int err;
4728
4729 if (!PyArg_ParseTuple(args, ":prepare"))
4730 return NULL;
4731
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004732 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004733 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4734 "after txn_commit or txn_abort");
4735 PyErr_SetObject(DBError, t);
4736 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004737 return NULL;
4738 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004739 MYDB_BEGIN_ALLOW_THREADS;
4740 err = txn_prepare(self->txn);
4741 MYDB_END_ALLOW_THREADS;
4742 RETURN_IF_ERR();
4743 RETURN_NONE();
4744#endif
4745}
4746
4747
4748static PyObject*
4749DBTxn_abort(DBTxnObject* self, PyObject* args)
4750{
4751 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004752 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004753
4754 if (!PyArg_ParseTuple(args, ":abort"))
4755 return NULL;
4756
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004757 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004758 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4759 "after txn_commit or txn_abort");
4760 PyErr_SetObject(DBError, t);
4761 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004762 return NULL;
4763 }
4764 txn = self->txn;
4765 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766 MYDB_BEGIN_ALLOW_THREADS;
4767#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004770 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004771#endif
4772 MYDB_END_ALLOW_THREADS;
4773 RETURN_IF_ERR();
4774 RETURN_NONE();
4775}
4776
4777
4778static PyObject*
4779DBTxn_id(DBTxnObject* self, PyObject* args)
4780{
4781 int id;
4782
4783 if (!PyArg_ParseTuple(args, ":id"))
4784 return NULL;
4785
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004786 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004787 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4788 "after txn_commit or txn_abort");
4789 PyErr_SetObject(DBError, t);
4790 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004791 return NULL;
4792 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004793 MYDB_BEGIN_ALLOW_THREADS;
4794#if (DBVER >= 40)
4795 id = self->txn->id(self->txn);
4796#else
4797 id = txn_id(self->txn);
4798#endif
4799 MYDB_END_ALLOW_THREADS;
4800 return PyInt_FromLong(id);
4801}
4802
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004803#if (DBVER >= 43)
4804/* --------------------------------------------------------------------- */
4805/* DBSequence methods */
4806
4807
4808static PyObject*
4809DBSequence_close(DBSequenceObject* self, PyObject* args)
4810{
4811 int err, flags=0;
4812 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4813 return NULL;
4814 CHECK_SEQUENCE_NOT_CLOSED(self)
4815
4816 MYDB_BEGIN_ALLOW_THREADS
4817 err = self->sequence->close(self->sequence, flags);
4818 self->sequence = NULL;
4819 MYDB_END_ALLOW_THREADS
4820
4821 RETURN_IF_ERR();
4822
4823 RETURN_NONE();
4824}
4825
4826static PyObject*
4827DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4828{
4829 int err, flags = 0;
4830 int delta = 1;
4831 db_seq_t value;
4832 PyObject *txnobj = NULL;
4833 DB_TXN *txn = NULL;
4834 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4835 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4836 return NULL;
4837 CHECK_SEQUENCE_NOT_CLOSED(self)
4838
4839 if (!checkTxnObj(txnobj, &txn))
4840 return NULL;
4841
4842 MYDB_BEGIN_ALLOW_THREADS
4843 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4844 MYDB_END_ALLOW_THREADS
4845
4846 RETURN_IF_ERR();
4847 return PyLong_FromLongLong(value);
4848
4849}
4850
4851static PyObject*
4852DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4853{
4854 if (!PyArg_ParseTuple(args,":get_dbp"))
4855 return NULL;
4856 CHECK_SEQUENCE_NOT_CLOSED(self)
4857 Py_INCREF(self->mydb);
4858 return (PyObject* )self->mydb;
4859}
4860
4861static PyObject*
4862DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4863{
4864 int err;
4865 DBT key;
4866 CHECK_SEQUENCE_NOT_CLOSED(self)
4867 MYDB_BEGIN_ALLOW_THREADS
4868 err = self->sequence->get_key(self->sequence, &key);
4869 MYDB_END_ALLOW_THREADS
4870
4871 RETURN_IF_ERR();
4872
4873 return PyString_FromStringAndSize(key.data, key.size);
4874}
4875
4876static PyObject*
4877DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4878{
4879 int err;
4880 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004881 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004882 return NULL;
4883 CHECK_SEQUENCE_NOT_CLOSED(self)
4884
4885 MYDB_BEGIN_ALLOW_THREADS
4886 err = self->sequence->initial_value(self->sequence, value);
4887 MYDB_END_ALLOW_THREADS
4888
4889 RETURN_IF_ERR();
4890
4891 RETURN_NONE();
4892}
4893
4894static PyObject*
4895DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4896{
4897 int err, flags = 0;
4898 PyObject* keyobj;
4899 PyObject *txnobj = NULL;
4900 DB_TXN *txn = NULL;
4901 DBT key;
4902
4903 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004905 return NULL;
4906
4907 if (!checkTxnObj(txnobj, &txn))
4908 return NULL;
4909
4910 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4911 return NULL;
4912
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err = self->sequence->open(self->sequence, txn, &key, flags);
4915 MYDB_END_ALLOW_THREADS
4916
4917 CLEAR_DBT(key);
4918 RETURN_IF_ERR();
4919
4920 RETURN_NONE();
4921}
4922
4923static PyObject*
4924DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4925{
4926 int err, flags = 0;
4927 PyObject *txnobj = NULL;
4928 DB_TXN *txn = NULL;
4929
4930 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004931 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004932 return NULL;
4933
4934 if (!checkTxnObj(txnobj, &txn))
4935 return NULL;
4936
4937 CHECK_SEQUENCE_NOT_CLOSED(self)
4938
4939 MYDB_BEGIN_ALLOW_THREADS
4940 err = self->sequence->remove(self->sequence, txn, flags);
4941 MYDB_END_ALLOW_THREADS
4942
4943 RETURN_IF_ERR();
4944 RETURN_NONE();
4945}
4946
4947static PyObject*
4948DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4949{
4950 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004951 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004952 return NULL;
4953 CHECK_SEQUENCE_NOT_CLOSED(self)
4954
4955 MYDB_BEGIN_ALLOW_THREADS
4956 err = self->sequence->set_cachesize(self->sequence, size);
4957 MYDB_END_ALLOW_THREADS
4958
4959 RETURN_IF_ERR();
4960 RETURN_NONE();
4961}
4962
4963static PyObject*
4964DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4965{
4966 int err, size;
4967 if (!PyArg_ParseTuple(args,":get_cachesize"))
4968 return NULL;
4969 CHECK_SEQUENCE_NOT_CLOSED(self)
4970
4971 MYDB_BEGIN_ALLOW_THREADS
4972 err = self->sequence->get_cachesize(self->sequence, &size);
4973 MYDB_END_ALLOW_THREADS
4974
4975 RETURN_IF_ERR();
4976 return PyInt_FromLong(size);
4977}
4978
4979static PyObject*
4980DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4981{
4982 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004983 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004984 return NULL;
4985 CHECK_SEQUENCE_NOT_CLOSED(self)
4986
4987 MYDB_BEGIN_ALLOW_THREADS
4988 err = self->sequence->set_flags(self->sequence, flags);
4989 MYDB_END_ALLOW_THREADS
4990
4991 RETURN_IF_ERR();
4992 RETURN_NONE();
4993
4994}
4995
4996static PyObject*
4997DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4998{
4999 unsigned int flags;
5000 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005001 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005002 return NULL;
5003 CHECK_SEQUENCE_NOT_CLOSED(self)
5004
5005 MYDB_BEGIN_ALLOW_THREADS
5006 err = self->sequence->get_flags(self->sequence, &flags);
5007 MYDB_END_ALLOW_THREADS
5008
5009 RETURN_IF_ERR();
5010 return PyInt_FromLong((int)flags);
5011}
5012
5013static PyObject*
5014DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5015{
5016 int err;
5017 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005018 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005019 return NULL;
5020 CHECK_SEQUENCE_NOT_CLOSED(self)
5021
5022 MYDB_BEGIN_ALLOW_THREADS
5023 err = self->sequence->set_range(self->sequence, min, max);
5024 MYDB_END_ALLOW_THREADS
5025
5026 RETURN_IF_ERR();
5027 RETURN_NONE();
5028}
5029
5030static PyObject*
5031DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5032{
5033 int err;
5034 db_seq_t min, max;
5035 if (!PyArg_ParseTuple(args,":get_range"))
5036 return NULL;
5037 CHECK_SEQUENCE_NOT_CLOSED(self)
5038
5039 MYDB_BEGIN_ALLOW_THREADS
5040 err = self->sequence->get_range(self->sequence, &min, &max);
5041 MYDB_END_ALLOW_THREADS
5042
5043 RETURN_IF_ERR();
5044 return Py_BuildValue("(LL)", min, max);
5045}
5046
5047static PyObject*
5048DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5049{
5050 int err, flags = 0;
5051 DB_SEQUENCE_STAT* sp = NULL;
5052 PyObject* dict_stat;
5053 static char* kwnames[] = {"flags", NULL };
5054 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5055 return NULL;
5056 CHECK_SEQUENCE_NOT_CLOSED(self);
5057
5058 MYDB_BEGIN_ALLOW_THREADS;
5059 err = self->sequence->stat(self->sequence, &sp, flags);
5060 MYDB_END_ALLOW_THREADS;
5061 RETURN_IF_ERR();
5062
5063 if ((dict_stat = PyDict_New()) == NULL) {
5064 free(sp);
5065 return NULL;
5066 }
5067
5068
5069#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5070#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5071
5072 MAKE_INT_ENTRY(wait);
5073 MAKE_INT_ENTRY(nowait);
5074 MAKE_LONG_LONG_ENTRY(current);
5075 MAKE_LONG_LONG_ENTRY(value);
5076 MAKE_LONG_LONG_ENTRY(last_value);
5077 MAKE_LONG_LONG_ENTRY(min);
5078 MAKE_LONG_LONG_ENTRY(max);
5079 MAKE_INT_ENTRY(cache_size);
5080 MAKE_INT_ENTRY(flags);
5081
5082#undef MAKE_INT_ENTRY
5083#undef MAKE_LONG_LONG_ENTRY
5084
5085 free(sp);
5086 return dict_stat;
5087}
5088#endif
5089
5090
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005091/* --------------------------------------------------------------------- */
5092/* Method definition tables and type objects */
5093
5094static PyMethodDef DB_methods[] = {
5095 {"append", (PyCFunction)DB_append, METH_VARARGS},
5096#if (DBVER >= 33)
5097 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5098#endif
5099 {"close", (PyCFunction)DB_close, METH_VARARGS},
5100#if (DBVER >= 32)
5101 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5102 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5103#endif
5104 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5105 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5106 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5107 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005108#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005109 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005110#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005111 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5112 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5113 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5114 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5115 {"join", (PyCFunction)DB_join, METH_VARARGS},
5116 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5117 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5118 {"items", (PyCFunction)DB_items, METH_VARARGS},
5119 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5120 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5121 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5122 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5123 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5124 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005125#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005126 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005127#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005128 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005129#if (DBVER >= 41)
5130 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5131#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005132 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5133 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5134 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5135 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5136 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5137 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5138 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5139 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5140 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5141#if (DBVER >= 32)
5142 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5143#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005144 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005145 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5146#if (DBVER >= 33)
5147 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5148#endif
5149 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5150 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5151 {"values", (PyCFunction)DB_values, METH_VARARGS},
5152 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5153 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5154 {NULL, NULL} /* sentinel */
5155};
5156
5157
5158static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00005159 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005160 (binaryfunc)DB_subscript, /*mp_subscript*/
5161 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5162};
5163
5164
5165static PyMethodDef DBCursor_methods[] = {
5166 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5167 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5168 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5169 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5170 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5171 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5172 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005173#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005174 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005175#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005176 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5177 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5178 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5179 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5180 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5181 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5182 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5183 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005184 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005185 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005186 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5187 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5188 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5189 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5190 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5191 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5192 {NULL, NULL} /* sentinel */
5193};
5194
5195
5196static PyMethodDef DBEnv_methods[] = {
5197 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5198 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5199 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005200#if (DBVER >= 41)
5201 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5202 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5203 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5204#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005205#if (DBVER >= 40)
5206 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5207#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005208 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005209 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5210 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5211#if (DBVER >= 32)
5212 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5213#endif
5214 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5215 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5216 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005217#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005218 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005219#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005220 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5221 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5222#if (DBVER >= 32)
5223 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5224 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5225 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5226#endif
5227 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5228 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5229 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5230 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5231 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5232 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005233 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005234 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5235 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5236 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5237 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5238 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5239 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005240#if (DBVER >= 40)
5241 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5242#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005243#if (DBVER >= 44)
5244 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5245#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005246 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5247 {NULL, NULL} /* sentinel */
5248};
5249
5250
5251static PyMethodDef DBTxn_methods[] = {
5252 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5253 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5254 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5255 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5256 {NULL, NULL} /* sentinel */
5257};
5258
5259
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005260#if (DBVER >= 43)
5261static PyMethodDef DBSequence_methods[] = {
5262 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5263 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5264 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5265 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005266 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5267 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5268 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5269 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5270 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5271 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5272 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5273 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5274 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5275 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5276 {NULL, NULL} /* sentinel */
5277};
5278#endif
5279
5280
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005281static PyObject*
5282DB_getattr(DBObject* self, char *name)
5283{
5284 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5285}
5286
5287
5288static PyObject*
5289DBEnv_getattr(DBEnvObject* self, char *name)
5290{
5291 if (!strcmp(name, "db_home")) {
5292 CHECK_ENV_NOT_CLOSED(self);
5293 if (self->db_env->db_home == NULL) {
5294 RETURN_NONE();
5295 }
5296 return PyString_FromString(self->db_env->db_home);
5297 }
5298
5299 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5300}
5301
5302
5303static PyObject*
5304DBCursor_getattr(DBCursorObject* self, char *name)
5305{
5306 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5307}
5308
5309static PyObject*
5310DBTxn_getattr(DBTxnObject* self, char *name)
5311{
5312 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5313}
5314
5315static PyObject*
5316DBLock_getattr(DBLockObject* self, char *name)
5317{
5318 return NULL;
5319}
5320
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005321#if (DBVER >= 43)
5322static PyObject*
5323DBSequence_getattr(DBSequenceObject* self, char *name)
5324{
5325 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5326}
5327#endif
5328
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005329statichere PyTypeObject DB_Type = {
5330 PyObject_HEAD_INIT(NULL)
5331 0, /*ob_size*/
5332 "DB", /*tp_name*/
5333 sizeof(DBObject), /*tp_basicsize*/
5334 0, /*tp_itemsize*/
5335 /* methods */
5336 (destructor)DB_dealloc, /*tp_dealloc*/
5337 0, /*tp_print*/
5338 (getattrfunc)DB_getattr, /*tp_getattr*/
5339 0, /*tp_setattr*/
5340 0, /*tp_compare*/
5341 0, /*tp_repr*/
5342 0, /*tp_as_number*/
5343 0, /*tp_as_sequence*/
5344 &DB_mapping,/*tp_as_mapping*/
5345 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005346#ifdef HAVE_WEAKREF
5347 0, /* tp_call */
5348 0, /* tp_str */
5349 0, /* tp_getattro */
5350 0, /* tp_setattro */
5351 0, /* tp_as_buffer */
5352 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5353 0, /* tp_doc */
5354 0, /* tp_traverse */
5355 0, /* tp_clear */
5356 0, /* tp_richcompare */
5357 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5358#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005359};
5360
5361
5362statichere PyTypeObject DBCursor_Type = {
5363 PyObject_HEAD_INIT(NULL)
5364 0, /*ob_size*/
5365 "DBCursor", /*tp_name*/
5366 sizeof(DBCursorObject), /*tp_basicsize*/
5367 0, /*tp_itemsize*/
5368 /* methods */
5369 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5370 0, /*tp_print*/
5371 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5372 0, /*tp_setattr*/
5373 0, /*tp_compare*/
5374 0, /*tp_repr*/
5375 0, /*tp_as_number*/
5376 0, /*tp_as_sequence*/
5377 0, /*tp_as_mapping*/
5378 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005379#ifdef HAVE_WEAKREF
5380 0, /* tp_call */
5381 0, /* tp_str */
5382 0, /* tp_getattro */
5383 0, /* tp_setattro */
5384 0, /* tp_as_buffer */
5385 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5386 0, /* tp_doc */
5387 0, /* tp_traverse */
5388 0, /* tp_clear */
5389 0, /* tp_richcompare */
5390 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5391#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005392};
5393
5394
5395statichere PyTypeObject DBEnv_Type = {
5396 PyObject_HEAD_INIT(NULL)
5397 0, /*ob_size*/
5398 "DBEnv", /*tp_name*/
5399 sizeof(DBEnvObject), /*tp_basicsize*/
5400 0, /*tp_itemsize*/
5401 /* methods */
5402 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5403 0, /*tp_print*/
5404 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5405 0, /*tp_setattr*/
5406 0, /*tp_compare*/
5407 0, /*tp_repr*/
5408 0, /*tp_as_number*/
5409 0, /*tp_as_sequence*/
5410 0, /*tp_as_mapping*/
5411 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005412#ifdef HAVE_WEAKREF
5413 0, /* tp_call */
5414 0, /* tp_str */
5415 0, /* tp_getattro */
5416 0, /* tp_setattro */
5417 0, /* tp_as_buffer */
5418 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5419 0, /* tp_doc */
5420 0, /* tp_traverse */
5421 0, /* tp_clear */
5422 0, /* tp_richcompare */
5423 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5424#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005425};
5426
5427statichere PyTypeObject DBTxn_Type = {
5428 PyObject_HEAD_INIT(NULL)
5429 0, /*ob_size*/
5430 "DBTxn", /*tp_name*/
5431 sizeof(DBTxnObject), /*tp_basicsize*/
5432 0, /*tp_itemsize*/
5433 /* methods */
5434 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5435 0, /*tp_print*/
5436 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5437 0, /*tp_setattr*/
5438 0, /*tp_compare*/
5439 0, /*tp_repr*/
5440 0, /*tp_as_number*/
5441 0, /*tp_as_sequence*/
5442 0, /*tp_as_mapping*/
5443 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005444#ifdef HAVE_WEAKREF
5445 0, /* tp_call */
5446 0, /* tp_str */
5447 0, /* tp_getattro */
5448 0, /* tp_setattro */
5449 0, /* tp_as_buffer */
5450 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5451 0, /* tp_doc */
5452 0, /* tp_traverse */
5453 0, /* tp_clear */
5454 0, /* tp_richcompare */
5455 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5456#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005457};
5458
5459
5460statichere PyTypeObject DBLock_Type = {
5461 PyObject_HEAD_INIT(NULL)
5462 0, /*ob_size*/
5463 "DBLock", /*tp_name*/
5464 sizeof(DBLockObject), /*tp_basicsize*/
5465 0, /*tp_itemsize*/
5466 /* methods */
5467 (destructor)DBLock_dealloc, /*tp_dealloc*/
5468 0, /*tp_print*/
5469 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5470 0, /*tp_setattr*/
5471 0, /*tp_compare*/
5472 0, /*tp_repr*/
5473 0, /*tp_as_number*/
5474 0, /*tp_as_sequence*/
5475 0, /*tp_as_mapping*/
5476 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005477#ifdef HAVE_WEAKREF
5478 0, /* tp_call */
5479 0, /* tp_str */
5480 0, /* tp_getattro */
5481 0, /* tp_setattro */
5482 0, /* tp_as_buffer */
5483 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5484 0, /* tp_doc */
5485 0, /* tp_traverse */
5486 0, /* tp_clear */
5487 0, /* tp_richcompare */
5488 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5489#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005490};
5491
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005492#if (DBVER >= 43)
5493statichere PyTypeObject DBSequence_Type = {
5494 PyObject_HEAD_INIT(NULL)
5495 0, /*ob_size*/
5496 "DBSequence", /*tp_name*/
5497 sizeof(DBSequenceObject), /*tp_basicsize*/
5498 0, /*tp_itemsize*/
5499 /* methods */
5500 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5501 0, /*tp_print*/
5502 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5503 0, /*tp_setattr*/
5504 0, /*tp_compare*/
5505 0, /*tp_repr*/
5506 0, /*tp_as_number*/
5507 0, /*tp_as_sequence*/
5508 0, /*tp_as_mapping*/
5509 0, /*tp_hash*/
5510#ifdef HAVE_WEAKREF
5511 0, /* tp_call */
5512 0, /* tp_str */
5513 0, /* tp_getattro */
5514 0, /* tp_setattro */
5515 0, /* tp_as_buffer */
5516 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5517 0, /* tp_doc */
5518 0, /* tp_traverse */
5519 0, /* tp_clear */
5520 0, /* tp_richcompare */
5521 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5522#endif
5523};
5524#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005525
5526/* --------------------------------------------------------------------- */
5527/* Module-level functions */
5528
5529static PyObject*
5530DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5531{
5532 PyObject* dbenvobj = NULL;
5533 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005534 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005535
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005536 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5537 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005538 return NULL;
5539 if (dbenvobj == Py_None)
5540 dbenvobj = NULL;
5541 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5542 makeTypeError("DBEnv", dbenvobj);
5543 return NULL;
5544 }
5545
5546 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5547}
5548
5549
5550static PyObject*
5551DBEnv_construct(PyObject* self, PyObject* args)
5552{
5553 int flags = 0;
5554 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5555 return (PyObject* )newDBEnvObject(flags);
5556}
5557
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005558#if (DBVER >= 43)
5559static PyObject*
5560DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5561{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005562 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005563 int flags = 0;
5564 static char* kwnames[] = { "db", "flags", NULL};
5565
5566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5567 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005568 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005569 makeTypeError("DB", dbobj);
5570 return NULL;
5571 }
5572 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5573}
5574#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005575
5576static char bsddb_version_doc[] =
5577"Returns a tuple of major, minor, and patch release numbers of the\n\
5578underlying DB library.";
5579
5580static PyObject*
5581bsddb_version(PyObject* self, PyObject* args)
5582{
5583 int major, minor, patch;
5584
5585 if (!PyArg_ParseTuple(args, ":version"))
5586 return NULL;
5587 db_version(&major, &minor, &patch);
5588 return Py_BuildValue("(iii)", major, minor, patch);
5589}
5590
5591
5592/* List of functions defined in the module */
5593
5594static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005595 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5596 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5597#if (DBVER >= 43)
5598 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5599#endif
5600 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005601 {NULL, NULL} /* sentinel */
5602};
5603
5604
5605/* --------------------------------------------------------------------- */
5606/* Module initialization */
5607
5608
5609/* Convenience routine to export an integer value.
5610 * Errors are silently ignored, for better or for worse...
5611 */
5612#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5613
Gregory P. Smith41631e82003-09-21 00:08:14 +00005614#define MODULE_NAME_MAX_LEN 11
5615static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005616
5617DL_EXPORT(void) init_bsddb(void)
5618{
5619 PyObject* m;
5620 PyObject* d;
5621 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5622 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5623 PyObject* cvsid_s = PyString_FromString( rcs_id );
5624
5625 /* Initialize the type of the new type objects here; doing it here
5626 is required for portability to Windows without requiring C++. */
5627 DB_Type.ob_type = &PyType_Type;
5628 DBCursor_Type.ob_type = &PyType_Type;
5629 DBEnv_Type.ob_type = &PyType_Type;
5630 DBTxn_Type.ob_type = &PyType_Type;
5631 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005632#if (DBVER >= 43)
5633 DBSequence_Type.ob_type = &PyType_Type;
5634#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005635
5636
Mark Hammonda69d4092003-04-22 23:13:27 +00005637#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005639 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005640#endif
5641
5642 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005643 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005644 if (m == NULL)
5645 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005646
5647 /* Add some symbolic constants to the module */
5648 d = PyModule_GetDict(m);
5649 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5650 PyDict_SetItemString(d, "cvsid", cvsid_s);
5651 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5652 Py_DECREF(pybsddb_version_s);
5653 pybsddb_version_s = NULL;
5654 Py_DECREF(cvsid_s);
5655 cvsid_s = NULL;
5656 Py_DECREF(db_version_s);
5657 db_version_s = NULL;
5658
5659 ADD_INT(d, DB_VERSION_MAJOR);
5660 ADD_INT(d, DB_VERSION_MINOR);
5661 ADD_INT(d, DB_VERSION_PATCH);
5662
5663 ADD_INT(d, DB_MAX_PAGES);
5664 ADD_INT(d, DB_MAX_RECORDS);
5665
Gregory P. Smith41631e82003-09-21 00:08:14 +00005666#if (DBVER >= 42)
5667 ADD_INT(d, DB_RPCCLIENT);
5668#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005669 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005670 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5671 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5672#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005673 ADD_INT(d, DB_XA_CREATE);
5674
5675 ADD_INT(d, DB_CREATE);
5676 ADD_INT(d, DB_NOMMAP);
5677 ADD_INT(d, DB_THREAD);
5678
5679 ADD_INT(d, DB_FORCE);
5680 ADD_INT(d, DB_INIT_CDB);
5681 ADD_INT(d, DB_INIT_LOCK);
5682 ADD_INT(d, DB_INIT_LOG);
5683 ADD_INT(d, DB_INIT_MPOOL);
5684 ADD_INT(d, DB_INIT_TXN);
5685#if (DBVER >= 32)
5686 ADD_INT(d, DB_JOINENV);
5687#endif
5688
5689 ADD_INT(d, DB_RECOVER);
5690 ADD_INT(d, DB_RECOVER_FATAL);
5691 ADD_INT(d, DB_TXN_NOSYNC);
5692 ADD_INT(d, DB_USE_ENVIRON);
5693 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5694
5695 ADD_INT(d, DB_LOCKDOWN);
5696 ADD_INT(d, DB_PRIVATE);
5697 ADD_INT(d, DB_SYSTEM_MEM);
5698
5699 ADD_INT(d, DB_TXN_SYNC);
5700 ADD_INT(d, DB_TXN_NOWAIT);
5701
5702 ADD_INT(d, DB_EXCL);
5703 ADD_INT(d, DB_FCNTL_LOCKING);
5704 ADD_INT(d, DB_ODDFILESIZE);
5705 ADD_INT(d, DB_RDWRMASTER);
5706 ADD_INT(d, DB_RDONLY);
5707 ADD_INT(d, DB_TRUNCATE);
5708#if (DBVER >= 32)
5709 ADD_INT(d, DB_EXTENT);
5710 ADD_INT(d, DB_CDB_ALLDB);
5711 ADD_INT(d, DB_VERIFY);
5712#endif
5713 ADD_INT(d, DB_UPGRADE);
5714
5715 ADD_INT(d, DB_AGGRESSIVE);
5716 ADD_INT(d, DB_NOORDERCHK);
5717 ADD_INT(d, DB_ORDERCHKONLY);
5718 ADD_INT(d, DB_PR_PAGE);
5719#if ! (DBVER >= 33)
5720 ADD_INT(d, DB_VRFY_FLAGMASK);
5721 ADD_INT(d, DB_PR_HEADERS);
5722#endif
5723 ADD_INT(d, DB_PR_RECOVERYTEST);
5724 ADD_INT(d, DB_SALVAGE);
5725
5726 ADD_INT(d, DB_LOCK_NORUN);
5727 ADD_INT(d, DB_LOCK_DEFAULT);
5728 ADD_INT(d, DB_LOCK_OLDEST);
5729 ADD_INT(d, DB_LOCK_RANDOM);
5730 ADD_INT(d, DB_LOCK_YOUNGEST);
5731#if (DBVER >= 33)
5732 ADD_INT(d, DB_LOCK_MAXLOCKS);
5733 ADD_INT(d, DB_LOCK_MINLOCKS);
5734 ADD_INT(d, DB_LOCK_MINWRITE);
5735#endif
5736
5737
5738#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005739 /* docs say to use zero instead */
5740 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005741#else
5742 ADD_INT(d, DB_LOCK_CONFLICT);
5743#endif
5744
5745 ADD_INT(d, DB_LOCK_DUMP);
5746 ADD_INT(d, DB_LOCK_GET);
5747 ADD_INT(d, DB_LOCK_INHERIT);
5748 ADD_INT(d, DB_LOCK_PUT);
5749 ADD_INT(d, DB_LOCK_PUT_ALL);
5750 ADD_INT(d, DB_LOCK_PUT_OBJ);
5751
5752 ADD_INT(d, DB_LOCK_NG);
5753 ADD_INT(d, DB_LOCK_READ);
5754 ADD_INT(d, DB_LOCK_WRITE);
5755 ADD_INT(d, DB_LOCK_NOWAIT);
5756#if (DBVER >= 32)
5757 ADD_INT(d, DB_LOCK_WAIT);
5758#endif
5759 ADD_INT(d, DB_LOCK_IWRITE);
5760 ADD_INT(d, DB_LOCK_IREAD);
5761 ADD_INT(d, DB_LOCK_IWR);
5762#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005763#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005764 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005765#else
5766 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5767#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005768 ADD_INT(d, DB_LOCK_WWRITE);
5769#endif
5770
5771 ADD_INT(d, DB_LOCK_RECORD);
5772 ADD_INT(d, DB_LOCK_UPGRADE);
5773#if (DBVER >= 32)
5774 ADD_INT(d, DB_LOCK_SWITCH);
5775#endif
5776#if (DBVER >= 33)
5777 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5778#endif
5779
5780 ADD_INT(d, DB_LOCK_NOWAIT);
5781 ADD_INT(d, DB_LOCK_RECORD);
5782 ADD_INT(d, DB_LOCK_UPGRADE);
5783
5784#if (DBVER >= 33)
5785 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005786#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005788#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005789 ADD_INT(d, DB_LSTAT_FREE);
5790 ADD_INT(d, DB_LSTAT_HELD);
5791#if (DBVER == 33)
5792 ADD_INT(d, DB_LSTAT_NOGRANT);
5793#endif
5794 ADD_INT(d, DB_LSTAT_PENDING);
5795 ADD_INT(d, DB_LSTAT_WAITING);
5796#endif
5797
5798 ADD_INT(d, DB_ARCH_ABS);
5799 ADD_INT(d, DB_ARCH_DATA);
5800 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005801#if (DBVER >= 42)
5802 ADD_INT(d, DB_ARCH_REMOVE);
5803#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005804
5805 ADD_INT(d, DB_BTREE);
5806 ADD_INT(d, DB_HASH);
5807 ADD_INT(d, DB_RECNO);
5808 ADD_INT(d, DB_QUEUE);
5809 ADD_INT(d, DB_UNKNOWN);
5810
5811 ADD_INT(d, DB_DUP);
5812 ADD_INT(d, DB_DUPSORT);
5813 ADD_INT(d, DB_RECNUM);
5814 ADD_INT(d, DB_RENUMBER);
5815 ADD_INT(d, DB_REVSPLITOFF);
5816 ADD_INT(d, DB_SNAPSHOT);
5817
5818 ADD_INT(d, DB_JOIN_NOSORT);
5819
5820 ADD_INT(d, DB_AFTER);
5821 ADD_INT(d, DB_APPEND);
5822 ADD_INT(d, DB_BEFORE);
5823 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005824#if (DBVER >= 41)
5825 _addIntToDict(d, "DB_CHECKPOINT", 0);
5826#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005827 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005828 ADD_INT(d, DB_CURLSN);
5829#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005830#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005831 ADD_INT(d, DB_COMMIT);
5832#endif
5833 ADD_INT(d, DB_CONSUME);
5834#if (DBVER >= 32)
5835 ADD_INT(d, DB_CONSUME_WAIT);
5836#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005837 ADD_INT(d, DB_CURRENT);
5838#if (DBVER >= 33)
5839 ADD_INT(d, DB_FAST_STAT);
5840#endif
5841 ADD_INT(d, DB_FIRST);
5842 ADD_INT(d, DB_FLUSH);
5843 ADD_INT(d, DB_GET_BOTH);
5844 ADD_INT(d, DB_GET_RECNO);
5845 ADD_INT(d, DB_JOIN_ITEM);
5846 ADD_INT(d, DB_KEYFIRST);
5847 ADD_INT(d, DB_KEYLAST);
5848 ADD_INT(d, DB_LAST);
5849 ADD_INT(d, DB_NEXT);
5850 ADD_INT(d, DB_NEXT_DUP);
5851 ADD_INT(d, DB_NEXT_NODUP);
5852 ADD_INT(d, DB_NODUPDATA);
5853 ADD_INT(d, DB_NOOVERWRITE);
5854 ADD_INT(d, DB_NOSYNC);
5855 ADD_INT(d, DB_POSITION);
5856 ADD_INT(d, DB_PREV);
5857 ADD_INT(d, DB_PREV_NODUP);
5858 ADD_INT(d, DB_RECORDCOUNT);
5859 ADD_INT(d, DB_SET);
5860 ADD_INT(d, DB_SET_RANGE);
5861 ADD_INT(d, DB_SET_RECNO);
5862 ADD_INT(d, DB_WRITECURSOR);
5863
5864 ADD_INT(d, DB_OPFLAGS_MASK);
5865 ADD_INT(d, DB_RMW);
5866#if (DBVER >= 33)
5867 ADD_INT(d, DB_DIRTY_READ);
5868 ADD_INT(d, DB_MULTIPLE);
5869 ADD_INT(d, DB_MULTIPLE_KEY);
5870#endif
5871
Gregory P. Smith29602d22006-01-24 09:46:48 +00005872#if (DBVER >= 44)
5873 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5874 ADD_INT(d, DB_READ_COMMITTED);
5875#endif
5876
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877#if (DBVER >= 33)
5878 ADD_INT(d, DB_DONOTINDEX);
5879#endif
5880
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005881#if (DBVER >= 41)
5882 _addIntToDict(d, "DB_INCOMPLETE", 0);
5883#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005884 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005885#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005886 ADD_INT(d, DB_KEYEMPTY);
5887 ADD_INT(d, DB_KEYEXIST);
5888 ADD_INT(d, DB_LOCK_DEADLOCK);
5889 ADD_INT(d, DB_LOCK_NOTGRANTED);
5890 ADD_INT(d, DB_NOSERVER);
5891 ADD_INT(d, DB_NOSERVER_HOME);
5892 ADD_INT(d, DB_NOSERVER_ID);
5893 ADD_INT(d, DB_NOTFOUND);
5894 ADD_INT(d, DB_OLD_VERSION);
5895 ADD_INT(d, DB_RUNRECOVERY);
5896 ADD_INT(d, DB_VERIFY_BAD);
5897#if (DBVER >= 33)
5898 ADD_INT(d, DB_PAGE_NOTFOUND);
5899 ADD_INT(d, DB_SECONDARY_BAD);
5900#endif
5901#if (DBVER >= 40)
5902 ADD_INT(d, DB_STAT_CLEAR);
5903 ADD_INT(d, DB_REGION_INIT);
5904 ADD_INT(d, DB_NOLOCKING);
5905 ADD_INT(d, DB_YIELDCPU);
5906 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5907 ADD_INT(d, DB_NOPANIC);
5908#endif
5909
Gregory P. Smith41631e82003-09-21 00:08:14 +00005910#if (DBVER >= 42)
5911 ADD_INT(d, DB_TIME_NOTGRANTED);
5912 ADD_INT(d, DB_TXN_NOT_DURABLE);
5913 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5914 ADD_INT(d, DB_LOG_AUTOREMOVE);
5915 ADD_INT(d, DB_DIRECT_LOG);
5916 ADD_INT(d, DB_DIRECT_DB);
5917 ADD_INT(d, DB_INIT_REP);
5918 ADD_INT(d, DB_ENCRYPT);
5919 ADD_INT(d, DB_CHKSUM);
5920#endif
5921
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005922#if (DBVER >= 43)
5923 ADD_INT(d, DB_LOG_INMEMORY);
5924 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005925 ADD_INT(d, DB_SEQ_DEC);
5926 ADD_INT(d, DB_SEQ_INC);
5927 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005928#endif
5929
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005930#if (DBVER >= 41)
5931 ADD_INT(d, DB_ENCRYPT_AES);
5932 ADD_INT(d, DB_AUTO_COMMIT);
5933#else
5934 /* allow berkeleydb 4.1 aware apps to run on older versions */
5935 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5936#endif
5937
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005938 ADD_INT(d, EINVAL);
5939 ADD_INT(d, EACCES);
5940 ADD_INT(d, ENOSPC);
5941 ADD_INT(d, ENOMEM);
5942 ADD_INT(d, EAGAIN);
5943 ADD_INT(d, EBUSY);
5944 ADD_INT(d, EEXIST);
5945 ADD_INT(d, ENOENT);
5946 ADD_INT(d, EPERM);
5947
Barry Warsaw1baa9822003-03-31 19:51:29 +00005948#if (DBVER >= 40)
5949 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5950 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5951#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005952
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005953 /* The exception name must be correct for pickled exception *
5954 * objects to unpickle properly. */
5955#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5956#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5957#else
5958#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5959#endif
5960
5961 /* All the rest of the exceptions derive only from DBError */
5962#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5963 PyDict_SetItemString(d, #name, name)
5964
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005965 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005966 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5967 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005968
Gregory P. Smithe9477062005-06-04 06:46:59 +00005969 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5970 * from both DBError and KeyError, since the API only supports
5971 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005972 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005973 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5974 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005975 Py_file_input, d, d);
5976 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005977 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005978 PyDict_DelItemString(d, "KeyError");
5979
5980
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981#if !INCOMPLETE_IS_WARNING
5982 MAKE_EX(DBIncompleteError);
5983#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005984 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005985 MAKE_EX(DBKeyEmptyError);
5986 MAKE_EX(DBKeyExistError);
5987 MAKE_EX(DBLockDeadlockError);
5988 MAKE_EX(DBLockNotGrantedError);
5989 MAKE_EX(DBOldVersionError);
5990 MAKE_EX(DBRunRecoveryError);
5991 MAKE_EX(DBVerifyBadError);
5992 MAKE_EX(DBNoServerError);
5993 MAKE_EX(DBNoServerHomeError);
5994 MAKE_EX(DBNoServerIDError);
5995#if (DBVER >= 33)
5996 MAKE_EX(DBPageNotFoundError);
5997 MAKE_EX(DBSecondaryBadError);
5998#endif
5999
6000 MAKE_EX(DBInvalidArgError);
6001 MAKE_EX(DBAccessError);
6002 MAKE_EX(DBNoSpaceError);
6003 MAKE_EX(DBNoMemoryError);
6004 MAKE_EX(DBAgainError);
6005 MAKE_EX(DBBusyError);
6006 MAKE_EX(DBFileExistsError);
6007 MAKE_EX(DBNoSuchFileError);
6008 MAKE_EX(DBPermissionsError);
6009
6010#undef MAKE_EX
6011
6012 /* Check for errors */
6013 if (PyErr_Occurred()) {
6014 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006015 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006016 }
6017}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006018
6019/* allow this module to be named _pybsddb so that it can be installed
6020 * and imported on top of python >= 2.3 that includes its own older
6021 * copy of the library named _bsddb without importing the old version. */
6022DL_EXPORT(void) init_pybsddb(void)
6023{
6024 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6025 init_bsddb();
6026}