blob: 90de6aec4b1ca6e743d3f3d91b984b36d7726104 [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. Smith8a474042006-01-27 07:05:40 +0000101#define PY_BSDDB_VERSION "4.4.2"
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)
106#define Py_ssize_t int
107#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öwis18e16552006-02-15 17:27:45 +00002684Py_ssize_t DB_length(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002685{
2686 int err;
2687 long size = 0;
2688 int flags = 0;
2689 void* sp;
2690
2691 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002692 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError, t);
2694 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002695 return -1;
2696 }
2697
2698 if (self->haveStat) { /* Has the stat function been called recently? If
2699 so, we can use the cached value. */
2700 flags = DB_CACHED_COUNTS;
2701 }
2702
2703 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002704#if (DBVER >= 43)
2705 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2706#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002707 err = self->db->stat(self->db, &sp, flags);
2708#else
2709 err = self->db->stat(self->db, &sp, NULL, flags);
2710#endif
2711 MYDB_END_ALLOW_THREADS;
2712
2713 if (err)
2714 return -1;
2715
2716 self->haveStat = 1;
2717
2718 /* All the stat structures have matching fields upto the ndata field,
2719 so we can use any of them for the type cast */
2720 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2721 free(sp);
2722 return size;
2723}
2724
2725
2726PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2727{
2728 int err;
2729 PyObject* retval;
2730 DBT key;
2731 DBT data;
2732
2733 CHECK_DB_NOT_CLOSED(self);
2734 if (!make_key_dbt(self, keyobj, &key, NULL))
2735 return NULL;
2736
2737 CLEAR_DBT(data);
2738 if (CHECK_DBFLAG(self, DB_THREAD)) {
2739 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2740 data.flags = DB_DBT_MALLOC;
2741 }
2742 MYDB_BEGIN_ALLOW_THREADS;
2743 err = self->db->get(self->db, NULL, &key, &data, 0);
2744 MYDB_END_ALLOW_THREADS;
2745 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2746 PyErr_SetObject(PyExc_KeyError, keyobj);
2747 retval = NULL;
2748 }
2749 else if (makeDBError(err)) {
2750 retval = NULL;
2751 }
2752 else {
2753 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2754 FREE_DBT(data);
2755 }
2756
2757 FREE_DBT(key);
2758 return retval;
2759}
2760
2761
2762static int
2763DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2764{
2765 DBT key, data;
2766 int retval;
2767 int flags = 0;
2768
2769 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002770 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2771 PyErr_SetObject(DBError, t);
2772 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002773 return -1;
2774 }
2775
2776 if (!make_key_dbt(self, keyobj, &key, NULL))
2777 return -1;
2778
2779 if (dataobj != NULL) {
2780 if (!make_dbt(dataobj, &data))
2781 retval = -1;
2782 else {
2783 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002784 /* dictionaries shouldn't have duplicate keys */
2785 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 retval = _DB_put(self, NULL, &key, &data, flags);
2787
2788 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002789 /* try deleting any old record that matches and then PUT it
2790 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002791 _DB_delete(self, NULL, &key, 0);
2792 PyErr_Clear();
2793 retval = _DB_put(self, NULL, &key, &data, flags);
2794 }
2795 }
2796 }
2797 else {
2798 /* dataobj == NULL, so delete the key */
2799 retval = _DB_delete(self, NULL, &key, 0);
2800 }
2801 FREE_DBT(key);
2802 return retval;
2803}
2804
2805
2806static PyObject*
2807DB_has_key(DBObject* self, PyObject* args)
2808{
2809 int err;
2810 PyObject* keyobj;
2811 DBT key, data;
2812 PyObject* txnobj = NULL;
2813 DB_TXN *txn = NULL;
2814
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002815 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002816 return NULL;
2817 CHECK_DB_NOT_CLOSED(self);
2818 if (!make_key_dbt(self, keyobj, &key, NULL))
2819 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002820 if (!checkTxnObj(txnobj, &txn)) {
2821 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002822 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002823 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002825 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002826 it has a record but can't allocate a buffer for the data. This saves
2827 having to deal with data we won't be using.
2828 */
2829 CLEAR_DBT(data);
2830 data.flags = DB_DBT_USERMEM;
2831
2832 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002833 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002834 MYDB_END_ALLOW_THREADS;
2835 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002836
2837 if (err == DB_BUFFER_SMALL || err == 0) {
2838 return PyInt_FromLong(1);
2839 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2840 return PyInt_FromLong(0);
2841 }
2842
2843 makeDBError(err);
2844 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002845}
2846
2847
2848#define _KEYS_LIST 1
2849#define _VALUES_LIST 2
2850#define _ITEMS_LIST 3
2851
2852static PyObject*
2853_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2854{
2855 int err, dbtype;
2856 DBT key;
2857 DBT data;
2858 DBC *cursor;
2859 PyObject* list;
2860 PyObject* item = NULL;
2861
2862 CHECK_DB_NOT_CLOSED(self);
2863 CLEAR_DBT(key);
2864 CLEAR_DBT(data);
2865
2866 dbtype = _DB_get_type(self);
2867 if (dbtype == -1)
2868 return NULL;
2869
2870 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002871 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873
2874 /* get a cursor */
2875 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002876 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002877 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002878 if (makeDBError(err)) {
2879 Py_DECREF(list);
2880 return NULL;
2881 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002882
2883 if (CHECK_DBFLAG(self, DB_THREAD)) {
2884 key.flags = DB_DBT_REALLOC;
2885 data.flags = DB_DBT_REALLOC;
2886 }
2887
2888 while (1) { /* use the cursor to traverse the DB, collecting items */
2889 MYDB_BEGIN_ALLOW_THREADS;
2890 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2891 MYDB_END_ALLOW_THREADS;
2892
2893 if (err) {
2894 /* for any error, break out of the loop */
2895 break;
2896 }
2897
2898 switch (type) {
2899 case _KEYS_LIST:
2900 switch(dbtype) {
2901 case DB_BTREE:
2902 case DB_HASH:
2903 default:
2904 item = PyString_FromStringAndSize((char*)key.data, key.size);
2905 break;
2906 case DB_RECNO:
2907 case DB_QUEUE:
2908 item = PyInt_FromLong(*((db_recno_t*)key.data));
2909 break;
2910 }
2911 break;
2912
2913 case _VALUES_LIST:
2914 item = PyString_FromStringAndSize((char*)data.data, data.size);
2915 break;
2916
2917 case _ITEMS_LIST:
2918 switch(dbtype) {
2919 case DB_BTREE:
2920 case DB_HASH:
2921 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002922 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2923 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924 break;
2925 case DB_RECNO:
2926 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002927 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2928 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929 break;
2930 }
2931 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002932 default:
2933 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2934 item = NULL;
2935 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002936 }
2937 if (item == NULL) {
2938 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 list = NULL;
2940 goto done;
2941 }
2942 PyList_Append(list, item);
2943 Py_DECREF(item);
2944 }
2945
Gregory P. Smithe9477062005-06-04 06:46:59 +00002946 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2947 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 Py_DECREF(list);
2949 list = NULL;
2950 }
2951
2952 done:
2953 FREE_DBT(key);
2954 FREE_DBT(data);
2955 MYDB_BEGIN_ALLOW_THREADS;
2956 cursor->c_close(cursor);
2957 MYDB_END_ALLOW_THREADS;
2958 return list;
2959}
2960
2961
2962static PyObject*
2963DB_keys(DBObject* self, PyObject* args)
2964{
2965 PyObject* txnobj = NULL;
2966 DB_TXN *txn = NULL;
2967
Georg Brandl96a8c392006-05-29 21:04:52 +00002968 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002969 return NULL;
2970 if (!checkTxnObj(txnobj, &txn))
2971 return NULL;
2972 return _DB_make_list(self, txn, _KEYS_LIST);
2973}
2974
2975
2976static PyObject*
2977DB_items(DBObject* self, PyObject* args)
2978{
2979 PyObject* txnobj = NULL;
2980 DB_TXN *txn = NULL;
2981
Georg Brandl96a8c392006-05-29 21:04:52 +00002982 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002983 return NULL;
2984 if (!checkTxnObj(txnobj, &txn))
2985 return NULL;
2986 return _DB_make_list(self, txn, _ITEMS_LIST);
2987}
2988
2989
2990static PyObject*
2991DB_values(DBObject* self, PyObject* args)
2992{
2993 PyObject* txnobj = NULL;
2994 DB_TXN *txn = NULL;
2995
Georg Brandl96a8c392006-05-29 21:04:52 +00002996 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002997 return NULL;
2998 if (!checkTxnObj(txnobj, &txn))
2999 return NULL;
3000 return _DB_make_list(self, txn, _VALUES_LIST);
3001}
3002
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003003/* --------------------------------------------------------------------- */
3004/* DBCursor methods */
3005
3006
3007static PyObject*
3008DBC_close(DBCursorObject* self, PyObject* args)
3009{
3010 int err = 0;
3011
3012 if (!PyArg_ParseTuple(args, ":close"))
3013 return NULL;
3014
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 if (self->dbc != NULL) {
3016 MYDB_BEGIN_ALLOW_THREADS;
3017 err = self->dbc->c_close(self->dbc);
3018 self->dbc = NULL;
3019 MYDB_END_ALLOW_THREADS;
3020 }
3021 RETURN_IF_ERR();
3022 RETURN_NONE();
3023}
3024
3025
3026static PyObject*
3027DBC_count(DBCursorObject* self, PyObject* args)
3028{
3029 int err = 0;
3030 db_recno_t count;
3031 int flags = 0;
3032
3033 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3034 return NULL;
3035
3036 CHECK_CURSOR_NOT_CLOSED(self);
3037
3038 MYDB_BEGIN_ALLOW_THREADS;
3039 err = self->dbc->c_count(self->dbc, &count, flags);
3040 MYDB_END_ALLOW_THREADS;
3041 RETURN_IF_ERR();
3042
3043 return PyInt_FromLong(count);
3044}
3045
3046
3047static PyObject*
3048DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3049{
3050 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3051}
3052
3053
3054static PyObject*
3055DBC_delete(DBCursorObject* self, PyObject* args)
3056{
3057 int err, flags=0;
3058
3059 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3060 return NULL;
3061
3062 CHECK_CURSOR_NOT_CLOSED(self);
3063
3064 MYDB_BEGIN_ALLOW_THREADS;
3065 err = self->dbc->c_del(self->dbc, flags);
3066 MYDB_END_ALLOW_THREADS;
3067 RETURN_IF_ERR();
3068
3069 self->mydb->haveStat = 0;
3070 RETURN_NONE();
3071}
3072
3073
3074static PyObject*
3075DBC_dup(DBCursorObject* self, PyObject* args)
3076{
3077 int err, flags =0;
3078 DBC* dbc = NULL;
3079
3080 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3081 return NULL;
3082
3083 CHECK_CURSOR_NOT_CLOSED(self);
3084
3085 MYDB_BEGIN_ALLOW_THREADS;
3086 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3087 MYDB_END_ALLOW_THREADS;
3088 RETURN_IF_ERR();
3089
3090 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3091}
3092
3093static PyObject*
3094DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3095{
3096 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3097}
3098
3099
3100static PyObject*
3101DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3102{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003103 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003104 PyObject* keyobj = NULL;
3105 PyObject* dataobj = NULL;
3106 PyObject* retval = NULL;
3107 int dlen = -1;
3108 int doff = -1;
3109 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003110 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003111 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003112
3113 CLEAR_DBT(key);
3114 CLEAR_DBT(data);
3115 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003116 &flags, &dlen, &doff))
3117 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003119 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3120 &kwnames[1],
3121 &keyobj, &flags, &dlen, &doff))
3122 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003123 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3125 kwnames, &keyobj, &dataobj,
3126 &flags, &dlen, &doff))
3127 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 return NULL;
3129 }
3130 }
3131 }
3132
3133 CHECK_CURSOR_NOT_CLOSED(self);
3134
3135 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3136 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003137 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3138 (!add_partial_dbt(&data, dlen, doff)) )
3139 {
3140 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003142 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003143
3144 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3145 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003146 if (!(key.flags & DB_DBT_REALLOC)) {
3147 key.flags |= DB_DBT_MALLOC;
3148 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149 }
3150
3151 MYDB_BEGIN_ALLOW_THREADS;
3152 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3153 MYDB_END_ALLOW_THREADS;
3154
Gregory P. Smithe9477062005-06-04 06:46:59 +00003155 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3156 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003157 Py_INCREF(Py_None);
3158 retval = Py_None;
3159 }
3160 else if (makeDBError(err)) {
3161 retval = NULL;
3162 }
3163 else {
3164 switch (_DB_get_type(self->mydb)) {
3165 case -1:
3166 retval = NULL;
3167 break;
3168 case DB_BTREE:
3169 case DB_HASH:
3170 default:
3171 retval = Py_BuildValue("s#s#", key.data, key.size,
3172 data.data, data.size);
3173 break;
3174 case DB_RECNO:
3175 case DB_QUEUE:
3176 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3177 data.data, data.size);
3178 break;
3179 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003180 FREE_DBT(data);
3181 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003182 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003183 return retval;
3184}
3185
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003186#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003187static PyObject*
3188DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3189{
3190 int err, flags=0;
3191 PyObject* keyobj = NULL;
3192 PyObject* dataobj = NULL;
3193 PyObject* retval = NULL;
3194 int dlen = -1;
3195 int doff = -1;
3196 DBT key, pkey, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003197 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003198 NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199
3200 CLEAR_DBT(key);
3201 CLEAR_DBT(data);
3202 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3203 &flags, &dlen, &doff))
3204 {
3205 PyErr_Clear();
3206 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3207 &kwnames[1],
3208 &keyobj, &flags, &dlen, &doff))
3209 {
3210 PyErr_Clear();
3211 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3212 kwnames, &keyobj, &dataobj,
3213 &flags, &dlen, &doff))
3214 {
3215 return NULL;
3216 }
3217 }
3218 }
3219
3220 CHECK_CURSOR_NOT_CLOSED(self);
3221
3222 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3223 return NULL;
3224 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3225 (!add_partial_dbt(&data, dlen, doff)) ) {
3226 FREE_DBT(key);
3227 return NULL;
3228 }
3229
3230 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3231 data.flags = DB_DBT_MALLOC;
3232 if (!(key.flags & DB_DBT_REALLOC)) {
3233 key.flags |= DB_DBT_MALLOC;
3234 }
3235 }
3236
3237 CLEAR_DBT(pkey);
3238 pkey.flags = DB_DBT_MALLOC;
3239
3240 MYDB_BEGIN_ALLOW_THREADS;
3241 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3242 MYDB_END_ALLOW_THREADS;
3243
Gregory P. Smithe9477062005-06-04 06:46:59 +00003244 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3245 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003246 Py_INCREF(Py_None);
3247 retval = Py_None;
3248 }
3249 else if (makeDBError(err)) {
3250 retval = NULL;
3251 }
3252 else {
3253 PyObject *pkeyObj;
3254 PyObject *dataObj;
3255 dataObj = PyString_FromStringAndSize(data.data, data.size);
3256
3257 if (self->mydb->primaryDBType == DB_RECNO ||
3258 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003259 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003260 else
3261 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3262
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003263 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003264 {
3265 PyObject *keyObj;
3266 int type = _DB_get_type(self->mydb);
3267 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003268 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003269 else
3270 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003271#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003272 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003273#else
3274 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3275#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003276 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003277 FREE_DBT(key);
3278 }
3279 else /* return just the pkey and data */
3280 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003281#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003282 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003283#else
3284 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3285#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003286 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003287 Py_DECREF(dataObj);
3288 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003289 FREE_DBT(pkey);
3290 FREE_DBT(data);
3291 }
3292 /* the only time REALLOC should be set is if we used an integer
3293 * key that make_key_dbt malloc'd for us. always free these. */
3294 if (key.flags & DB_DBT_REALLOC) {
3295 FREE_DBT(key);
3296 }
3297 return retval;
3298}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003299#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003301
3302static PyObject*
3303DBC_get_recno(DBCursorObject* self, PyObject* args)
3304{
3305 int err;
3306 db_recno_t recno;
3307 DBT key;
3308 DBT data;
3309
3310 if (!PyArg_ParseTuple(args, ":get_recno"))
3311 return NULL;
3312
3313 CHECK_CURSOR_NOT_CLOSED(self);
3314
3315 CLEAR_DBT(key);
3316 CLEAR_DBT(data);
3317 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3318 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3319 data.flags = DB_DBT_MALLOC;
3320 key.flags = DB_DBT_MALLOC;
3321 }
3322
3323 MYDB_BEGIN_ALLOW_THREADS;
3324 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3325 MYDB_END_ALLOW_THREADS;
3326 RETURN_IF_ERR();
3327
3328 recno = *((db_recno_t*)data.data);
3329 FREE_DBT(key);
3330 FREE_DBT(data);
3331 return PyInt_FromLong(recno);
3332}
3333
3334
3335static PyObject*
3336DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3337{
3338 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3339}
3340
3341
3342static PyObject*
3343DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3344{
3345 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3346}
3347
3348
3349static PyObject*
3350DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3351{
3352 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3353}
3354
3355
3356static PyObject*
3357DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3358{
3359 int err, flags = 0;
3360 PyObject* keyobj, *dataobj;
3361 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003362 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003363 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003364 int dlen = -1;
3365 int doff = -1;
3366
3367 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3368 &keyobj, &dataobj, &flags, &dlen, &doff))
3369 return NULL;
3370
3371 CHECK_CURSOR_NOT_CLOSED(self);
3372
3373 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3374 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003375 if (!make_dbt(dataobj, &data) ||
3376 !add_partial_dbt(&data, dlen, doff) )
3377 {
3378 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003379 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003381
3382 MYDB_BEGIN_ALLOW_THREADS;
3383 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3384 MYDB_END_ALLOW_THREADS;
3385 FREE_DBT(key);
3386 RETURN_IF_ERR();
3387 self->mydb->haveStat = 0;
3388 RETURN_NONE();
3389}
3390
3391
3392static PyObject*
3393DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3394{
3395 int err, flags = 0;
3396 DBT key, data;
3397 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003398 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003399 int dlen = -1;
3400 int doff = -1;
3401
3402 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3403 &keyobj, &flags, &dlen, &doff))
3404 return NULL;
3405
3406 CHECK_CURSOR_NOT_CLOSED(self);
3407
3408 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3409 return NULL;
3410
3411 CLEAR_DBT(data);
3412 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3413 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3414 data.flags = DB_DBT_MALLOC;
3415 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003416 if (!add_partial_dbt(&data, dlen, doff)) {
3417 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003418 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003419 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003420
3421 MYDB_BEGIN_ALLOW_THREADS;
3422 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3423 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003424 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3425 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003426 Py_INCREF(Py_None);
3427 retval = Py_None;
3428 }
3429 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003430 retval = NULL;
3431 }
3432 else {
3433 switch (_DB_get_type(self->mydb)) {
3434 case -1:
3435 retval = NULL;
3436 break;
3437 case DB_BTREE:
3438 case DB_HASH:
3439 default:
3440 retval = Py_BuildValue("s#s#", key.data, key.size,
3441 data.data, data.size);
3442 break;
3443 case DB_RECNO:
3444 case DB_QUEUE:
3445 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3446 data.data, data.size);
3447 break;
3448 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003450 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003452 /* the only time REALLOC should be set is if we used an integer
3453 * key that make_key_dbt malloc'd for us. always free these. */
3454 if (key.flags & DB_DBT_REALLOC) {
3455 FREE_DBT(key);
3456 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003457
3458 return retval;
3459}
3460
3461
3462static PyObject*
3463DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3464{
3465 int err, flags = 0;
3466 DBT key, data;
3467 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003468 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469 int dlen = -1;
3470 int doff = -1;
3471
3472 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3473 &keyobj, &flags, &dlen, &doff))
3474 return NULL;
3475
3476 CHECK_CURSOR_NOT_CLOSED(self);
3477
3478 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3479 return NULL;
3480
3481 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003482 if (!add_partial_dbt(&data, dlen, doff)) {
3483 FREE_DBT(key);
3484 return NULL;
3485 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003486 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3487 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003488 data.flags |= DB_DBT_MALLOC;
3489 /* only BTREE databases will return anything in the key */
3490 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3491 key.flags |= DB_DBT_MALLOC;
3492 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003493 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494 MYDB_BEGIN_ALLOW_THREADS;
3495 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3496 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003497 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3498 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003499 Py_INCREF(Py_None);
3500 retval = Py_None;
3501 }
3502 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003503 retval = NULL;
3504 }
3505 else {
3506 switch (_DB_get_type(self->mydb)) {
3507 case -1:
3508 retval = NULL;
3509 break;
3510 case DB_BTREE:
3511 case DB_HASH:
3512 default:
3513 retval = Py_BuildValue("s#s#", key.data, key.size,
3514 data.data, data.size);
3515 break;
3516 case DB_RECNO:
3517 case DB_QUEUE:
3518 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3519 data.data, data.size);
3520 break;
3521 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003522 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003523 FREE_DBT(data);
3524 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003525 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003526 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 if (key.flags & DB_DBT_REALLOC) {
3528 FREE_DBT(key);
3529 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003530
3531 return retval;
3532}
3533
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003534static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003535_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3536 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003537{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003538 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003539 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003540 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003541
Gregory P. Smith7441e652003-11-03 21:35:31 +00003542 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3544 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003545 if (!make_dbt(dataobj, &data)) {
3546 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003548 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549
3550 MYDB_BEGIN_ALLOW_THREADS;
3551 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3552 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003553 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003554 Py_INCREF(Py_None);
3555 retval = Py_None;
3556 }
3557 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003558 retval = NULL;
3559 }
3560 else {
3561 switch (_DB_get_type(self->mydb)) {
3562 case -1:
3563 retval = NULL;
3564 break;
3565 case DB_BTREE:
3566 case DB_HASH:
3567 default:
3568 retval = Py_BuildValue("s#s#", key.data, key.size,
3569 data.data, data.size);
3570 break;
3571 case DB_RECNO:
3572 case DB_QUEUE:
3573 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3574 data.data, data.size);
3575 break;
3576 }
3577 }
3578
3579 FREE_DBT(key);
3580 return retval;
3581}
3582
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003583static PyObject*
3584DBC_get_both(DBCursorObject* self, PyObject* args)
3585{
3586 int flags=0;
3587 PyObject *keyobj, *dataobj;
3588
3589 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3590 return NULL;
3591
Gregory P. Smith7441e652003-11-03 21:35:31 +00003592 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003593 CHECK_CURSOR_NOT_CLOSED(self);
3594
3595 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3596 self->mydb->moduleFlags.getReturnsNone);
3597}
3598
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003599/* Return size of entry */
3600static PyObject*
3601DBC_get_current_size(DBCursorObject* self, PyObject* args)
3602{
3603 int err, flags=DB_CURRENT;
3604 PyObject* retval = NULL;
3605 DBT key, data;
3606
3607 if (!PyArg_ParseTuple(args, ":get_current_size"))
3608 return NULL;
3609 CHECK_CURSOR_NOT_CLOSED(self);
3610 CLEAR_DBT(key);
3611 CLEAR_DBT(data);
3612
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003613 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003614 getting the record size. */
3615 data.flags = DB_DBT_USERMEM;
3616 data.ulen = 0;
3617 MYDB_BEGIN_ALLOW_THREADS;
3618 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3619 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003620 if (err == DB_BUFFER_SMALL || !err) {
3621 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003622 retval = PyInt_FromLong((long)data.size);
3623 err = 0;
3624 }
3625
3626 FREE_DBT(key);
3627 FREE_DBT(data);
3628 RETURN_IF_ERR();
3629 return retval;
3630}
3631
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003632static PyObject*
3633DBC_set_both(DBCursorObject* self, PyObject* args)
3634{
3635 int flags=0;
3636 PyObject *keyobj, *dataobj;
3637
3638 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3639 return NULL;
3640
Gregory P. Smith7441e652003-11-03 21:35:31 +00003641 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 CHECK_CURSOR_NOT_CLOSED(self);
3643
3644 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3645 self->mydb->moduleFlags.cursorSetReturnsNone);
3646}
3647
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003648
3649static PyObject*
3650DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3651{
3652 int err, irecno, flags=0;
3653 db_recno_t recno;
3654 DBT key, data;
3655 PyObject* retval;
3656 int dlen = -1;
3657 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003658 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003659
3660 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3661 &irecno, &flags, &dlen, &doff))
3662 return NULL;
3663
3664 CHECK_CURSOR_NOT_CLOSED(self);
3665
3666 CLEAR_DBT(key);
3667 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003668 /* use allocated space so DB will be able to realloc room for the real
3669 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670 key.data = malloc(sizeof(db_recno_t));
3671 if (key.data == NULL) {
3672 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3673 return NULL;
3674 }
3675 key.size = sizeof(db_recno_t);
3676 key.ulen = key.size;
3677 memcpy(key.data, &recno, sizeof(db_recno_t));
3678 key.flags = DB_DBT_REALLOC;
3679
3680 CLEAR_DBT(data);
3681 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3682 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3683 data.flags = DB_DBT_MALLOC;
3684 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003685 if (!add_partial_dbt(&data, dlen, doff)) {
3686 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003687 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003688 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003689
3690 MYDB_BEGIN_ALLOW_THREADS;
3691 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3692 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003693 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3694 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003695 Py_INCREF(Py_None);
3696 retval = Py_None;
3697 }
3698 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699 retval = NULL;
3700 }
3701 else { /* Can only be used for BTrees, so no need to return int key */
3702 retval = Py_BuildValue("s#s#", key.data, key.size,
3703 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704 FREE_DBT(data);
3705 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003706 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003707
3708 return retval;
3709}
3710
3711
3712static PyObject*
3713DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3714{
3715 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3716}
3717
3718
3719static PyObject*
3720DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3721{
3722 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3723}
3724
3725
3726static PyObject*
3727DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3728{
3729 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3730}
3731
3732
3733static PyObject*
3734DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3735{
3736 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3737}
3738
3739
3740static PyObject*
3741DBC_join_item(DBCursorObject* self, PyObject* args)
3742{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003743 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003744 DBT key, data;
3745 PyObject* retval;
3746
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003747 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003748 return NULL;
3749
3750 CHECK_CURSOR_NOT_CLOSED(self);
3751
3752 CLEAR_DBT(key);
3753 CLEAR_DBT(data);
3754 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3755 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3756 key.flags = DB_DBT_MALLOC;
3757 }
3758
3759 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003760 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003761 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003762 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3763 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003764 Py_INCREF(Py_None);
3765 retval = Py_None;
3766 }
3767 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003768 retval = NULL;
3769 }
3770 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003771 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003772 FREE_DBT(key);
3773 }
3774
3775 return retval;
3776}
3777
3778
3779
3780/* --------------------------------------------------------------------- */
3781/* DBEnv methods */
3782
3783
3784static PyObject*
3785DBEnv_close(DBEnvObject* self, PyObject* args)
3786{
3787 int err, flags = 0;
3788
3789 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3790 return NULL;
3791 if (!self->closed) { /* Don't close more than once */
3792 MYDB_BEGIN_ALLOW_THREADS;
3793 err = self->db_env->close(self->db_env, flags);
3794 MYDB_END_ALLOW_THREADS;
3795 /* after calling DBEnv->close, regardless of error, this DBEnv
3796 * may not be accessed again (BerkeleyDB docs). */
3797 self->closed = 1;
3798 self->db_env = NULL;
3799 RETURN_IF_ERR();
3800 }
3801 RETURN_NONE();
3802}
3803
3804
3805static PyObject*
3806DBEnv_open(DBEnvObject* self, PyObject* args)
3807{
3808 int err, flags=0, mode=0660;
3809 char *db_home;
3810
3811 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3812 return NULL;
3813
3814 CHECK_ENV_NOT_CLOSED(self);
3815
3816 MYDB_BEGIN_ALLOW_THREADS;
3817 err = self->db_env->open(self->db_env, db_home, flags, mode);
3818 MYDB_END_ALLOW_THREADS;
3819 RETURN_IF_ERR();
3820 self->closed = 0;
3821 self->flags = flags;
3822 RETURN_NONE();
3823}
3824
3825
3826static PyObject*
3827DBEnv_remove(DBEnvObject* self, PyObject* args)
3828{
3829 int err, flags=0;
3830 char *db_home;
3831
3832 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3833 return NULL;
3834 CHECK_ENV_NOT_CLOSED(self);
3835 MYDB_BEGIN_ALLOW_THREADS;
3836 err = self->db_env->remove(self->db_env, db_home, flags);
3837 MYDB_END_ALLOW_THREADS;
3838 RETURN_IF_ERR();
3839 RETURN_NONE();
3840}
3841
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003842#if (DBVER >= 41)
3843static PyObject*
3844DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3845{
3846 int err;
3847 u_int32_t flags=0;
3848 char *file = NULL;
3849 char *database = NULL;
3850 PyObject *txnobj = NULL;
3851 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003852 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003853 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003854
3855 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3856 &file, &database, &txnobj, &flags)) {
3857 return NULL;
3858 }
3859 if (!checkTxnObj(txnobj, &txn)) {
3860 return NULL;
3861 }
3862 CHECK_ENV_NOT_CLOSED(self);
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3868}
3869
3870static PyObject*
3871DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3872{
3873 int err;
3874 u_int32_t flags=0;
3875 char *file = NULL;
3876 char *database = NULL;
3877 char *newname = NULL;
3878 PyObject *txnobj = NULL;
3879 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003880 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003881 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003882
3883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3884 &file, &database, &newname, &txnobj, &flags)) {
3885 return NULL;
3886 }
3887 if (!checkTxnObj(txnobj, &txn)) {
3888 return NULL;
3889 }
3890 CHECK_ENV_NOT_CLOSED(self);
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3893 flags);
3894 MYDB_END_ALLOW_THREADS;
3895 RETURN_IF_ERR();
3896 RETURN_NONE();
3897}
3898
3899static PyObject*
3900DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3901{
3902 int err;
3903 u_int32_t flags=0;
3904 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003905 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003906
3907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3908 &passwd, &flags)) {
3909 return NULL;
3910 }
3911
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3914 MYDB_END_ALLOW_THREADS;
3915
3916 RETURN_IF_ERR();
3917 RETURN_NONE();
3918}
3919#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003920
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003921#if (DBVER >= 40)
3922static PyObject*
3923DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3924{
3925 int err;
3926 u_int32_t flags=0;
3927 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003928 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003929
3930 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3931 &timeout, &flags)) {
3932 return NULL;
3933 }
3934
3935 MYDB_BEGIN_ALLOW_THREADS;
3936 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3937 MYDB_END_ALLOW_THREADS;
3938
3939 RETURN_IF_ERR();
3940 RETURN_NONE();
3941}
3942#endif /* DBVER >= 40 */
3943
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003944static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003945DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3946{
3947 int err;
3948 long shm_key = 0;
3949
3950 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3951 return NULL;
3952 CHECK_ENV_NOT_CLOSED(self);
3953
3954 err = self->db_env->set_shm_key(self->db_env, shm_key);
3955 RETURN_IF_ERR();
3956 RETURN_NONE();
3957}
3958
3959static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003960DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3961{
3962 int err, gbytes=0, bytes=0, ncache=0;
3963
3964 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3965 &gbytes, &bytes, &ncache))
3966 return NULL;
3967 CHECK_ENV_NOT_CLOSED(self);
3968
3969 MYDB_BEGIN_ALLOW_THREADS;
3970 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3971 MYDB_END_ALLOW_THREADS;
3972 RETURN_IF_ERR();
3973 RETURN_NONE();
3974}
3975
3976
3977#if (DBVER >= 32)
3978static PyObject*
3979DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3980{
3981 int err, flags=0, onoff=0;
3982
3983 if (!PyArg_ParseTuple(args, "ii:set_flags",
3984 &flags, &onoff))
3985 return NULL;
3986 CHECK_ENV_NOT_CLOSED(self);
3987
3988 MYDB_BEGIN_ALLOW_THREADS;
3989 err = self->db_env->set_flags(self->db_env, flags, onoff);
3990 MYDB_END_ALLOW_THREADS;
3991 RETURN_IF_ERR();
3992 RETURN_NONE();
3993}
3994#endif
3995
3996
3997static PyObject*
3998DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3999{
4000 int err;
4001 char *dir;
4002
4003 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4004 return NULL;
4005 CHECK_ENV_NOT_CLOSED(self);
4006
4007 MYDB_BEGIN_ALLOW_THREADS;
4008 err = self->db_env->set_data_dir(self->db_env, dir);
4009 MYDB_END_ALLOW_THREADS;
4010 RETURN_IF_ERR();
4011 RETURN_NONE();
4012}
4013
4014
4015static PyObject*
4016DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4017{
4018 int err, lg_bsize;
4019
4020 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4021 return NULL;
4022 CHECK_ENV_NOT_CLOSED(self);
4023
4024 MYDB_BEGIN_ALLOW_THREADS;
4025 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4026 MYDB_END_ALLOW_THREADS;
4027 RETURN_IF_ERR();
4028 RETURN_NONE();
4029}
4030
4031
4032static PyObject*
4033DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4034{
4035 int err;
4036 char *dir;
4037
4038 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4039 return NULL;
4040 CHECK_ENV_NOT_CLOSED(self);
4041
4042 MYDB_BEGIN_ALLOW_THREADS;
4043 err = self->db_env->set_lg_dir(self->db_env, dir);
4044 MYDB_END_ALLOW_THREADS;
4045 RETURN_IF_ERR();
4046 RETURN_NONE();
4047}
4048
4049static PyObject*
4050DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4051{
4052 int err, lg_max;
4053
4054 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4055 return NULL;
4056 CHECK_ENV_NOT_CLOSED(self);
4057
4058 MYDB_BEGIN_ALLOW_THREADS;
4059 err = self->db_env->set_lg_max(self->db_env, lg_max);
4060 MYDB_END_ALLOW_THREADS;
4061 RETURN_IF_ERR();
4062 RETURN_NONE();
4063}
4064
4065
Neal Norwitz84562352005-10-20 04:30:15 +00004066#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004067static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004068DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4069{
4070 int err, lg_max;
4071
4072 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4073 return NULL;
4074 CHECK_ENV_NOT_CLOSED(self);
4075
4076 MYDB_BEGIN_ALLOW_THREADS;
4077 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4078 MYDB_END_ALLOW_THREADS;
4079 RETURN_IF_ERR();
4080 RETURN_NONE();
4081}
Neal Norwitz84562352005-10-20 04:30:15 +00004082#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004083
4084
4085static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004086DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4087{
4088 int err, lk_detect;
4089
4090 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4091 return NULL;
4092 CHECK_ENV_NOT_CLOSED(self);
4093
4094 MYDB_BEGIN_ALLOW_THREADS;
4095 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4096 MYDB_END_ALLOW_THREADS;
4097 RETURN_IF_ERR();
4098 RETURN_NONE();
4099}
4100
4101
4102static PyObject*
4103DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4104{
4105 int err, max;
4106
4107 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4108 return NULL;
4109 CHECK_ENV_NOT_CLOSED(self);
4110
4111 MYDB_BEGIN_ALLOW_THREADS;
4112 err = self->db_env->set_lk_max(self->db_env, max);
4113 MYDB_END_ALLOW_THREADS;
4114 RETURN_IF_ERR();
4115 RETURN_NONE();
4116}
4117
4118
4119#if (DBVER >= 32)
4120
4121static PyObject*
4122DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4123{
4124 int err, max;
4125
4126 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4127 return NULL;
4128 CHECK_ENV_NOT_CLOSED(self);
4129
4130 MYDB_BEGIN_ALLOW_THREADS;
4131 err = self->db_env->set_lk_max_locks(self->db_env, max);
4132 MYDB_END_ALLOW_THREADS;
4133 RETURN_IF_ERR();
4134 RETURN_NONE();
4135}
4136
4137
4138static PyObject*
4139DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4140{
4141 int err, max;
4142
4143 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4144 return NULL;
4145 CHECK_ENV_NOT_CLOSED(self);
4146
4147 MYDB_BEGIN_ALLOW_THREADS;
4148 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4149 MYDB_END_ALLOW_THREADS;
4150 RETURN_IF_ERR();
4151 RETURN_NONE();
4152}
4153
4154
4155static PyObject*
4156DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4157{
4158 int err, max;
4159
4160 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4161 return NULL;
4162 CHECK_ENV_NOT_CLOSED(self);
4163
4164 MYDB_BEGIN_ALLOW_THREADS;
4165 err = self->db_env->set_lk_max_objects(self->db_env, max);
4166 MYDB_END_ALLOW_THREADS;
4167 RETURN_IF_ERR();
4168 RETURN_NONE();
4169}
4170
4171#endif
4172
4173
4174static PyObject*
4175DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4176{
4177 int err, mp_mmapsize;
4178
4179 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4180 return NULL;
4181 CHECK_ENV_NOT_CLOSED(self);
4182
4183 MYDB_BEGIN_ALLOW_THREADS;
4184 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4185 MYDB_END_ALLOW_THREADS;
4186 RETURN_IF_ERR();
4187 RETURN_NONE();
4188}
4189
4190
4191static PyObject*
4192DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4193{
4194 int err;
4195 char *dir;
4196
4197 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4198 return NULL;
4199 CHECK_ENV_NOT_CLOSED(self);
4200
4201 MYDB_BEGIN_ALLOW_THREADS;
4202 err = self->db_env->set_tmp_dir(self->db_env, dir);
4203 MYDB_END_ALLOW_THREADS;
4204 RETURN_IF_ERR();
4205 RETURN_NONE();
4206}
4207
4208
4209static PyObject*
4210DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4211{
4212 int flags = 0;
4213 PyObject* txnobj = NULL;
4214 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004215 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004216
4217 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4218 &txnobj, &flags))
4219 return NULL;
4220
4221 if (!checkTxnObj(txnobj, &txn))
4222 return NULL;
4223 CHECK_ENV_NOT_CLOSED(self);
4224
4225 return (PyObject*)newDBTxnObject(self, txn, flags);
4226}
4227
4228
4229static PyObject*
4230DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4231{
4232 int err, kbyte=0, min=0, flags=0;
4233
4234 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4235 return NULL;
4236 CHECK_ENV_NOT_CLOSED(self);
4237
4238 MYDB_BEGIN_ALLOW_THREADS;
4239#if (DBVER >= 40)
4240 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4241#else
4242 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4243#endif
4244 MYDB_END_ALLOW_THREADS;
4245 RETURN_IF_ERR();
4246 RETURN_NONE();
4247}
4248
4249
4250static PyObject*
4251DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4252{
4253 int err, max;
4254
4255 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4256 return NULL;
4257 CHECK_ENV_NOT_CLOSED(self);
4258
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004259 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004260 RETURN_IF_ERR();
4261 RETURN_NONE();
4262}
4263
4264
4265static PyObject*
4266DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4267{
4268 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004269 long stamp;
4270 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004271
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004272 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004273 return NULL;
4274 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004275 timestamp = (time_t)stamp;
4276 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004277 RETURN_IF_ERR();
4278 RETURN_NONE();
4279}
4280
4281
4282static PyObject*
4283DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4284{
4285 int err, atype, flags=0;
4286 int aborted = 0;
4287
4288 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4289 return NULL;
4290 CHECK_ENV_NOT_CLOSED(self);
4291
4292 MYDB_BEGIN_ALLOW_THREADS;
4293#if (DBVER >= 40)
4294 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4295#else
4296 err = lock_detect(self->db_env, flags, atype, &aborted);
4297#endif
4298 MYDB_END_ALLOW_THREADS;
4299 RETURN_IF_ERR();
4300 return PyInt_FromLong(aborted);
4301}
4302
4303
4304static PyObject*
4305DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4306{
4307 int flags=0;
4308 int locker, lock_mode;
4309 DBT obj;
4310 PyObject* objobj;
4311
4312 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4313 return NULL;
4314
4315
4316 if (!make_dbt(objobj, &obj))
4317 return NULL;
4318
4319 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4320}
4321
4322
4323static PyObject*
4324DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4325{
4326 int err;
4327 u_int32_t theID;
4328
4329 if (!PyArg_ParseTuple(args, ":lock_id"))
4330 return NULL;
4331
4332 CHECK_ENV_NOT_CLOSED(self);
4333 MYDB_BEGIN_ALLOW_THREADS;
4334#if (DBVER >= 40)
4335 err = self->db_env->lock_id(self->db_env, &theID);
4336#else
4337 err = lock_id(self->db_env, &theID);
4338#endif
4339 MYDB_END_ALLOW_THREADS;
4340 RETURN_IF_ERR();
4341
4342 return PyInt_FromLong((long)theID);
4343}
4344
4345
4346static PyObject*
4347DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4348{
4349 int err;
4350 DBLockObject* dblockobj;
4351
4352 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4353 return NULL;
4354
4355 CHECK_ENV_NOT_CLOSED(self);
4356 MYDB_BEGIN_ALLOW_THREADS;
4357#if (DBVER >= 40)
4358 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4359#else
4360 err = lock_put(self->db_env, &dblockobj->lock);
4361#endif
4362 MYDB_END_ALLOW_THREADS;
4363 RETURN_IF_ERR();
4364 RETURN_NONE();
4365}
4366
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004367#if (DBVER >= 44)
4368static PyObject*
4369DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4370{
4371 int err;
4372 char *file;
4373 u_int32_t flags = 0;
4374 static char* kwnames[] = { "file", "flags", NULL};
4375
4376 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4377 &file, &flags))
4378 return NULL;
4379 CHECK_ENV_NOT_CLOSED(self);
4380
4381 MYDB_BEGIN_ALLOW_THREADS;
4382 err = self->db_env->lsn_reset(self->db_env, file, flags);
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385 RETURN_NONE();
4386}
4387#endif /* DBVER >= 4.4 */
4388
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004389#if (DBVER >= 40)
4390static PyObject*
4391DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4392{
4393 int err;
4394 DB_LOG_STAT* statp = NULL;
4395 PyObject* d = NULL;
4396 u_int32_t flags = 0;
4397
4398 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4399 return NULL;
4400 CHECK_ENV_NOT_CLOSED(self);
4401
4402 MYDB_BEGIN_ALLOW_THREADS;
4403 err = self->db_env->log_stat(self->db_env, &statp, flags);
4404 MYDB_END_ALLOW_THREADS;
4405 RETURN_IF_ERR();
4406
4407 /* Turn the stat structure into a dictionary */
4408 d = PyDict_New();
4409 if (d == NULL) {
4410 if (statp)
4411 free(statp);
4412 return NULL;
4413 }
4414
4415#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4416
4417 MAKE_ENTRY(magic);
4418 MAKE_ENTRY(version);
4419 MAKE_ENTRY(mode);
4420 MAKE_ENTRY(lg_bsize);
4421#if (DBVER >= 44)
4422 MAKE_ENTRY(lg_size);
4423 MAKE_ENTRY(record);
4424#endif
4425#if (DBVER <= 40)
4426 MAKE_ENTRY(lg_max);
4427#endif
4428 MAKE_ENTRY(w_mbytes);
4429 MAKE_ENTRY(w_bytes);
4430 MAKE_ENTRY(wc_mbytes);
4431 MAKE_ENTRY(wc_bytes);
4432 MAKE_ENTRY(wcount);
4433 MAKE_ENTRY(wcount_fill);
4434#if (DBVER >= 44)
4435 MAKE_ENTRY(rcount);
4436#endif
4437 MAKE_ENTRY(scount);
4438 MAKE_ENTRY(cur_file);
4439 MAKE_ENTRY(cur_offset);
4440 MAKE_ENTRY(disk_file);
4441 MAKE_ENTRY(disk_offset);
4442 MAKE_ENTRY(maxcommitperflush);
4443 MAKE_ENTRY(mincommitperflush);
4444 MAKE_ENTRY(regsize);
4445 MAKE_ENTRY(region_wait);
4446 MAKE_ENTRY(region_nowait);
4447
4448#undef MAKE_ENTRY
4449 free(statp);
4450 return d;
4451} /* DBEnv_log_stat */
4452#endif /* DBVER >= 4.0 for log_stat method */
4453
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004454
4455static PyObject*
4456DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4457{
4458 int err;
4459 DB_LOCK_STAT* sp;
4460 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004461 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004462
4463 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4464 return NULL;
4465 CHECK_ENV_NOT_CLOSED(self);
4466
4467 MYDB_BEGIN_ALLOW_THREADS;
4468#if (DBVER >= 40)
4469 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4470#else
4471#if (DBVER >= 33)
4472 err = lock_stat(self->db_env, &sp);
4473#else
4474 err = lock_stat(self->db_env, &sp, NULL);
4475#endif
4476#endif
4477 MYDB_END_ALLOW_THREADS;
4478 RETURN_IF_ERR();
4479
4480 /* Turn the stat structure into a dictionary */
4481 d = PyDict_New();
4482 if (d == NULL) {
4483 free(sp);
4484 return NULL;
4485 }
4486
4487#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4488
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004489#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004491#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004492 MAKE_ENTRY(nmodes);
4493#if (DBVER >= 32)
4494 MAKE_ENTRY(maxlocks);
4495 MAKE_ENTRY(maxlockers);
4496 MAKE_ENTRY(maxobjects);
4497 MAKE_ENTRY(nlocks);
4498 MAKE_ENTRY(maxnlocks);
4499#endif
4500 MAKE_ENTRY(nlockers);
4501 MAKE_ENTRY(maxnlockers);
4502#if (DBVER >= 32)
4503 MAKE_ENTRY(nobjects);
4504 MAKE_ENTRY(maxnobjects);
4505#endif
4506 MAKE_ENTRY(nrequests);
4507 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004508#if (DBVER < 44)
4509 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004511#else
4512 MAKE_ENTRY(lock_nowait);
4513 MAKE_ENTRY(lock_wait);
4514#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004515 MAKE_ENTRY(ndeadlocks);
4516 MAKE_ENTRY(regsize);
4517 MAKE_ENTRY(region_wait);
4518 MAKE_ENTRY(region_nowait);
4519
4520#undef MAKE_ENTRY
4521 free(sp);
4522 return d;
4523}
4524
4525
4526static PyObject*
4527DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4528{
4529 int flags=0;
4530 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004531 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004532 PyObject* list;
4533 PyObject* item = NULL;
4534
4535 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4536 return NULL;
4537
4538 CHECK_ENV_NOT_CLOSED(self);
4539 MYDB_BEGIN_ALLOW_THREADS;
4540#if (DBVER >= 40)
4541 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4542#elif (DBVER == 33)
4543 err = log_archive(self->db_env, &log_list, flags);
4544#else
4545 err = log_archive(self->db_env, &log_list, flags, NULL);
4546#endif
4547 MYDB_END_ALLOW_THREADS;
4548 RETURN_IF_ERR();
4549
Gregory P. Smithbad47452006-06-05 00:33:35 +00004550 list = PyList_New(0);
4551 if (list == NULL) {
4552 if (log_list)
4553 free(log_list);
4554 return NULL;
4555 }
4556
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004557 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004558 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004559 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4560 item = PyString_FromString (*log_list);
4561 if (item == NULL) {
4562 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 list = NULL;
4564 break;
4565 }
4566 PyList_Append(list, item);
4567 Py_DECREF(item);
4568 }
4569 free(log_list_start);
4570 }
4571 return list;
4572}
4573
4574
4575static PyObject*
4576DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4577{
4578 int err;
4579 DB_TXN_STAT* sp;
4580 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004581 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004582
4583 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4584 return NULL;
4585 CHECK_ENV_NOT_CLOSED(self);
4586
4587 MYDB_BEGIN_ALLOW_THREADS;
4588#if (DBVER >= 40)
4589 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4590#elif (DBVER == 33)
4591 err = txn_stat(self->db_env, &sp);
4592#else
4593 err = txn_stat(self->db_env, &sp, NULL);
4594#endif
4595 MYDB_END_ALLOW_THREADS;
4596 RETURN_IF_ERR();
4597
4598 /* Turn the stat structure into a dictionary */
4599 d = PyDict_New();
4600 if (d == NULL) {
4601 free(sp);
4602 return NULL;
4603 }
4604
4605#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4606
4607 MAKE_ENTRY(time_ckp);
4608 MAKE_ENTRY(last_txnid);
4609 MAKE_ENTRY(maxtxns);
4610 MAKE_ENTRY(nactive);
4611 MAKE_ENTRY(maxnactive);
4612 MAKE_ENTRY(nbegins);
4613 MAKE_ENTRY(naborts);
4614 MAKE_ENTRY(ncommits);
4615 MAKE_ENTRY(regsize);
4616 MAKE_ENTRY(region_wait);
4617 MAKE_ENTRY(region_nowait);
4618
4619#undef MAKE_ENTRY
4620 free(sp);
4621 return d;
4622}
4623
4624
4625static PyObject*
4626DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4627{
4628 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004629 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630
4631 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4632 return NULL;
4633 CHECK_ENV_NOT_CLOSED(self);
4634
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004635 if (self->moduleFlags.getReturnsNone)
4636 ++oldValue;
4637 if (self->moduleFlags.cursorSetReturnsNone)
4638 ++oldValue;
4639 self->moduleFlags.getReturnsNone = (flags >= 1);
4640 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004641 return PyInt_FromLong(oldValue);
4642}
4643
4644
4645/* --------------------------------------------------------------------- */
4646/* DBTxn methods */
4647
4648
4649static PyObject*
4650DBTxn_commit(DBTxnObject* self, PyObject* args)
4651{
4652 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004653 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004654
4655 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4656 return NULL;
4657
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004658 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004659 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4660 "after txn_commit or txn_abort");
4661 PyErr_SetObject(DBError, t);
4662 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004663 return NULL;
4664 }
4665 txn = self->txn;
4666 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004667 MYDB_BEGIN_ALLOW_THREADS;
4668#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004669 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004670#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004671 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004672#endif
4673 MYDB_END_ALLOW_THREADS;
4674 RETURN_IF_ERR();
4675 RETURN_NONE();
4676}
4677
4678static PyObject*
4679DBTxn_prepare(DBTxnObject* self, PyObject* args)
4680{
4681#if (DBVER >= 33)
4682 int err;
4683 char* gid=NULL;
4684 int gid_size=0;
4685
4686 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4687 return NULL;
4688
4689 if (gid_size != DB_XIDDATASIZE) {
4690 PyErr_SetString(PyExc_TypeError,
4691 "gid must be DB_XIDDATASIZE bytes long");
4692 return NULL;
4693 }
4694
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004695 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004696 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4697 "after txn_commit or txn_abort");
4698 PyErr_SetObject(DBError, t);
4699 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004700 return NULL;
4701 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702 MYDB_BEGIN_ALLOW_THREADS;
4703#if (DBVER >= 40)
4704 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4705#else
4706 err = txn_prepare(self->txn, (u_int8_t*)gid);
4707#endif
4708 MYDB_END_ALLOW_THREADS;
4709 RETURN_IF_ERR();
4710 RETURN_NONE();
4711#else
4712 int err;
4713
4714 if (!PyArg_ParseTuple(args, ":prepare"))
4715 return NULL;
4716
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004717 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004718 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4719 "after txn_commit or txn_abort");
4720 PyErr_SetObject(DBError, t);
4721 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004722 return NULL;
4723 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724 MYDB_BEGIN_ALLOW_THREADS;
4725 err = txn_prepare(self->txn);
4726 MYDB_END_ALLOW_THREADS;
4727 RETURN_IF_ERR();
4728 RETURN_NONE();
4729#endif
4730}
4731
4732
4733static PyObject*
4734DBTxn_abort(DBTxnObject* self, PyObject* args)
4735{
4736 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004737 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004738
4739 if (!PyArg_ParseTuple(args, ":abort"))
4740 return NULL;
4741
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004742 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004743 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4744 "after txn_commit or txn_abort");
4745 PyErr_SetObject(DBError, t);
4746 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004747 return NULL;
4748 }
4749 txn = self->txn;
4750 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004751 MYDB_BEGIN_ALLOW_THREADS;
4752#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004753 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004754#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004755 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004756#endif
4757 MYDB_END_ALLOW_THREADS;
4758 RETURN_IF_ERR();
4759 RETURN_NONE();
4760}
4761
4762
4763static PyObject*
4764DBTxn_id(DBTxnObject* self, PyObject* args)
4765{
4766 int id;
4767
4768 if (!PyArg_ParseTuple(args, ":id"))
4769 return NULL;
4770
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004771 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004772 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4773 "after txn_commit or txn_abort");
4774 PyErr_SetObject(DBError, t);
4775 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004776 return NULL;
4777 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004778 MYDB_BEGIN_ALLOW_THREADS;
4779#if (DBVER >= 40)
4780 id = self->txn->id(self->txn);
4781#else
4782 id = txn_id(self->txn);
4783#endif
4784 MYDB_END_ALLOW_THREADS;
4785 return PyInt_FromLong(id);
4786}
4787
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004788#if (DBVER >= 43)
4789/* --------------------------------------------------------------------- */
4790/* DBSequence methods */
4791
4792
4793static PyObject*
4794DBSequence_close(DBSequenceObject* self, PyObject* args)
4795{
4796 int err, flags=0;
4797 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4798 return NULL;
4799 CHECK_SEQUENCE_NOT_CLOSED(self)
4800
4801 MYDB_BEGIN_ALLOW_THREADS
4802 err = self->sequence->close(self->sequence, flags);
4803 self->sequence = NULL;
4804 MYDB_END_ALLOW_THREADS
4805
4806 RETURN_IF_ERR();
4807
4808 RETURN_NONE();
4809}
4810
4811static PyObject*
4812DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4813{
4814 int err, flags = 0;
4815 int delta = 1;
4816 db_seq_t value;
4817 PyObject *txnobj = NULL;
4818 DB_TXN *txn = NULL;
4819 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4820 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4821 return NULL;
4822 CHECK_SEQUENCE_NOT_CLOSED(self)
4823
4824 if (!checkTxnObj(txnobj, &txn))
4825 return NULL;
4826
4827 MYDB_BEGIN_ALLOW_THREADS
4828 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4829 MYDB_END_ALLOW_THREADS
4830
4831 RETURN_IF_ERR();
4832 return PyLong_FromLongLong(value);
4833
4834}
4835
4836static PyObject*
4837DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4838{
4839 if (!PyArg_ParseTuple(args,":get_dbp"))
4840 return NULL;
4841 CHECK_SEQUENCE_NOT_CLOSED(self)
4842 Py_INCREF(self->mydb);
4843 return (PyObject* )self->mydb;
4844}
4845
4846static PyObject*
4847DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4848{
4849 int err;
4850 DBT key;
4851 CHECK_SEQUENCE_NOT_CLOSED(self)
4852 MYDB_BEGIN_ALLOW_THREADS
4853 err = self->sequence->get_key(self->sequence, &key);
4854 MYDB_END_ALLOW_THREADS
4855
4856 RETURN_IF_ERR();
4857
4858 return PyString_FromStringAndSize(key.data, key.size);
4859}
4860
4861static PyObject*
4862DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4863{
4864 int err;
4865 db_seq_t value;
4866 if (!PyArg_ParseTuple(args,"L|:init_value", &value))
4867 return NULL;
4868 CHECK_SEQUENCE_NOT_CLOSED(self)
4869
4870 MYDB_BEGIN_ALLOW_THREADS
4871 err = self->sequence->initial_value(self->sequence, value);
4872 MYDB_END_ALLOW_THREADS
4873
4874 RETURN_IF_ERR();
4875
4876 RETURN_NONE();
4877}
4878
4879static PyObject*
4880DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4881{
4882 int err, flags = 0;
4883 PyObject* keyobj;
4884 PyObject *txnobj = NULL;
4885 DB_TXN *txn = NULL;
4886 DBT key;
4887
4888 static char* kwnames[] = {"key", "txn", "flags", NULL };
4889 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:set", kwnames, &keyobj, &txnobj, &flags))
4890 return NULL;
4891
4892 if (!checkTxnObj(txnobj, &txn))
4893 return NULL;
4894
4895 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4896 return NULL;
4897
4898 MYDB_BEGIN_ALLOW_THREADS
4899 err = self->sequence->open(self->sequence, txn, &key, flags);
4900 MYDB_END_ALLOW_THREADS
4901
4902 CLEAR_DBT(key);
4903 RETURN_IF_ERR();
4904
4905 RETURN_NONE();
4906}
4907
4908static PyObject*
4909DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4910{
4911 int err, flags = 0;
4912 PyObject *txnobj = NULL;
4913 DB_TXN *txn = NULL;
4914
4915 static char* kwnames[] = {"txn", "flags", NULL };
4916 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:set", kwnames, &txnobj, &flags))
4917 return NULL;
4918
4919 if (!checkTxnObj(txnobj, &txn))
4920 return NULL;
4921
4922 CHECK_SEQUENCE_NOT_CLOSED(self)
4923
4924 MYDB_BEGIN_ALLOW_THREADS
4925 err = self->sequence->remove(self->sequence, txn, flags);
4926 MYDB_END_ALLOW_THREADS
4927
4928 RETURN_IF_ERR();
4929 RETURN_NONE();
4930}
4931
4932static PyObject*
4933DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4934{
4935 int err, size;
4936 if (!PyArg_ParseTuple(args,"i|:set_cachesize", &size))
4937 return NULL;
4938 CHECK_SEQUENCE_NOT_CLOSED(self)
4939
4940 MYDB_BEGIN_ALLOW_THREADS
4941 err = self->sequence->set_cachesize(self->sequence, size);
4942 MYDB_END_ALLOW_THREADS
4943
4944 RETURN_IF_ERR();
4945 RETURN_NONE();
4946}
4947
4948static PyObject*
4949DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4950{
4951 int err, size;
4952 if (!PyArg_ParseTuple(args,":get_cachesize"))
4953 return NULL;
4954 CHECK_SEQUENCE_NOT_CLOSED(self)
4955
4956 MYDB_BEGIN_ALLOW_THREADS
4957 err = self->sequence->get_cachesize(self->sequence, &size);
4958 MYDB_END_ALLOW_THREADS
4959
4960 RETURN_IF_ERR();
4961 return PyInt_FromLong(size);
4962}
4963
4964static PyObject*
4965DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4966{
4967 int err, flags = 0;
4968 if (!PyArg_ParseTuple(args,"i|:set_flags", &flags))
4969 return NULL;
4970 CHECK_SEQUENCE_NOT_CLOSED(self)
4971
4972 MYDB_BEGIN_ALLOW_THREADS
4973 err = self->sequence->set_flags(self->sequence, flags);
4974 MYDB_END_ALLOW_THREADS
4975
4976 RETURN_IF_ERR();
4977 RETURN_NONE();
4978
4979}
4980
4981static PyObject*
4982DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4983{
4984 unsigned int flags;
4985 int err;
4986 if (!PyArg_ParseTuple(args,":get_cachesize"))
4987 return NULL;
4988 CHECK_SEQUENCE_NOT_CLOSED(self)
4989
4990 MYDB_BEGIN_ALLOW_THREADS
4991 err = self->sequence->get_flags(self->sequence, &flags);
4992 MYDB_END_ALLOW_THREADS
4993
4994 RETURN_IF_ERR();
4995 return PyInt_FromLong((int)flags);
4996}
4997
4998static PyObject*
4999DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5000{
5001 int err;
5002 db_seq_t min, max;
5003 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5004 return NULL;
5005 CHECK_SEQUENCE_NOT_CLOSED(self)
5006
5007 MYDB_BEGIN_ALLOW_THREADS
5008 err = self->sequence->set_range(self->sequence, min, max);
5009 MYDB_END_ALLOW_THREADS
5010
5011 RETURN_IF_ERR();
5012 RETURN_NONE();
5013}
5014
5015static PyObject*
5016DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5017{
5018 int err;
5019 db_seq_t min, max;
5020 if (!PyArg_ParseTuple(args,":get_range"))
5021 return NULL;
5022 CHECK_SEQUENCE_NOT_CLOSED(self)
5023
5024 MYDB_BEGIN_ALLOW_THREADS
5025 err = self->sequence->get_range(self->sequence, &min, &max);
5026 MYDB_END_ALLOW_THREADS
5027
5028 RETURN_IF_ERR();
5029 return Py_BuildValue("(LL)", min, max);
5030}
5031
5032static PyObject*
5033DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5034{
5035 int err, flags = 0;
5036 DB_SEQUENCE_STAT* sp = NULL;
5037 PyObject* dict_stat;
5038 static char* kwnames[] = {"flags", NULL };
5039 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5040 return NULL;
5041 CHECK_SEQUENCE_NOT_CLOSED(self);
5042
5043 MYDB_BEGIN_ALLOW_THREADS;
5044 err = self->sequence->stat(self->sequence, &sp, flags);
5045 MYDB_END_ALLOW_THREADS;
5046 RETURN_IF_ERR();
5047
5048 if ((dict_stat = PyDict_New()) == NULL) {
5049 free(sp);
5050 return NULL;
5051 }
5052
5053
5054#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5055#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5056
5057 MAKE_INT_ENTRY(wait);
5058 MAKE_INT_ENTRY(nowait);
5059 MAKE_LONG_LONG_ENTRY(current);
5060 MAKE_LONG_LONG_ENTRY(value);
5061 MAKE_LONG_LONG_ENTRY(last_value);
5062 MAKE_LONG_LONG_ENTRY(min);
5063 MAKE_LONG_LONG_ENTRY(max);
5064 MAKE_INT_ENTRY(cache_size);
5065 MAKE_INT_ENTRY(flags);
5066
5067#undef MAKE_INT_ENTRY
5068#undef MAKE_LONG_LONG_ENTRY
5069
5070 free(sp);
5071 return dict_stat;
5072}
5073#endif
5074
5075
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005076/* --------------------------------------------------------------------- */
5077/* Method definition tables and type objects */
5078
5079static PyMethodDef DB_methods[] = {
5080 {"append", (PyCFunction)DB_append, METH_VARARGS},
5081#if (DBVER >= 33)
5082 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5083#endif
5084 {"close", (PyCFunction)DB_close, METH_VARARGS},
5085#if (DBVER >= 32)
5086 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5087 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5088#endif
5089 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5090 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5091 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5092 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005093#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005094 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005095#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005096 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5097 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5098 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5099 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5100 {"join", (PyCFunction)DB_join, METH_VARARGS},
5101 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5102 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5103 {"items", (PyCFunction)DB_items, METH_VARARGS},
5104 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5105 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5106 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5107 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5108 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5109 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005110#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005111 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005112#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005113 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005114#if (DBVER >= 41)
5115 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5116#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005117 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5118 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5119 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5120 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5121 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5122 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5123 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5124 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5125 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5126#if (DBVER >= 32)
5127 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5128#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005129 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005130 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5131#if (DBVER >= 33)
5132 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5133#endif
5134 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5135 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5136 {"values", (PyCFunction)DB_values, METH_VARARGS},
5137 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5138 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5139 {NULL, NULL} /* sentinel */
5140};
5141
5142
5143static PyMappingMethods DB_mapping = {
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005144#if (PY_VERSION_HEX < 0x02050000)
5145 (inquiry)DB_length, /*mp_length*/
5146#else
Martin v. Löwis18e16552006-02-15 17:27:45 +00005147 (lenfunc)DB_length, /*mp_length*/
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005148#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005149 (binaryfunc)DB_subscript, /*mp_subscript*/
5150 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5151};
5152
5153
5154static PyMethodDef DBCursor_methods[] = {
5155 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5156 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5157 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5158 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5159 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5160 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5161 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005162#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005163 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005164#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005165 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5166 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5167 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5168 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5169 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5170 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5171 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5172 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005173 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005174 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005175 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5176 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5177 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5178 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5179 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5180 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5181 {NULL, NULL} /* sentinel */
5182};
5183
5184
5185static PyMethodDef DBEnv_methods[] = {
5186 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5187 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5188 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005189#if (DBVER >= 41)
5190 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5191 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5192 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5193#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005194#if (DBVER >= 40)
5195 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5196#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005197 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005198 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5199 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5200#if (DBVER >= 32)
5201 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5202#endif
5203 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5204 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5205 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005206#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005207 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005208#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005209 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5210 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5211#if (DBVER >= 32)
5212 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5213 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5214 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5215#endif
5216 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5217 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5218 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5219 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5220 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5221 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005222 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005223 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5224 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5225 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5226 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5227 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5228 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005229#if (DBVER >= 40)
5230 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5231#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005232#if (DBVER >= 44)
5233 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5234#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005235 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5236 {NULL, NULL} /* sentinel */
5237};
5238
5239
5240static PyMethodDef DBTxn_methods[] = {
5241 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5242 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5243 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5244 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5245 {NULL, NULL} /* sentinel */
5246};
5247
5248
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005249#if (DBVER >= 43)
5250static PyMethodDef DBSequence_methods[] = {
5251 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5252 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5253 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5254 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5255 //should it be called "initial_value" as in c code?
5256 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5257 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5258 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5259 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5260 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5261 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5262 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5263 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5264 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5265 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5266 {NULL, NULL} /* sentinel */
5267};
5268#endif
5269
5270
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005271static PyObject*
5272DB_getattr(DBObject* self, char *name)
5273{
5274 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5275}
5276
5277
5278static PyObject*
5279DBEnv_getattr(DBEnvObject* self, char *name)
5280{
5281 if (!strcmp(name, "db_home")) {
5282 CHECK_ENV_NOT_CLOSED(self);
5283 if (self->db_env->db_home == NULL) {
5284 RETURN_NONE();
5285 }
5286 return PyString_FromString(self->db_env->db_home);
5287 }
5288
5289 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5290}
5291
5292
5293static PyObject*
5294DBCursor_getattr(DBCursorObject* self, char *name)
5295{
5296 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5297}
5298
5299static PyObject*
5300DBTxn_getattr(DBTxnObject* self, char *name)
5301{
5302 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5303}
5304
5305static PyObject*
5306DBLock_getattr(DBLockObject* self, char *name)
5307{
5308 return NULL;
5309}
5310
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005311#if (DBVER >= 43)
5312static PyObject*
5313DBSequence_getattr(DBSequenceObject* self, char *name)
5314{
5315 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5316}
5317#endif
5318
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005319statichere PyTypeObject DB_Type = {
5320 PyObject_HEAD_INIT(NULL)
5321 0, /*ob_size*/
5322 "DB", /*tp_name*/
5323 sizeof(DBObject), /*tp_basicsize*/
5324 0, /*tp_itemsize*/
5325 /* methods */
5326 (destructor)DB_dealloc, /*tp_dealloc*/
5327 0, /*tp_print*/
5328 (getattrfunc)DB_getattr, /*tp_getattr*/
5329 0, /*tp_setattr*/
5330 0, /*tp_compare*/
5331 0, /*tp_repr*/
5332 0, /*tp_as_number*/
5333 0, /*tp_as_sequence*/
5334 &DB_mapping,/*tp_as_mapping*/
5335 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005336#ifdef HAVE_WEAKREF
5337 0, /* tp_call */
5338 0, /* tp_str */
5339 0, /* tp_getattro */
5340 0, /* tp_setattro */
5341 0, /* tp_as_buffer */
5342 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5343 0, /* tp_doc */
5344 0, /* tp_traverse */
5345 0, /* tp_clear */
5346 0, /* tp_richcompare */
5347 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5348#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005349};
5350
5351
5352statichere PyTypeObject DBCursor_Type = {
5353 PyObject_HEAD_INIT(NULL)
5354 0, /*ob_size*/
5355 "DBCursor", /*tp_name*/
5356 sizeof(DBCursorObject), /*tp_basicsize*/
5357 0, /*tp_itemsize*/
5358 /* methods */
5359 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5360 0, /*tp_print*/
5361 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5362 0, /*tp_setattr*/
5363 0, /*tp_compare*/
5364 0, /*tp_repr*/
5365 0, /*tp_as_number*/
5366 0, /*tp_as_sequence*/
5367 0, /*tp_as_mapping*/
5368 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005369#ifdef HAVE_WEAKREF
5370 0, /* tp_call */
5371 0, /* tp_str */
5372 0, /* tp_getattro */
5373 0, /* tp_setattro */
5374 0, /* tp_as_buffer */
5375 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5376 0, /* tp_doc */
5377 0, /* tp_traverse */
5378 0, /* tp_clear */
5379 0, /* tp_richcompare */
5380 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5381#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005382};
5383
5384
5385statichere PyTypeObject DBEnv_Type = {
5386 PyObject_HEAD_INIT(NULL)
5387 0, /*ob_size*/
5388 "DBEnv", /*tp_name*/
5389 sizeof(DBEnvObject), /*tp_basicsize*/
5390 0, /*tp_itemsize*/
5391 /* methods */
5392 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5393 0, /*tp_print*/
5394 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5395 0, /*tp_setattr*/
5396 0, /*tp_compare*/
5397 0, /*tp_repr*/
5398 0, /*tp_as_number*/
5399 0, /*tp_as_sequence*/
5400 0, /*tp_as_mapping*/
5401 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005402#ifdef HAVE_WEAKREF
5403 0, /* tp_call */
5404 0, /* tp_str */
5405 0, /* tp_getattro */
5406 0, /* tp_setattro */
5407 0, /* tp_as_buffer */
5408 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5409 0, /* tp_doc */
5410 0, /* tp_traverse */
5411 0, /* tp_clear */
5412 0, /* tp_richcompare */
5413 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5414#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005415};
5416
5417statichere PyTypeObject DBTxn_Type = {
5418 PyObject_HEAD_INIT(NULL)
5419 0, /*ob_size*/
5420 "DBTxn", /*tp_name*/
5421 sizeof(DBTxnObject), /*tp_basicsize*/
5422 0, /*tp_itemsize*/
5423 /* methods */
5424 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5425 0, /*tp_print*/
5426 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5427 0, /*tp_setattr*/
5428 0, /*tp_compare*/
5429 0, /*tp_repr*/
5430 0, /*tp_as_number*/
5431 0, /*tp_as_sequence*/
5432 0, /*tp_as_mapping*/
5433 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005434#ifdef HAVE_WEAKREF
5435 0, /* tp_call */
5436 0, /* tp_str */
5437 0, /* tp_getattro */
5438 0, /* tp_setattro */
5439 0, /* tp_as_buffer */
5440 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5441 0, /* tp_doc */
5442 0, /* tp_traverse */
5443 0, /* tp_clear */
5444 0, /* tp_richcompare */
5445 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5446#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005447};
5448
5449
5450statichere PyTypeObject DBLock_Type = {
5451 PyObject_HEAD_INIT(NULL)
5452 0, /*ob_size*/
5453 "DBLock", /*tp_name*/
5454 sizeof(DBLockObject), /*tp_basicsize*/
5455 0, /*tp_itemsize*/
5456 /* methods */
5457 (destructor)DBLock_dealloc, /*tp_dealloc*/
5458 0, /*tp_print*/
5459 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5460 0, /*tp_setattr*/
5461 0, /*tp_compare*/
5462 0, /*tp_repr*/
5463 0, /*tp_as_number*/
5464 0, /*tp_as_sequence*/
5465 0, /*tp_as_mapping*/
5466 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005467#ifdef HAVE_WEAKREF
5468 0, /* tp_call */
5469 0, /* tp_str */
5470 0, /* tp_getattro */
5471 0, /* tp_setattro */
5472 0, /* tp_as_buffer */
5473 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5474 0, /* tp_doc */
5475 0, /* tp_traverse */
5476 0, /* tp_clear */
5477 0, /* tp_richcompare */
5478 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5479#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005480};
5481
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005482#if (DBVER >= 43)
5483statichere PyTypeObject DBSequence_Type = {
5484 PyObject_HEAD_INIT(NULL)
5485 0, /*ob_size*/
5486 "DBSequence", /*tp_name*/
5487 sizeof(DBSequenceObject), /*tp_basicsize*/
5488 0, /*tp_itemsize*/
5489 /* methods */
5490 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5491 0, /*tp_print*/
5492 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5493 0, /*tp_setattr*/
5494 0, /*tp_compare*/
5495 0, /*tp_repr*/
5496 0, /*tp_as_number*/
5497 0, /*tp_as_sequence*/
5498 0, /*tp_as_mapping*/
5499 0, /*tp_hash*/
5500#ifdef HAVE_WEAKREF
5501 0, /* tp_call */
5502 0, /* tp_str */
5503 0, /* tp_getattro */
5504 0, /* tp_setattro */
5505 0, /* tp_as_buffer */
5506 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5507 0, /* tp_doc */
5508 0, /* tp_traverse */
5509 0, /* tp_clear */
5510 0, /* tp_richcompare */
5511 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5512#endif
5513};
5514#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005515
5516/* --------------------------------------------------------------------- */
5517/* Module-level functions */
5518
5519static PyObject*
5520DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5521{
5522 PyObject* dbenvobj = NULL;
5523 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005524 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005525
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005526 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5527 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005528 return NULL;
5529 if (dbenvobj == Py_None)
5530 dbenvobj = NULL;
5531 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5532 makeTypeError("DBEnv", dbenvobj);
5533 return NULL;
5534 }
5535
5536 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5537}
5538
5539
5540static PyObject*
5541DBEnv_construct(PyObject* self, PyObject* args)
5542{
5543 int flags = 0;
5544 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5545 return (PyObject* )newDBEnvObject(flags);
5546}
5547
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005548#if (DBVER >= 43)
5549static PyObject*
5550DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5551{
5552 PyObject* dbobj = NULL;
5553 int flags = 0;
5554 static char* kwnames[] = { "db", "flags", NULL};
5555
5556 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5557 return NULL;
5558 if (dbobj == Py_None)
5559 dbobj = NULL;
5560 else if (dbobj && !DBObject_Check(dbobj)) {
5561 makeTypeError("DB", dbobj);
5562 return NULL;
5563 }
5564 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5565}
5566#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005567
5568static char bsddb_version_doc[] =
5569"Returns a tuple of major, minor, and patch release numbers of the\n\
5570underlying DB library.";
5571
5572static PyObject*
5573bsddb_version(PyObject* self, PyObject* args)
5574{
5575 int major, minor, patch;
5576
5577 if (!PyArg_ParseTuple(args, ":version"))
5578 return NULL;
5579 db_version(&major, &minor, &patch);
5580 return Py_BuildValue("(iii)", major, minor, patch);
5581}
5582
5583
5584/* List of functions defined in the module */
5585
5586static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005587 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5588 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5589#if (DBVER >= 43)
5590 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5591#endif
5592 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005593 {NULL, NULL} /* sentinel */
5594};
5595
5596
5597/* --------------------------------------------------------------------- */
5598/* Module initialization */
5599
5600
5601/* Convenience routine to export an integer value.
5602 * Errors are silently ignored, for better or for worse...
5603 */
5604#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5605
Gregory P. Smith41631e82003-09-21 00:08:14 +00005606#define MODULE_NAME_MAX_LEN 11
5607static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005608
5609DL_EXPORT(void) init_bsddb(void)
5610{
5611 PyObject* m;
5612 PyObject* d;
5613 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5614 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5615 PyObject* cvsid_s = PyString_FromString( rcs_id );
5616
5617 /* Initialize the type of the new type objects here; doing it here
5618 is required for portability to Windows without requiring C++. */
5619 DB_Type.ob_type = &PyType_Type;
5620 DBCursor_Type.ob_type = &PyType_Type;
5621 DBEnv_Type.ob_type = &PyType_Type;
5622 DBTxn_Type.ob_type = &PyType_Type;
5623 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005624#if (DBVER >= 43)
5625 DBSequence_Type.ob_type = &PyType_Type;
5626#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005627
5628
Mark Hammonda69d4092003-04-22 23:13:27 +00005629#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005630 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005631 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005632#endif
5633
5634 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005635 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005636 if (m == NULL)
5637 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638
5639 /* Add some symbolic constants to the module */
5640 d = PyModule_GetDict(m);
5641 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5642 PyDict_SetItemString(d, "cvsid", cvsid_s);
5643 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5644 Py_DECREF(pybsddb_version_s);
5645 pybsddb_version_s = NULL;
5646 Py_DECREF(cvsid_s);
5647 cvsid_s = NULL;
5648 Py_DECREF(db_version_s);
5649 db_version_s = NULL;
5650
5651 ADD_INT(d, DB_VERSION_MAJOR);
5652 ADD_INT(d, DB_VERSION_MINOR);
5653 ADD_INT(d, DB_VERSION_PATCH);
5654
5655 ADD_INT(d, DB_MAX_PAGES);
5656 ADD_INT(d, DB_MAX_RECORDS);
5657
Gregory P. Smith41631e82003-09-21 00:08:14 +00005658#if (DBVER >= 42)
5659 ADD_INT(d, DB_RPCCLIENT);
5660#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005661 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005662 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5663 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5664#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005665 ADD_INT(d, DB_XA_CREATE);
5666
5667 ADD_INT(d, DB_CREATE);
5668 ADD_INT(d, DB_NOMMAP);
5669 ADD_INT(d, DB_THREAD);
5670
5671 ADD_INT(d, DB_FORCE);
5672 ADD_INT(d, DB_INIT_CDB);
5673 ADD_INT(d, DB_INIT_LOCK);
5674 ADD_INT(d, DB_INIT_LOG);
5675 ADD_INT(d, DB_INIT_MPOOL);
5676 ADD_INT(d, DB_INIT_TXN);
5677#if (DBVER >= 32)
5678 ADD_INT(d, DB_JOINENV);
5679#endif
5680
5681 ADD_INT(d, DB_RECOVER);
5682 ADD_INT(d, DB_RECOVER_FATAL);
5683 ADD_INT(d, DB_TXN_NOSYNC);
5684 ADD_INT(d, DB_USE_ENVIRON);
5685 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5686
5687 ADD_INT(d, DB_LOCKDOWN);
5688 ADD_INT(d, DB_PRIVATE);
5689 ADD_INT(d, DB_SYSTEM_MEM);
5690
5691 ADD_INT(d, DB_TXN_SYNC);
5692 ADD_INT(d, DB_TXN_NOWAIT);
5693
5694 ADD_INT(d, DB_EXCL);
5695 ADD_INT(d, DB_FCNTL_LOCKING);
5696 ADD_INT(d, DB_ODDFILESIZE);
5697 ADD_INT(d, DB_RDWRMASTER);
5698 ADD_INT(d, DB_RDONLY);
5699 ADD_INT(d, DB_TRUNCATE);
5700#if (DBVER >= 32)
5701 ADD_INT(d, DB_EXTENT);
5702 ADD_INT(d, DB_CDB_ALLDB);
5703 ADD_INT(d, DB_VERIFY);
5704#endif
5705 ADD_INT(d, DB_UPGRADE);
5706
5707 ADD_INT(d, DB_AGGRESSIVE);
5708 ADD_INT(d, DB_NOORDERCHK);
5709 ADD_INT(d, DB_ORDERCHKONLY);
5710 ADD_INT(d, DB_PR_PAGE);
5711#if ! (DBVER >= 33)
5712 ADD_INT(d, DB_VRFY_FLAGMASK);
5713 ADD_INT(d, DB_PR_HEADERS);
5714#endif
5715 ADD_INT(d, DB_PR_RECOVERYTEST);
5716 ADD_INT(d, DB_SALVAGE);
5717
5718 ADD_INT(d, DB_LOCK_NORUN);
5719 ADD_INT(d, DB_LOCK_DEFAULT);
5720 ADD_INT(d, DB_LOCK_OLDEST);
5721 ADD_INT(d, DB_LOCK_RANDOM);
5722 ADD_INT(d, DB_LOCK_YOUNGEST);
5723#if (DBVER >= 33)
5724 ADD_INT(d, DB_LOCK_MAXLOCKS);
5725 ADD_INT(d, DB_LOCK_MINLOCKS);
5726 ADD_INT(d, DB_LOCK_MINWRITE);
5727#endif
5728
5729
5730#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005731 /* docs say to use zero instead */
5732 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005733#else
5734 ADD_INT(d, DB_LOCK_CONFLICT);
5735#endif
5736
5737 ADD_INT(d, DB_LOCK_DUMP);
5738 ADD_INT(d, DB_LOCK_GET);
5739 ADD_INT(d, DB_LOCK_INHERIT);
5740 ADD_INT(d, DB_LOCK_PUT);
5741 ADD_INT(d, DB_LOCK_PUT_ALL);
5742 ADD_INT(d, DB_LOCK_PUT_OBJ);
5743
5744 ADD_INT(d, DB_LOCK_NG);
5745 ADD_INT(d, DB_LOCK_READ);
5746 ADD_INT(d, DB_LOCK_WRITE);
5747 ADD_INT(d, DB_LOCK_NOWAIT);
5748#if (DBVER >= 32)
5749 ADD_INT(d, DB_LOCK_WAIT);
5750#endif
5751 ADD_INT(d, DB_LOCK_IWRITE);
5752 ADD_INT(d, DB_LOCK_IREAD);
5753 ADD_INT(d, DB_LOCK_IWR);
5754#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005755#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005756 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005757#else
5758 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5759#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005760 ADD_INT(d, DB_LOCK_WWRITE);
5761#endif
5762
5763 ADD_INT(d, DB_LOCK_RECORD);
5764 ADD_INT(d, DB_LOCK_UPGRADE);
5765#if (DBVER >= 32)
5766 ADD_INT(d, DB_LOCK_SWITCH);
5767#endif
5768#if (DBVER >= 33)
5769 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5770#endif
5771
5772 ADD_INT(d, DB_LOCK_NOWAIT);
5773 ADD_INT(d, DB_LOCK_RECORD);
5774 ADD_INT(d, DB_LOCK_UPGRADE);
5775
5776#if (DBVER >= 33)
5777 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005778#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005779 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005780#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005781 ADD_INT(d, DB_LSTAT_FREE);
5782 ADD_INT(d, DB_LSTAT_HELD);
5783#if (DBVER == 33)
5784 ADD_INT(d, DB_LSTAT_NOGRANT);
5785#endif
5786 ADD_INT(d, DB_LSTAT_PENDING);
5787 ADD_INT(d, DB_LSTAT_WAITING);
5788#endif
5789
5790 ADD_INT(d, DB_ARCH_ABS);
5791 ADD_INT(d, DB_ARCH_DATA);
5792 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005793#if (DBVER >= 42)
5794 ADD_INT(d, DB_ARCH_REMOVE);
5795#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796
5797 ADD_INT(d, DB_BTREE);
5798 ADD_INT(d, DB_HASH);
5799 ADD_INT(d, DB_RECNO);
5800 ADD_INT(d, DB_QUEUE);
5801 ADD_INT(d, DB_UNKNOWN);
5802
5803 ADD_INT(d, DB_DUP);
5804 ADD_INT(d, DB_DUPSORT);
5805 ADD_INT(d, DB_RECNUM);
5806 ADD_INT(d, DB_RENUMBER);
5807 ADD_INT(d, DB_REVSPLITOFF);
5808 ADD_INT(d, DB_SNAPSHOT);
5809
5810 ADD_INT(d, DB_JOIN_NOSORT);
5811
5812 ADD_INT(d, DB_AFTER);
5813 ADD_INT(d, DB_APPEND);
5814 ADD_INT(d, DB_BEFORE);
5815 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005816#if (DBVER >= 41)
5817 _addIntToDict(d, "DB_CHECKPOINT", 0);
5818#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005819 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005820 ADD_INT(d, DB_CURLSN);
5821#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005822#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005823 ADD_INT(d, DB_COMMIT);
5824#endif
5825 ADD_INT(d, DB_CONSUME);
5826#if (DBVER >= 32)
5827 ADD_INT(d, DB_CONSUME_WAIT);
5828#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_CURRENT);
5830#if (DBVER >= 33)
5831 ADD_INT(d, DB_FAST_STAT);
5832#endif
5833 ADD_INT(d, DB_FIRST);
5834 ADD_INT(d, DB_FLUSH);
5835 ADD_INT(d, DB_GET_BOTH);
5836 ADD_INT(d, DB_GET_RECNO);
5837 ADD_INT(d, DB_JOIN_ITEM);
5838 ADD_INT(d, DB_KEYFIRST);
5839 ADD_INT(d, DB_KEYLAST);
5840 ADD_INT(d, DB_LAST);
5841 ADD_INT(d, DB_NEXT);
5842 ADD_INT(d, DB_NEXT_DUP);
5843 ADD_INT(d, DB_NEXT_NODUP);
5844 ADD_INT(d, DB_NODUPDATA);
5845 ADD_INT(d, DB_NOOVERWRITE);
5846 ADD_INT(d, DB_NOSYNC);
5847 ADD_INT(d, DB_POSITION);
5848 ADD_INT(d, DB_PREV);
5849 ADD_INT(d, DB_PREV_NODUP);
5850 ADD_INT(d, DB_RECORDCOUNT);
5851 ADD_INT(d, DB_SET);
5852 ADD_INT(d, DB_SET_RANGE);
5853 ADD_INT(d, DB_SET_RECNO);
5854 ADD_INT(d, DB_WRITECURSOR);
5855
5856 ADD_INT(d, DB_OPFLAGS_MASK);
5857 ADD_INT(d, DB_RMW);
5858#if (DBVER >= 33)
5859 ADD_INT(d, DB_DIRTY_READ);
5860 ADD_INT(d, DB_MULTIPLE);
5861 ADD_INT(d, DB_MULTIPLE_KEY);
5862#endif
5863
Gregory P. Smith29602d22006-01-24 09:46:48 +00005864#if (DBVER >= 44)
5865 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5866 ADD_INT(d, DB_READ_COMMITTED);
5867#endif
5868
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005869#if (DBVER >= 33)
5870 ADD_INT(d, DB_DONOTINDEX);
5871#endif
5872
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005873#if (DBVER >= 41)
5874 _addIntToDict(d, "DB_INCOMPLETE", 0);
5875#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005876 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005877#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005878 ADD_INT(d, DB_KEYEMPTY);
5879 ADD_INT(d, DB_KEYEXIST);
5880 ADD_INT(d, DB_LOCK_DEADLOCK);
5881 ADD_INT(d, DB_LOCK_NOTGRANTED);
5882 ADD_INT(d, DB_NOSERVER);
5883 ADD_INT(d, DB_NOSERVER_HOME);
5884 ADD_INT(d, DB_NOSERVER_ID);
5885 ADD_INT(d, DB_NOTFOUND);
5886 ADD_INT(d, DB_OLD_VERSION);
5887 ADD_INT(d, DB_RUNRECOVERY);
5888 ADD_INT(d, DB_VERIFY_BAD);
5889#if (DBVER >= 33)
5890 ADD_INT(d, DB_PAGE_NOTFOUND);
5891 ADD_INT(d, DB_SECONDARY_BAD);
5892#endif
5893#if (DBVER >= 40)
5894 ADD_INT(d, DB_STAT_CLEAR);
5895 ADD_INT(d, DB_REGION_INIT);
5896 ADD_INT(d, DB_NOLOCKING);
5897 ADD_INT(d, DB_YIELDCPU);
5898 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5899 ADD_INT(d, DB_NOPANIC);
5900#endif
5901
Gregory P. Smith41631e82003-09-21 00:08:14 +00005902#if (DBVER >= 42)
5903 ADD_INT(d, DB_TIME_NOTGRANTED);
5904 ADD_INT(d, DB_TXN_NOT_DURABLE);
5905 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5906 ADD_INT(d, DB_LOG_AUTOREMOVE);
5907 ADD_INT(d, DB_DIRECT_LOG);
5908 ADD_INT(d, DB_DIRECT_DB);
5909 ADD_INT(d, DB_INIT_REP);
5910 ADD_INT(d, DB_ENCRYPT);
5911 ADD_INT(d, DB_CHKSUM);
5912#endif
5913
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005914#if (DBVER >= 43)
5915 ADD_INT(d, DB_LOG_INMEMORY);
5916 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005917 ADD_INT(d, DB_SEQ_DEC);
5918 ADD_INT(d, DB_SEQ_INC);
5919 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005920#endif
5921
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005922#if (DBVER >= 41)
5923 ADD_INT(d, DB_ENCRYPT_AES);
5924 ADD_INT(d, DB_AUTO_COMMIT);
5925#else
5926 /* allow berkeleydb 4.1 aware apps to run on older versions */
5927 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5928#endif
5929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930 ADD_INT(d, EINVAL);
5931 ADD_INT(d, EACCES);
5932 ADD_INT(d, ENOSPC);
5933 ADD_INT(d, ENOMEM);
5934 ADD_INT(d, EAGAIN);
5935 ADD_INT(d, EBUSY);
5936 ADD_INT(d, EEXIST);
5937 ADD_INT(d, ENOENT);
5938 ADD_INT(d, EPERM);
5939
Barry Warsaw1baa9822003-03-31 19:51:29 +00005940#if (DBVER >= 40)
5941 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5942 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5943#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005944
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005945 /* The exception name must be correct for pickled exception *
5946 * objects to unpickle properly. */
5947#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5948#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5949#else
5950#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5951#endif
5952
5953 /* All the rest of the exceptions derive only from DBError */
5954#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5955 PyDict_SetItemString(d, #name, name)
5956
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005957 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005958 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5959 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005960
Gregory P. Smithe9477062005-06-04 06:46:59 +00005961 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5962 * from both DBError and KeyError, since the API only supports
5963 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005964 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005965 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5966 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005967 Py_file_input, d, d);
5968 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005969 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005970 PyDict_DelItemString(d, "KeyError");
5971
5972
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005973#if !INCOMPLETE_IS_WARNING
5974 MAKE_EX(DBIncompleteError);
5975#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005976 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005977 MAKE_EX(DBKeyEmptyError);
5978 MAKE_EX(DBKeyExistError);
5979 MAKE_EX(DBLockDeadlockError);
5980 MAKE_EX(DBLockNotGrantedError);
5981 MAKE_EX(DBOldVersionError);
5982 MAKE_EX(DBRunRecoveryError);
5983 MAKE_EX(DBVerifyBadError);
5984 MAKE_EX(DBNoServerError);
5985 MAKE_EX(DBNoServerHomeError);
5986 MAKE_EX(DBNoServerIDError);
5987#if (DBVER >= 33)
5988 MAKE_EX(DBPageNotFoundError);
5989 MAKE_EX(DBSecondaryBadError);
5990#endif
5991
5992 MAKE_EX(DBInvalidArgError);
5993 MAKE_EX(DBAccessError);
5994 MAKE_EX(DBNoSpaceError);
5995 MAKE_EX(DBNoMemoryError);
5996 MAKE_EX(DBAgainError);
5997 MAKE_EX(DBBusyError);
5998 MAKE_EX(DBFileExistsError);
5999 MAKE_EX(DBNoSuchFileError);
6000 MAKE_EX(DBPermissionsError);
6001
6002#undef MAKE_EX
6003
6004 /* Check for errors */
6005 if (PyErr_Occurred()) {
6006 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006007 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006008 }
6009}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006010
6011/* allow this module to be named _pybsddb so that it can be installed
6012 * and imported on top of python >= 2.3 that includes its own older
6013 * copy of the library named _bsddb without importing the old version. */
6014DL_EXPORT(void) init_pybsddb(void)
6015{
6016 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6017 init_bsddb();
6018}