blob: 0822aa9886c730410475a47067d170a07d96f174 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith372b5832006-06-05 18:48:21 +0000101#define PY_BSDDB_VERSION "4.4.4"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
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;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002687 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 int flags = 0;
2689 void* sp;
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. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002700 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002701 }
2702
2703 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002704redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002705#if (DBVER >= 43)
2706 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2707#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002708 err = self->db->stat(self->db, &sp, flags);
2709#else
2710 err = self->db->stat(self->db, &sp, NULL, flags);
2711#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002712
2713 /* All the stat structures have matching fields upto the ndata field,
2714 so we can use any of them for the type cast */
2715 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2716
2717 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2718 * redo a full stat to make sure.
2719 * Fixes SF python bug 1493322, pybsddb bug 1184012
2720 */
2721 if (size == 0 && (flags & DB_FAST_STAT)) {
2722 flags = 0;
2723 goto redo_stat_for_length;
2724 }
2725
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002726 MYDB_END_ALLOW_THREADS;
2727
2728 if (err)
2729 return -1;
2730
2731 self->haveStat = 1;
2732
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002733 free(sp);
2734 return size;
2735}
2736
2737
2738PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2739{
2740 int err;
2741 PyObject* retval;
2742 DBT key;
2743 DBT data;
2744
2745 CHECK_DB_NOT_CLOSED(self);
2746 if (!make_key_dbt(self, keyobj, &key, NULL))
2747 return NULL;
2748
2749 CLEAR_DBT(data);
2750 if (CHECK_DBFLAG(self, DB_THREAD)) {
2751 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2752 data.flags = DB_DBT_MALLOC;
2753 }
2754 MYDB_BEGIN_ALLOW_THREADS;
2755 err = self->db->get(self->db, NULL, &key, &data, 0);
2756 MYDB_END_ALLOW_THREADS;
2757 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2758 PyErr_SetObject(PyExc_KeyError, keyobj);
2759 retval = NULL;
2760 }
2761 else if (makeDBError(err)) {
2762 retval = NULL;
2763 }
2764 else {
2765 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2766 FREE_DBT(data);
2767 }
2768
2769 FREE_DBT(key);
2770 return retval;
2771}
2772
2773
2774static int
2775DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2776{
2777 DBT key, data;
2778 int retval;
2779 int flags = 0;
2780
2781 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002782 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2783 PyErr_SetObject(DBError, t);
2784 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002785 return -1;
2786 }
2787
2788 if (!make_key_dbt(self, keyobj, &key, NULL))
2789 return -1;
2790
2791 if (dataobj != NULL) {
2792 if (!make_dbt(dataobj, &data))
2793 retval = -1;
2794 else {
2795 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002796 /* dictionaries shouldn't have duplicate keys */
2797 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002798 retval = _DB_put(self, NULL, &key, &data, flags);
2799
2800 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002801 /* try deleting any old record that matches and then PUT it
2802 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 _DB_delete(self, NULL, &key, 0);
2804 PyErr_Clear();
2805 retval = _DB_put(self, NULL, &key, &data, flags);
2806 }
2807 }
2808 }
2809 else {
2810 /* dataobj == NULL, so delete the key */
2811 retval = _DB_delete(self, NULL, &key, 0);
2812 }
2813 FREE_DBT(key);
2814 return retval;
2815}
2816
2817
2818static PyObject*
2819DB_has_key(DBObject* self, PyObject* args)
2820{
2821 int err;
2822 PyObject* keyobj;
2823 DBT key, data;
2824 PyObject* txnobj = NULL;
2825 DB_TXN *txn = NULL;
2826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002827 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002828 return NULL;
2829 CHECK_DB_NOT_CLOSED(self);
2830 if (!make_key_dbt(self, keyobj, &key, NULL))
2831 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002832 if (!checkTxnObj(txnobj, &txn)) {
2833 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002834 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002835 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002837 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838 it has a record but can't allocate a buffer for the data. This saves
2839 having to deal with data we won't be using.
2840 */
2841 CLEAR_DBT(data);
2842 data.flags = DB_DBT_USERMEM;
2843
2844 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002845 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 MYDB_END_ALLOW_THREADS;
2847 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002848
2849 if (err == DB_BUFFER_SMALL || err == 0) {
2850 return PyInt_FromLong(1);
2851 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2852 return PyInt_FromLong(0);
2853 }
2854
2855 makeDBError(err);
2856 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857}
2858
2859
2860#define _KEYS_LIST 1
2861#define _VALUES_LIST 2
2862#define _ITEMS_LIST 3
2863
2864static PyObject*
2865_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2866{
2867 int err, dbtype;
2868 DBT key;
2869 DBT data;
2870 DBC *cursor;
2871 PyObject* list;
2872 PyObject* item = NULL;
2873
2874 CHECK_DB_NOT_CLOSED(self);
2875 CLEAR_DBT(key);
2876 CLEAR_DBT(data);
2877
2878 dbtype = _DB_get_type(self);
2879 if (dbtype == -1)
2880 return NULL;
2881
2882 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002883 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002884 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002885
2886 /* get a cursor */
2887 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002888 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002889 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002890 if (makeDBError(err)) {
2891 Py_DECREF(list);
2892 return NULL;
2893 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894
2895 if (CHECK_DBFLAG(self, DB_THREAD)) {
2896 key.flags = DB_DBT_REALLOC;
2897 data.flags = DB_DBT_REALLOC;
2898 }
2899
2900 while (1) { /* use the cursor to traverse the DB, collecting items */
2901 MYDB_BEGIN_ALLOW_THREADS;
2902 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2903 MYDB_END_ALLOW_THREADS;
2904
2905 if (err) {
2906 /* for any error, break out of the loop */
2907 break;
2908 }
2909
2910 switch (type) {
2911 case _KEYS_LIST:
2912 switch(dbtype) {
2913 case DB_BTREE:
2914 case DB_HASH:
2915 default:
2916 item = PyString_FromStringAndSize((char*)key.data, key.size);
2917 break;
2918 case DB_RECNO:
2919 case DB_QUEUE:
2920 item = PyInt_FromLong(*((db_recno_t*)key.data));
2921 break;
2922 }
2923 break;
2924
2925 case _VALUES_LIST:
2926 item = PyString_FromStringAndSize((char*)data.data, data.size);
2927 break;
2928
2929 case _ITEMS_LIST:
2930 switch(dbtype) {
2931 case DB_BTREE:
2932 case DB_HASH:
2933 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002934 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2935 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002936 break;
2937 case DB_RECNO:
2938 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002939 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2940 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002941 break;
2942 }
2943 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002944 default:
2945 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2946 item = NULL;
2947 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002948 }
2949 if (item == NULL) {
2950 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002951 list = NULL;
2952 goto done;
2953 }
2954 PyList_Append(list, item);
2955 Py_DECREF(item);
2956 }
2957
Gregory P. Smithe9477062005-06-04 06:46:59 +00002958 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2959 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 Py_DECREF(list);
2961 list = NULL;
2962 }
2963
2964 done:
2965 FREE_DBT(key);
2966 FREE_DBT(data);
2967 MYDB_BEGIN_ALLOW_THREADS;
2968 cursor->c_close(cursor);
2969 MYDB_END_ALLOW_THREADS;
2970 return list;
2971}
2972
2973
2974static PyObject*
2975DB_keys(DBObject* self, PyObject* args)
2976{
2977 PyObject* txnobj = NULL;
2978 DB_TXN *txn = NULL;
2979
Georg Brandl96a8c392006-05-29 21:04:52 +00002980 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002981 return NULL;
2982 if (!checkTxnObj(txnobj, &txn))
2983 return NULL;
2984 return _DB_make_list(self, txn, _KEYS_LIST);
2985}
2986
2987
2988static PyObject*
2989DB_items(DBObject* self, PyObject* args)
2990{
2991 PyObject* txnobj = NULL;
2992 DB_TXN *txn = NULL;
2993
Georg Brandl96a8c392006-05-29 21:04:52 +00002994 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002995 return NULL;
2996 if (!checkTxnObj(txnobj, &txn))
2997 return NULL;
2998 return _DB_make_list(self, txn, _ITEMS_LIST);
2999}
3000
3001
3002static PyObject*
3003DB_values(DBObject* self, PyObject* args)
3004{
3005 PyObject* txnobj = NULL;
3006 DB_TXN *txn = NULL;
3007
Georg Brandl96a8c392006-05-29 21:04:52 +00003008 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003009 return NULL;
3010 if (!checkTxnObj(txnobj, &txn))
3011 return NULL;
3012 return _DB_make_list(self, txn, _VALUES_LIST);
3013}
3014
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015/* --------------------------------------------------------------------- */
3016/* DBCursor methods */
3017
3018
3019static PyObject*
3020DBC_close(DBCursorObject* self, PyObject* args)
3021{
3022 int err = 0;
3023
3024 if (!PyArg_ParseTuple(args, ":close"))
3025 return NULL;
3026
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003027 if (self->dbc != NULL) {
3028 MYDB_BEGIN_ALLOW_THREADS;
3029 err = self->dbc->c_close(self->dbc);
3030 self->dbc = NULL;
3031 MYDB_END_ALLOW_THREADS;
3032 }
3033 RETURN_IF_ERR();
3034 RETURN_NONE();
3035}
3036
3037
3038static PyObject*
3039DBC_count(DBCursorObject* self, PyObject* args)
3040{
3041 int err = 0;
3042 db_recno_t count;
3043 int flags = 0;
3044
3045 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3046 return NULL;
3047
3048 CHECK_CURSOR_NOT_CLOSED(self);
3049
3050 MYDB_BEGIN_ALLOW_THREADS;
3051 err = self->dbc->c_count(self->dbc, &count, flags);
3052 MYDB_END_ALLOW_THREADS;
3053 RETURN_IF_ERR();
3054
3055 return PyInt_FromLong(count);
3056}
3057
3058
3059static PyObject*
3060DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3061{
3062 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3063}
3064
3065
3066static PyObject*
3067DBC_delete(DBCursorObject* self, PyObject* args)
3068{
3069 int err, flags=0;
3070
3071 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3072 return NULL;
3073
3074 CHECK_CURSOR_NOT_CLOSED(self);
3075
3076 MYDB_BEGIN_ALLOW_THREADS;
3077 err = self->dbc->c_del(self->dbc, flags);
3078 MYDB_END_ALLOW_THREADS;
3079 RETURN_IF_ERR();
3080
3081 self->mydb->haveStat = 0;
3082 RETURN_NONE();
3083}
3084
3085
3086static PyObject*
3087DBC_dup(DBCursorObject* self, PyObject* args)
3088{
3089 int err, flags =0;
3090 DBC* dbc = NULL;
3091
3092 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3093 return NULL;
3094
3095 CHECK_CURSOR_NOT_CLOSED(self);
3096
3097 MYDB_BEGIN_ALLOW_THREADS;
3098 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3099 MYDB_END_ALLOW_THREADS;
3100 RETURN_IF_ERR();
3101
3102 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3103}
3104
3105static PyObject*
3106DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3107{
3108 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3109}
3110
3111
3112static PyObject*
3113DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3114{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003115 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003116 PyObject* keyobj = NULL;
3117 PyObject* dataobj = NULL;
3118 PyObject* retval = NULL;
3119 int dlen = -1;
3120 int doff = -1;
3121 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003122 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003123 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003124
3125 CLEAR_DBT(key);
3126 CLEAR_DBT(data);
3127 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003128 &flags, &dlen, &doff))
3129 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003130 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003131 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3132 &kwnames[1],
3133 &keyobj, &flags, &dlen, &doff))
3134 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003135 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3137 kwnames, &keyobj, &dataobj,
3138 &flags, &dlen, &doff))
3139 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003140 return NULL;
3141 }
3142 }
3143 }
3144
3145 CHECK_CURSOR_NOT_CLOSED(self);
3146
3147 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3148 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003149 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3150 (!add_partial_dbt(&data, dlen, doff)) )
3151 {
3152 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003153 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003154 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003155
3156 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3157 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003158 if (!(key.flags & DB_DBT_REALLOC)) {
3159 key.flags |= DB_DBT_MALLOC;
3160 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003161 }
3162
3163 MYDB_BEGIN_ALLOW_THREADS;
3164 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3165 MYDB_END_ALLOW_THREADS;
3166
Gregory P. Smithe9477062005-06-04 06:46:59 +00003167 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3168 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169 Py_INCREF(Py_None);
3170 retval = Py_None;
3171 }
3172 else if (makeDBError(err)) {
3173 retval = NULL;
3174 }
3175 else {
3176 switch (_DB_get_type(self->mydb)) {
3177 case -1:
3178 retval = NULL;
3179 break;
3180 case DB_BTREE:
3181 case DB_HASH:
3182 default:
3183 retval = Py_BuildValue("s#s#", key.data, key.size,
3184 data.data, data.size);
3185 break;
3186 case DB_RECNO:
3187 case DB_QUEUE:
3188 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3189 data.data, data.size);
3190 break;
3191 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003192 FREE_DBT(data);
3193 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003194 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003195 return retval;
3196}
3197
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003198#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003199static PyObject*
3200DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3201{
3202 int err, flags=0;
3203 PyObject* keyobj = NULL;
3204 PyObject* dataobj = NULL;
3205 PyObject* retval = NULL;
3206 int dlen = -1;
3207 int doff = -1;
3208 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003209 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3210 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003211
3212 CLEAR_DBT(key);
3213 CLEAR_DBT(data);
3214 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3215 &flags, &dlen, &doff))
3216 {
3217 PyErr_Clear();
3218 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003219 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003220 &keyobj, &flags, &dlen, &doff))
3221 {
3222 PyErr_Clear();
3223 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3224 kwnames, &keyobj, &dataobj,
3225 &flags, &dlen, &doff))
3226 {
3227 return NULL;
3228 }
3229 }
3230 }
3231
3232 CHECK_CURSOR_NOT_CLOSED(self);
3233
3234 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3235 return NULL;
3236 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3237 (!add_partial_dbt(&data, dlen, doff)) ) {
3238 FREE_DBT(key);
3239 return NULL;
3240 }
3241
3242 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3243 data.flags = DB_DBT_MALLOC;
3244 if (!(key.flags & DB_DBT_REALLOC)) {
3245 key.flags |= DB_DBT_MALLOC;
3246 }
3247 }
3248
3249 CLEAR_DBT(pkey);
3250 pkey.flags = DB_DBT_MALLOC;
3251
3252 MYDB_BEGIN_ALLOW_THREADS;
3253 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3254 MYDB_END_ALLOW_THREADS;
3255
Gregory P. Smithe9477062005-06-04 06:46:59 +00003256 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3257 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003258 Py_INCREF(Py_None);
3259 retval = Py_None;
3260 }
3261 else if (makeDBError(err)) {
3262 retval = NULL;
3263 }
3264 else {
3265 PyObject *pkeyObj;
3266 PyObject *dataObj;
3267 dataObj = PyString_FromStringAndSize(data.data, data.size);
3268
3269 if (self->mydb->primaryDBType == DB_RECNO ||
3270 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003271 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003272 else
3273 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3274
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003275 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003276 {
3277 PyObject *keyObj;
3278 int type = _DB_get_type(self->mydb);
3279 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003280 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003281 else
3282 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003283#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003284 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003285#else
3286 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3287#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003288 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003289 FREE_DBT(key);
3290 }
3291 else /* return just the pkey and data */
3292 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003293#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003294 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003295#else
3296 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3297#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003298 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003299 Py_DECREF(dataObj);
3300 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003301 FREE_DBT(pkey);
3302 FREE_DBT(data);
3303 }
3304 /* the only time REALLOC should be set is if we used an integer
3305 * key that make_key_dbt malloc'd for us. always free these. */
3306 if (key.flags & DB_DBT_REALLOC) {
3307 FREE_DBT(key);
3308 }
3309 return retval;
3310}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003311#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003312
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003313
3314static PyObject*
3315DBC_get_recno(DBCursorObject* self, PyObject* args)
3316{
3317 int err;
3318 db_recno_t recno;
3319 DBT key;
3320 DBT data;
3321
3322 if (!PyArg_ParseTuple(args, ":get_recno"))
3323 return NULL;
3324
3325 CHECK_CURSOR_NOT_CLOSED(self);
3326
3327 CLEAR_DBT(key);
3328 CLEAR_DBT(data);
3329 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3330 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3331 data.flags = DB_DBT_MALLOC;
3332 key.flags = DB_DBT_MALLOC;
3333 }
3334
3335 MYDB_BEGIN_ALLOW_THREADS;
3336 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3337 MYDB_END_ALLOW_THREADS;
3338 RETURN_IF_ERR();
3339
3340 recno = *((db_recno_t*)data.data);
3341 FREE_DBT(key);
3342 FREE_DBT(data);
3343 return PyInt_FromLong(recno);
3344}
3345
3346
3347static PyObject*
3348DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3349{
3350 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3351}
3352
3353
3354static PyObject*
3355DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3356{
3357 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3358}
3359
3360
3361static PyObject*
3362DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3363{
3364 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3365}
3366
3367
3368static PyObject*
3369DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3370{
3371 int err, flags = 0;
3372 PyObject* keyobj, *dataobj;
3373 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003374 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003375 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003376 int dlen = -1;
3377 int doff = -1;
3378
3379 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3380 &keyobj, &dataobj, &flags, &dlen, &doff))
3381 return NULL;
3382
3383 CHECK_CURSOR_NOT_CLOSED(self);
3384
3385 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3386 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003387 if (!make_dbt(dataobj, &data) ||
3388 !add_partial_dbt(&data, dlen, doff) )
3389 {
3390 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003392 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393
3394 MYDB_BEGIN_ALLOW_THREADS;
3395 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3396 MYDB_END_ALLOW_THREADS;
3397 FREE_DBT(key);
3398 RETURN_IF_ERR();
3399 self->mydb->haveStat = 0;
3400 RETURN_NONE();
3401}
3402
3403
3404static PyObject*
3405DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3406{
3407 int err, flags = 0;
3408 DBT key, data;
3409 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003410 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003411 int dlen = -1;
3412 int doff = -1;
3413
3414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3415 &keyobj, &flags, &dlen, &doff))
3416 return NULL;
3417
3418 CHECK_CURSOR_NOT_CLOSED(self);
3419
3420 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3421 return NULL;
3422
3423 CLEAR_DBT(data);
3424 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3425 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3426 data.flags = DB_DBT_MALLOC;
3427 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003428 if (!add_partial_dbt(&data, dlen, doff)) {
3429 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003430 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003431 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003432
3433 MYDB_BEGIN_ALLOW_THREADS;
3434 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3435 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003436 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3437 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003438 Py_INCREF(Py_None);
3439 retval = Py_None;
3440 }
3441 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 retval = NULL;
3443 }
3444 else {
3445 switch (_DB_get_type(self->mydb)) {
3446 case -1:
3447 retval = NULL;
3448 break;
3449 case DB_BTREE:
3450 case DB_HASH:
3451 default:
3452 retval = Py_BuildValue("s#s#", key.data, key.size,
3453 data.data, data.size);
3454 break;
3455 case DB_RECNO:
3456 case DB_QUEUE:
3457 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3458 data.data, data.size);
3459 break;
3460 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003461 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003462 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003463 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003464 /* the only time REALLOC should be set is if we used an integer
3465 * key that make_key_dbt malloc'd for us. always free these. */
3466 if (key.flags & DB_DBT_REALLOC) {
3467 FREE_DBT(key);
3468 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003469
3470 return retval;
3471}
3472
3473
3474static PyObject*
3475DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3476{
3477 int err, flags = 0;
3478 DBT key, data;
3479 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003480 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 int dlen = -1;
3482 int doff = -1;
3483
3484 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3485 &keyobj, &flags, &dlen, &doff))
3486 return NULL;
3487
3488 CHECK_CURSOR_NOT_CLOSED(self);
3489
3490 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3491 return NULL;
3492
3493 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003494 if (!add_partial_dbt(&data, dlen, doff)) {
3495 FREE_DBT(key);
3496 return NULL;
3497 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003498 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3499 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003500 data.flags |= DB_DBT_MALLOC;
3501 /* only BTREE databases will return anything in the key */
3502 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3503 key.flags |= DB_DBT_MALLOC;
3504 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003506 MYDB_BEGIN_ALLOW_THREADS;
3507 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3508 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003509 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3510 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003511 Py_INCREF(Py_None);
3512 retval = Py_None;
3513 }
3514 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003515 retval = NULL;
3516 }
3517 else {
3518 switch (_DB_get_type(self->mydb)) {
3519 case -1:
3520 retval = NULL;
3521 break;
3522 case DB_BTREE:
3523 case DB_HASH:
3524 default:
3525 retval = Py_BuildValue("s#s#", key.data, key.size,
3526 data.data, data.size);
3527 break;
3528 case DB_RECNO:
3529 case DB_QUEUE:
3530 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3531 data.data, data.size);
3532 break;
3533 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003534 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 FREE_DBT(data);
3536 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003537 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003538 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003539 if (key.flags & DB_DBT_REALLOC) {
3540 FREE_DBT(key);
3541 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003542
3543 return retval;
3544}
3545
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003546static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003547_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3548 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003550 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003551 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003552 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003553
Gregory P. Smith7441e652003-11-03 21:35:31 +00003554 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003555 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3556 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003557 if (!make_dbt(dataobj, &data)) {
3558 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003559 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003560 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003561
3562 MYDB_BEGIN_ALLOW_THREADS;
3563 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3564 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003565 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003566 Py_INCREF(Py_None);
3567 retval = Py_None;
3568 }
3569 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570 retval = NULL;
3571 }
3572 else {
3573 switch (_DB_get_type(self->mydb)) {
3574 case -1:
3575 retval = NULL;
3576 break;
3577 case DB_BTREE:
3578 case DB_HASH:
3579 default:
3580 retval = Py_BuildValue("s#s#", key.data, key.size,
3581 data.data, data.size);
3582 break;
3583 case DB_RECNO:
3584 case DB_QUEUE:
3585 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3586 data.data, data.size);
3587 break;
3588 }
3589 }
3590
3591 FREE_DBT(key);
3592 return retval;
3593}
3594
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003595static PyObject*
3596DBC_get_both(DBCursorObject* self, PyObject* args)
3597{
3598 int flags=0;
3599 PyObject *keyobj, *dataobj;
3600
3601 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3602 return NULL;
3603
Gregory P. Smith7441e652003-11-03 21:35:31 +00003604 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003605 CHECK_CURSOR_NOT_CLOSED(self);
3606
3607 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3608 self->mydb->moduleFlags.getReturnsNone);
3609}
3610
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003611/* Return size of entry */
3612static PyObject*
3613DBC_get_current_size(DBCursorObject* self, PyObject* args)
3614{
3615 int err, flags=DB_CURRENT;
3616 PyObject* retval = NULL;
3617 DBT key, data;
3618
3619 if (!PyArg_ParseTuple(args, ":get_current_size"))
3620 return NULL;
3621 CHECK_CURSOR_NOT_CLOSED(self);
3622 CLEAR_DBT(key);
3623 CLEAR_DBT(data);
3624
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003625 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003626 getting the record size. */
3627 data.flags = DB_DBT_USERMEM;
3628 data.ulen = 0;
3629 MYDB_BEGIN_ALLOW_THREADS;
3630 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3631 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003632 if (err == DB_BUFFER_SMALL || !err) {
3633 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003634 retval = PyInt_FromLong((long)data.size);
3635 err = 0;
3636 }
3637
3638 FREE_DBT(key);
3639 FREE_DBT(data);
3640 RETURN_IF_ERR();
3641 return retval;
3642}
3643
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003644static PyObject*
3645DBC_set_both(DBCursorObject* self, PyObject* args)
3646{
3647 int flags=0;
3648 PyObject *keyobj, *dataobj;
3649
3650 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3651 return NULL;
3652
Gregory P. Smith7441e652003-11-03 21:35:31 +00003653 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003654 CHECK_CURSOR_NOT_CLOSED(self);
3655
3656 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3657 self->mydb->moduleFlags.cursorSetReturnsNone);
3658}
3659
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003660
3661static PyObject*
3662DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3663{
3664 int err, irecno, flags=0;
3665 db_recno_t recno;
3666 DBT key, data;
3667 PyObject* retval;
3668 int dlen = -1;
3669 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003670 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003671
3672 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3673 &irecno, &flags, &dlen, &doff))
3674 return NULL;
3675
3676 CHECK_CURSOR_NOT_CLOSED(self);
3677
3678 CLEAR_DBT(key);
3679 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003680 /* use allocated space so DB will be able to realloc room for the real
3681 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 key.data = malloc(sizeof(db_recno_t));
3683 if (key.data == NULL) {
3684 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3685 return NULL;
3686 }
3687 key.size = sizeof(db_recno_t);
3688 key.ulen = key.size;
3689 memcpy(key.data, &recno, sizeof(db_recno_t));
3690 key.flags = DB_DBT_REALLOC;
3691
3692 CLEAR_DBT(data);
3693 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3694 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3695 data.flags = DB_DBT_MALLOC;
3696 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003697 if (!add_partial_dbt(&data, dlen, doff)) {
3698 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003700 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701
3702 MYDB_BEGIN_ALLOW_THREADS;
3703 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3704 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003705 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3706 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003707 Py_INCREF(Py_None);
3708 retval = Py_None;
3709 }
3710 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003711 retval = NULL;
3712 }
3713 else { /* Can only be used for BTrees, so no need to return int key */
3714 retval = Py_BuildValue("s#s#", key.data, key.size,
3715 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 FREE_DBT(data);
3717 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003718 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719
3720 return retval;
3721}
3722
3723
3724static PyObject*
3725DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3726{
3727 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3728}
3729
3730
3731static PyObject*
3732DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3733{
3734 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3735}
3736
3737
3738static PyObject*
3739DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3740{
3741 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3742}
3743
3744
3745static PyObject*
3746DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3747{
3748 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3749}
3750
3751
3752static PyObject*
3753DBC_join_item(DBCursorObject* self, PyObject* args)
3754{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003755 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003756 DBT key, data;
3757 PyObject* retval;
3758
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003759 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003760 return NULL;
3761
3762 CHECK_CURSOR_NOT_CLOSED(self);
3763
3764 CLEAR_DBT(key);
3765 CLEAR_DBT(data);
3766 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3768 key.flags = DB_DBT_MALLOC;
3769 }
3770
3771 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003772 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003773 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003774 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3775 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003776 Py_INCREF(Py_None);
3777 retval = Py_None;
3778 }
3779 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003780 retval = NULL;
3781 }
3782 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003783 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003784 FREE_DBT(key);
3785 }
3786
3787 return retval;
3788}
3789
3790
3791
3792/* --------------------------------------------------------------------- */
3793/* DBEnv methods */
3794
3795
3796static PyObject*
3797DBEnv_close(DBEnvObject* self, PyObject* args)
3798{
3799 int err, flags = 0;
3800
3801 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3802 return NULL;
3803 if (!self->closed) { /* Don't close more than once */
3804 MYDB_BEGIN_ALLOW_THREADS;
3805 err = self->db_env->close(self->db_env, flags);
3806 MYDB_END_ALLOW_THREADS;
3807 /* after calling DBEnv->close, regardless of error, this DBEnv
3808 * may not be accessed again (BerkeleyDB docs). */
3809 self->closed = 1;
3810 self->db_env = NULL;
3811 RETURN_IF_ERR();
3812 }
3813 RETURN_NONE();
3814}
3815
3816
3817static PyObject*
3818DBEnv_open(DBEnvObject* self, PyObject* args)
3819{
3820 int err, flags=0, mode=0660;
3821 char *db_home;
3822
3823 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3824 return NULL;
3825
3826 CHECK_ENV_NOT_CLOSED(self);
3827
3828 MYDB_BEGIN_ALLOW_THREADS;
3829 err = self->db_env->open(self->db_env, db_home, flags, mode);
3830 MYDB_END_ALLOW_THREADS;
3831 RETURN_IF_ERR();
3832 self->closed = 0;
3833 self->flags = flags;
3834 RETURN_NONE();
3835}
3836
3837
3838static PyObject*
3839DBEnv_remove(DBEnvObject* self, PyObject* args)
3840{
3841 int err, flags=0;
3842 char *db_home;
3843
3844 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3845 return NULL;
3846 CHECK_ENV_NOT_CLOSED(self);
3847 MYDB_BEGIN_ALLOW_THREADS;
3848 err = self->db_env->remove(self->db_env, db_home, flags);
3849 MYDB_END_ALLOW_THREADS;
3850 RETURN_IF_ERR();
3851 RETURN_NONE();
3852}
3853
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003854#if (DBVER >= 41)
3855static PyObject*
3856DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3857{
3858 int err;
3859 u_int32_t flags=0;
3860 char *file = NULL;
3861 char *database = NULL;
3862 PyObject *txnobj = NULL;
3863 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003864 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003865 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003866
3867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3868 &file, &database, &txnobj, &flags)) {
3869 return NULL;
3870 }
3871 if (!checkTxnObj(txnobj, &txn)) {
3872 return NULL;
3873 }
3874 CHECK_ENV_NOT_CLOSED(self);
3875 MYDB_BEGIN_ALLOW_THREADS;
3876 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3877 MYDB_END_ALLOW_THREADS;
3878 RETURN_IF_ERR();
3879 RETURN_NONE();
3880}
3881
3882static PyObject*
3883DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3884{
3885 int err;
3886 u_int32_t flags=0;
3887 char *file = NULL;
3888 char *database = NULL;
3889 char *newname = NULL;
3890 PyObject *txnobj = NULL;
3891 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003892 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003893 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003894
3895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3896 &file, &database, &newname, &txnobj, &flags)) {
3897 return NULL;
3898 }
3899 if (!checkTxnObj(txnobj, &txn)) {
3900 return NULL;
3901 }
3902 CHECK_ENV_NOT_CLOSED(self);
3903 MYDB_BEGIN_ALLOW_THREADS;
3904 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3905 flags);
3906 MYDB_END_ALLOW_THREADS;
3907 RETURN_IF_ERR();
3908 RETURN_NONE();
3909}
3910
3911static PyObject*
3912DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3913{
3914 int err;
3915 u_int32_t flags=0;
3916 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003917 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003918
3919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3920 &passwd, &flags)) {
3921 return NULL;
3922 }
3923
3924 MYDB_BEGIN_ALLOW_THREADS;
3925 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3926 MYDB_END_ALLOW_THREADS;
3927
3928 RETURN_IF_ERR();
3929 RETURN_NONE();
3930}
3931#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003932
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003933#if (DBVER >= 40)
3934static PyObject*
3935DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3936{
3937 int err;
3938 u_int32_t flags=0;
3939 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003940 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003941
3942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3943 &timeout, &flags)) {
3944 return NULL;
3945 }
3946
3947 MYDB_BEGIN_ALLOW_THREADS;
3948 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3949 MYDB_END_ALLOW_THREADS;
3950
3951 RETURN_IF_ERR();
3952 RETURN_NONE();
3953}
3954#endif /* DBVER >= 40 */
3955
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003956static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003957DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3958{
3959 int err;
3960 long shm_key = 0;
3961
3962 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3963 return NULL;
3964 CHECK_ENV_NOT_CLOSED(self);
3965
3966 err = self->db_env->set_shm_key(self->db_env, shm_key);
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3969}
3970
3971static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003972DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3973{
3974 int err, gbytes=0, bytes=0, ncache=0;
3975
3976 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3977 &gbytes, &bytes, &ncache))
3978 return NULL;
3979 CHECK_ENV_NOT_CLOSED(self);
3980
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3983 MYDB_END_ALLOW_THREADS;
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3986}
3987
3988
3989#if (DBVER >= 32)
3990static PyObject*
3991DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3992{
3993 int err, flags=0, onoff=0;
3994
3995 if (!PyArg_ParseTuple(args, "ii:set_flags",
3996 &flags, &onoff))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
3999
4000 MYDB_BEGIN_ALLOW_THREADS;
4001 err = self->db_env->set_flags(self->db_env, flags, onoff);
4002 MYDB_END_ALLOW_THREADS;
4003 RETURN_IF_ERR();
4004 RETURN_NONE();
4005}
4006#endif
4007
4008
4009static PyObject*
4010DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4011{
4012 int err;
4013 char *dir;
4014
4015 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4016 return NULL;
4017 CHECK_ENV_NOT_CLOSED(self);
4018
4019 MYDB_BEGIN_ALLOW_THREADS;
4020 err = self->db_env->set_data_dir(self->db_env, dir);
4021 MYDB_END_ALLOW_THREADS;
4022 RETURN_IF_ERR();
4023 RETURN_NONE();
4024}
4025
4026
4027static PyObject*
4028DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4029{
4030 int err, lg_bsize;
4031
4032 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4033 return NULL;
4034 CHECK_ENV_NOT_CLOSED(self);
4035
4036 MYDB_BEGIN_ALLOW_THREADS;
4037 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4041}
4042
4043
4044static PyObject*
4045DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4046{
4047 int err;
4048 char *dir;
4049
4050 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_lg_dir(self->db_env, dir);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061static PyObject*
4062DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4063{
4064 int err, lg_max;
4065
4066 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4069
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_max(self->db_env, lg_max);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4075}
4076
4077
Neal Norwitz84562352005-10-20 04:30:15 +00004078#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004079static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004080DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4081{
4082 int err, lg_max;
4083
4084 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
Neal Norwitz84562352005-10-20 04:30:15 +00004094#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004095
4096
4097static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004098DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4099{
4100 int err, lk_detect;
4101
4102 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112
4113
4114static PyObject*
4115DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4116{
4117 int err, max;
4118
4119 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lk_max(self->db_env, max);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
4129
4130
4131#if (DBVER >= 32)
4132
4133static PyObject*
4134DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4135{
4136 int err, max;
4137
4138 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4139 return NULL;
4140 CHECK_ENV_NOT_CLOSED(self);
4141
4142 MYDB_BEGIN_ALLOW_THREADS;
4143 err = self->db_env->set_lk_max_locks(self->db_env, max);
4144 MYDB_END_ALLOW_THREADS;
4145 RETURN_IF_ERR();
4146 RETURN_NONE();
4147}
4148
4149
4150static PyObject*
4151DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4152{
4153 int err, max;
4154
4155 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4164}
4165
4166
4167static PyObject*
4168DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4169{
4170 int err, max;
4171
4172 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4173 return NULL;
4174 CHECK_ENV_NOT_CLOSED(self);
4175
4176 MYDB_BEGIN_ALLOW_THREADS;
4177 err = self->db_env->set_lk_max_objects(self->db_env, max);
4178 MYDB_END_ALLOW_THREADS;
4179 RETURN_IF_ERR();
4180 RETURN_NONE();
4181}
4182
4183#endif
4184
4185
4186static PyObject*
4187DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4188{
4189 int err, mp_mmapsize;
4190
4191 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4194
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
4201
4202
4203static PyObject*
4204DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4205{
4206 int err;
4207 char *dir;
4208
4209 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_tmp_dir(self->db_env, dir);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
4220
4221static PyObject*
4222DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4223{
4224 int flags = 0;
4225 PyObject* txnobj = NULL;
4226 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004227 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004228
4229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4230 &txnobj, &flags))
4231 return NULL;
4232
4233 if (!checkTxnObj(txnobj, &txn))
4234 return NULL;
4235 CHECK_ENV_NOT_CLOSED(self);
4236
4237 return (PyObject*)newDBTxnObject(self, txn, flags);
4238}
4239
4240
4241static PyObject*
4242DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4243{
4244 int err, kbyte=0, min=0, flags=0;
4245
4246 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4247 return NULL;
4248 CHECK_ENV_NOT_CLOSED(self);
4249
4250 MYDB_BEGIN_ALLOW_THREADS;
4251#if (DBVER >= 40)
4252 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4253#else
4254 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4255#endif
4256 MYDB_END_ALLOW_THREADS;
4257 RETURN_IF_ERR();
4258 RETURN_NONE();
4259}
4260
4261
4262static PyObject*
4263DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4264{
4265 int err, max;
4266
4267 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4268 return NULL;
4269 CHECK_ENV_NOT_CLOSED(self);
4270
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004271 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004272 RETURN_IF_ERR();
4273 RETURN_NONE();
4274}
4275
4276
4277static PyObject*
4278DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4279{
4280 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004281 long stamp;
4282 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004283
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004284 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004285 return NULL;
4286 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004287 timestamp = (time_t)stamp;
4288 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004289 RETURN_IF_ERR();
4290 RETURN_NONE();
4291}
4292
4293
4294static PyObject*
4295DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4296{
4297 int err, atype, flags=0;
4298 int aborted = 0;
4299
4300 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4301 return NULL;
4302 CHECK_ENV_NOT_CLOSED(self);
4303
4304 MYDB_BEGIN_ALLOW_THREADS;
4305#if (DBVER >= 40)
4306 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4307#else
4308 err = lock_detect(self->db_env, flags, atype, &aborted);
4309#endif
4310 MYDB_END_ALLOW_THREADS;
4311 RETURN_IF_ERR();
4312 return PyInt_FromLong(aborted);
4313}
4314
4315
4316static PyObject*
4317DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4318{
4319 int flags=0;
4320 int locker, lock_mode;
4321 DBT obj;
4322 PyObject* objobj;
4323
4324 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4325 return NULL;
4326
4327
4328 if (!make_dbt(objobj, &obj))
4329 return NULL;
4330
4331 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4332}
4333
4334
4335static PyObject*
4336DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4337{
4338 int err;
4339 u_int32_t theID;
4340
4341 if (!PyArg_ParseTuple(args, ":lock_id"))
4342 return NULL;
4343
4344 CHECK_ENV_NOT_CLOSED(self);
4345 MYDB_BEGIN_ALLOW_THREADS;
4346#if (DBVER >= 40)
4347 err = self->db_env->lock_id(self->db_env, &theID);
4348#else
4349 err = lock_id(self->db_env, &theID);
4350#endif
4351 MYDB_END_ALLOW_THREADS;
4352 RETURN_IF_ERR();
4353
4354 return PyInt_FromLong((long)theID);
4355}
4356
4357
4358static PyObject*
4359DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4360{
4361 int err;
4362 DBLockObject* dblockobj;
4363
4364 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4365 return NULL;
4366
4367 CHECK_ENV_NOT_CLOSED(self);
4368 MYDB_BEGIN_ALLOW_THREADS;
4369#if (DBVER >= 40)
4370 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4371#else
4372 err = lock_put(self->db_env, &dblockobj->lock);
4373#endif
4374 MYDB_END_ALLOW_THREADS;
4375 RETURN_IF_ERR();
4376 RETURN_NONE();
4377}
4378
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004379#if (DBVER >= 44)
4380static PyObject*
4381DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4382{
4383 int err;
4384 char *file;
4385 u_int32_t flags = 0;
4386 static char* kwnames[] = { "file", "flags", NULL};
4387
4388 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4389 &file, &flags))
4390 return NULL;
4391 CHECK_ENV_NOT_CLOSED(self);
4392
4393 MYDB_BEGIN_ALLOW_THREADS;
4394 err = self->db_env->lsn_reset(self->db_env, file, flags);
4395 MYDB_END_ALLOW_THREADS;
4396 RETURN_IF_ERR();
4397 RETURN_NONE();
4398}
4399#endif /* DBVER >= 4.4 */
4400
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004401#if (DBVER >= 40)
4402static PyObject*
4403DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4404{
4405 int err;
4406 DB_LOG_STAT* statp = NULL;
4407 PyObject* d = NULL;
4408 u_int32_t flags = 0;
4409
4410 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4411 return NULL;
4412 CHECK_ENV_NOT_CLOSED(self);
4413
4414 MYDB_BEGIN_ALLOW_THREADS;
4415 err = self->db_env->log_stat(self->db_env, &statp, flags);
4416 MYDB_END_ALLOW_THREADS;
4417 RETURN_IF_ERR();
4418
4419 /* Turn the stat structure into a dictionary */
4420 d = PyDict_New();
4421 if (d == NULL) {
4422 if (statp)
4423 free(statp);
4424 return NULL;
4425 }
4426
4427#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4428
4429 MAKE_ENTRY(magic);
4430 MAKE_ENTRY(version);
4431 MAKE_ENTRY(mode);
4432 MAKE_ENTRY(lg_bsize);
4433#if (DBVER >= 44)
4434 MAKE_ENTRY(lg_size);
4435 MAKE_ENTRY(record);
4436#endif
4437#if (DBVER <= 40)
4438 MAKE_ENTRY(lg_max);
4439#endif
4440 MAKE_ENTRY(w_mbytes);
4441 MAKE_ENTRY(w_bytes);
4442 MAKE_ENTRY(wc_mbytes);
4443 MAKE_ENTRY(wc_bytes);
4444 MAKE_ENTRY(wcount);
4445 MAKE_ENTRY(wcount_fill);
4446#if (DBVER >= 44)
4447 MAKE_ENTRY(rcount);
4448#endif
4449 MAKE_ENTRY(scount);
4450 MAKE_ENTRY(cur_file);
4451 MAKE_ENTRY(cur_offset);
4452 MAKE_ENTRY(disk_file);
4453 MAKE_ENTRY(disk_offset);
4454 MAKE_ENTRY(maxcommitperflush);
4455 MAKE_ENTRY(mincommitperflush);
4456 MAKE_ENTRY(regsize);
4457 MAKE_ENTRY(region_wait);
4458 MAKE_ENTRY(region_nowait);
4459
4460#undef MAKE_ENTRY
4461 free(statp);
4462 return d;
4463} /* DBEnv_log_stat */
4464#endif /* DBVER >= 4.0 for log_stat method */
4465
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004466
4467static PyObject*
4468DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4469{
4470 int err;
4471 DB_LOCK_STAT* sp;
4472 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004473 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004474
4475 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4476 return NULL;
4477 CHECK_ENV_NOT_CLOSED(self);
4478
4479 MYDB_BEGIN_ALLOW_THREADS;
4480#if (DBVER >= 40)
4481 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4482#else
4483#if (DBVER >= 33)
4484 err = lock_stat(self->db_env, &sp);
4485#else
4486 err = lock_stat(self->db_env, &sp, NULL);
4487#endif
4488#endif
4489 MYDB_END_ALLOW_THREADS;
4490 RETURN_IF_ERR();
4491
4492 /* Turn the stat structure into a dictionary */
4493 d = PyDict_New();
4494 if (d == NULL) {
4495 free(sp);
4496 return NULL;
4497 }
4498
4499#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4500
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004501#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004503#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004504 MAKE_ENTRY(nmodes);
4505#if (DBVER >= 32)
4506 MAKE_ENTRY(maxlocks);
4507 MAKE_ENTRY(maxlockers);
4508 MAKE_ENTRY(maxobjects);
4509 MAKE_ENTRY(nlocks);
4510 MAKE_ENTRY(maxnlocks);
4511#endif
4512 MAKE_ENTRY(nlockers);
4513 MAKE_ENTRY(maxnlockers);
4514#if (DBVER >= 32)
4515 MAKE_ENTRY(nobjects);
4516 MAKE_ENTRY(maxnobjects);
4517#endif
4518 MAKE_ENTRY(nrequests);
4519 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004520#if (DBVER < 44)
4521 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004523#else
4524 MAKE_ENTRY(lock_nowait);
4525 MAKE_ENTRY(lock_wait);
4526#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004527 MAKE_ENTRY(ndeadlocks);
4528 MAKE_ENTRY(regsize);
4529 MAKE_ENTRY(region_wait);
4530 MAKE_ENTRY(region_nowait);
4531
4532#undef MAKE_ENTRY
4533 free(sp);
4534 return d;
4535}
4536
4537
4538static PyObject*
4539DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4540{
4541 int flags=0;
4542 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004543 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004544 PyObject* list;
4545 PyObject* item = NULL;
4546
4547 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4548 return NULL;
4549
4550 CHECK_ENV_NOT_CLOSED(self);
4551 MYDB_BEGIN_ALLOW_THREADS;
4552#if (DBVER >= 40)
4553 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4554#elif (DBVER == 33)
4555 err = log_archive(self->db_env, &log_list, flags);
4556#else
4557 err = log_archive(self->db_env, &log_list, flags, NULL);
4558#endif
4559 MYDB_END_ALLOW_THREADS;
4560 RETURN_IF_ERR();
4561
Gregory P. Smithbad47452006-06-05 00:33:35 +00004562 list = PyList_New(0);
4563 if (list == NULL) {
4564 if (log_list)
4565 free(log_list);
4566 return NULL;
4567 }
4568
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004569 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004570 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004571 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4572 item = PyString_FromString (*log_list);
4573 if (item == NULL) {
4574 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004575 list = NULL;
4576 break;
4577 }
4578 PyList_Append(list, item);
4579 Py_DECREF(item);
4580 }
4581 free(log_list_start);
4582 }
4583 return list;
4584}
4585
4586
4587static PyObject*
4588DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4589{
4590 int err;
4591 DB_TXN_STAT* sp;
4592 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004593 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004594
4595 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4596 return NULL;
4597 CHECK_ENV_NOT_CLOSED(self);
4598
4599 MYDB_BEGIN_ALLOW_THREADS;
4600#if (DBVER >= 40)
4601 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4602#elif (DBVER == 33)
4603 err = txn_stat(self->db_env, &sp);
4604#else
4605 err = txn_stat(self->db_env, &sp, NULL);
4606#endif
4607 MYDB_END_ALLOW_THREADS;
4608 RETURN_IF_ERR();
4609
4610 /* Turn the stat structure into a dictionary */
4611 d = PyDict_New();
4612 if (d == NULL) {
4613 free(sp);
4614 return NULL;
4615 }
4616
4617#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4618
4619 MAKE_ENTRY(time_ckp);
4620 MAKE_ENTRY(last_txnid);
4621 MAKE_ENTRY(maxtxns);
4622 MAKE_ENTRY(nactive);
4623 MAKE_ENTRY(maxnactive);
4624 MAKE_ENTRY(nbegins);
4625 MAKE_ENTRY(naborts);
4626 MAKE_ENTRY(ncommits);
4627 MAKE_ENTRY(regsize);
4628 MAKE_ENTRY(region_wait);
4629 MAKE_ENTRY(region_nowait);
4630
4631#undef MAKE_ENTRY
4632 free(sp);
4633 return d;
4634}
4635
4636
4637static PyObject*
4638DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4639{
4640 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004641 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004642
4643 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4644 return NULL;
4645 CHECK_ENV_NOT_CLOSED(self);
4646
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004647 if (self->moduleFlags.getReturnsNone)
4648 ++oldValue;
4649 if (self->moduleFlags.cursorSetReturnsNone)
4650 ++oldValue;
4651 self->moduleFlags.getReturnsNone = (flags >= 1);
4652 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004653 return PyInt_FromLong(oldValue);
4654}
4655
4656
4657/* --------------------------------------------------------------------- */
4658/* DBTxn methods */
4659
4660
4661static PyObject*
4662DBTxn_commit(DBTxnObject* self, PyObject* args)
4663{
4664 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004665 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004666
4667 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4668 return NULL;
4669
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004670 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004671 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4672 "after txn_commit or txn_abort");
4673 PyErr_SetObject(DBError, t);
4674 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004675 return NULL;
4676 }
4677 txn = self->txn;
4678 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004679 MYDB_BEGIN_ALLOW_THREADS;
4680#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004681 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004683 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684#endif
4685 MYDB_END_ALLOW_THREADS;
4686 RETURN_IF_ERR();
4687 RETURN_NONE();
4688}
4689
4690static PyObject*
4691DBTxn_prepare(DBTxnObject* self, PyObject* args)
4692{
4693#if (DBVER >= 33)
4694 int err;
4695 char* gid=NULL;
4696 int gid_size=0;
4697
4698 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4699 return NULL;
4700
4701 if (gid_size != DB_XIDDATASIZE) {
4702 PyErr_SetString(PyExc_TypeError,
4703 "gid must be DB_XIDDATASIZE bytes long");
4704 return NULL;
4705 }
4706
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004707 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004708 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4709 "after txn_commit or txn_abort");
4710 PyErr_SetObject(DBError, t);
4711 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004712 return NULL;
4713 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004714 MYDB_BEGIN_ALLOW_THREADS;
4715#if (DBVER >= 40)
4716 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4717#else
4718 err = txn_prepare(self->txn, (u_int8_t*)gid);
4719#endif
4720 MYDB_END_ALLOW_THREADS;
4721 RETURN_IF_ERR();
4722 RETURN_NONE();
4723#else
4724 int err;
4725
4726 if (!PyArg_ParseTuple(args, ":prepare"))
4727 return NULL;
4728
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004729 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004730 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4731 "after txn_commit or txn_abort");
4732 PyErr_SetObject(DBError, t);
4733 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004734 return NULL;
4735 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004736 MYDB_BEGIN_ALLOW_THREADS;
4737 err = txn_prepare(self->txn);
4738 MYDB_END_ALLOW_THREADS;
4739 RETURN_IF_ERR();
4740 RETURN_NONE();
4741#endif
4742}
4743
4744
4745static PyObject*
4746DBTxn_abort(DBTxnObject* self, PyObject* args)
4747{
4748 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004749 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004750
4751 if (!PyArg_ParseTuple(args, ":abort"))
4752 return NULL;
4753
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004754 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004755 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4756 "after txn_commit or txn_abort");
4757 PyErr_SetObject(DBError, t);
4758 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004759 return NULL;
4760 }
4761 txn = self->txn;
4762 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004763 MYDB_BEGIN_ALLOW_THREADS;
4764#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004765 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004767 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004768#endif
4769 MYDB_END_ALLOW_THREADS;
4770 RETURN_IF_ERR();
4771 RETURN_NONE();
4772}
4773
4774
4775static PyObject*
4776DBTxn_id(DBTxnObject* self, PyObject* args)
4777{
4778 int id;
4779
4780 if (!PyArg_ParseTuple(args, ":id"))
4781 return NULL;
4782
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004783 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004784 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4785 "after txn_commit or txn_abort");
4786 PyErr_SetObject(DBError, t);
4787 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004788 return NULL;
4789 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004790 MYDB_BEGIN_ALLOW_THREADS;
4791#if (DBVER >= 40)
4792 id = self->txn->id(self->txn);
4793#else
4794 id = txn_id(self->txn);
4795#endif
4796 MYDB_END_ALLOW_THREADS;
4797 return PyInt_FromLong(id);
4798}
4799
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004800#if (DBVER >= 43)
4801/* --------------------------------------------------------------------- */
4802/* DBSequence methods */
4803
4804
4805static PyObject*
4806DBSequence_close(DBSequenceObject* self, PyObject* args)
4807{
4808 int err, flags=0;
4809 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4810 return NULL;
4811 CHECK_SEQUENCE_NOT_CLOSED(self)
4812
4813 MYDB_BEGIN_ALLOW_THREADS
4814 err = self->sequence->close(self->sequence, flags);
4815 self->sequence = NULL;
4816 MYDB_END_ALLOW_THREADS
4817
4818 RETURN_IF_ERR();
4819
4820 RETURN_NONE();
4821}
4822
4823static PyObject*
4824DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4825{
4826 int err, flags = 0;
4827 int delta = 1;
4828 db_seq_t value;
4829 PyObject *txnobj = NULL;
4830 DB_TXN *txn = NULL;
4831 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4832 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4833 return NULL;
4834 CHECK_SEQUENCE_NOT_CLOSED(self)
4835
4836 if (!checkTxnObj(txnobj, &txn))
4837 return NULL;
4838
4839 MYDB_BEGIN_ALLOW_THREADS
4840 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4841 MYDB_END_ALLOW_THREADS
4842
4843 RETURN_IF_ERR();
4844 return PyLong_FromLongLong(value);
4845
4846}
4847
4848static PyObject*
4849DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4850{
4851 if (!PyArg_ParseTuple(args,":get_dbp"))
4852 return NULL;
4853 CHECK_SEQUENCE_NOT_CLOSED(self)
4854 Py_INCREF(self->mydb);
4855 return (PyObject* )self->mydb;
4856}
4857
4858static PyObject*
4859DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4860{
4861 int err;
4862 DBT key;
4863 CHECK_SEQUENCE_NOT_CLOSED(self)
4864 MYDB_BEGIN_ALLOW_THREADS
4865 err = self->sequence->get_key(self->sequence, &key);
4866 MYDB_END_ALLOW_THREADS
4867
4868 RETURN_IF_ERR();
4869
4870 return PyString_FromStringAndSize(key.data, key.size);
4871}
4872
4873static PyObject*
4874DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4875{
4876 int err;
4877 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004878 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004879 return NULL;
4880 CHECK_SEQUENCE_NOT_CLOSED(self)
4881
4882 MYDB_BEGIN_ALLOW_THREADS
4883 err = self->sequence->initial_value(self->sequence, value);
4884 MYDB_END_ALLOW_THREADS
4885
4886 RETURN_IF_ERR();
4887
4888 RETURN_NONE();
4889}
4890
4891static PyObject*
4892DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4893{
4894 int err, flags = 0;
4895 PyObject* keyobj;
4896 PyObject *txnobj = NULL;
4897 DB_TXN *txn = NULL;
4898 DBT key;
4899
4900 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004902 return NULL;
4903
4904 if (!checkTxnObj(txnobj, &txn))
4905 return NULL;
4906
4907 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4908 return NULL;
4909
4910 MYDB_BEGIN_ALLOW_THREADS
4911 err = self->sequence->open(self->sequence, txn, &key, flags);
4912 MYDB_END_ALLOW_THREADS
4913
4914 CLEAR_DBT(key);
4915 RETURN_IF_ERR();
4916
4917 RETURN_NONE();
4918}
4919
4920static PyObject*
4921DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4922{
4923 int err, flags = 0;
4924 PyObject *txnobj = NULL;
4925 DB_TXN *txn = NULL;
4926
4927 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004929 return NULL;
4930
4931 if (!checkTxnObj(txnobj, &txn))
4932 return NULL;
4933
4934 CHECK_SEQUENCE_NOT_CLOSED(self)
4935
4936 MYDB_BEGIN_ALLOW_THREADS
4937 err = self->sequence->remove(self->sequence, txn, flags);
4938 MYDB_END_ALLOW_THREADS
4939
4940 RETURN_IF_ERR();
4941 RETURN_NONE();
4942}
4943
4944static PyObject*
4945DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4946{
4947 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004948 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004949 return NULL;
4950 CHECK_SEQUENCE_NOT_CLOSED(self)
4951
4952 MYDB_BEGIN_ALLOW_THREADS
4953 err = self->sequence->set_cachesize(self->sequence, size);
4954 MYDB_END_ALLOW_THREADS
4955
4956 RETURN_IF_ERR();
4957 RETURN_NONE();
4958}
4959
4960static PyObject*
4961DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4962{
4963 int err, size;
4964 if (!PyArg_ParseTuple(args,":get_cachesize"))
4965 return NULL;
4966 CHECK_SEQUENCE_NOT_CLOSED(self)
4967
4968 MYDB_BEGIN_ALLOW_THREADS
4969 err = self->sequence->get_cachesize(self->sequence, &size);
4970 MYDB_END_ALLOW_THREADS
4971
4972 RETURN_IF_ERR();
4973 return PyInt_FromLong(size);
4974}
4975
4976static PyObject*
4977DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4978{
4979 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004980 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self)
4983
4984 MYDB_BEGIN_ALLOW_THREADS
4985 err = self->sequence->set_flags(self->sequence, flags);
4986 MYDB_END_ALLOW_THREADS
4987
4988 RETURN_IF_ERR();
4989 RETURN_NONE();
4990
4991}
4992
4993static PyObject*
4994DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4995{
4996 unsigned int flags;
4997 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004998 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004999 return NULL;
5000 CHECK_SEQUENCE_NOT_CLOSED(self)
5001
5002 MYDB_BEGIN_ALLOW_THREADS
5003 err = self->sequence->get_flags(self->sequence, &flags);
5004 MYDB_END_ALLOW_THREADS
5005
5006 RETURN_IF_ERR();
5007 return PyInt_FromLong((int)flags);
5008}
5009
5010static PyObject*
5011DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5012{
5013 int err;
5014 db_seq_t min, max;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005015 if (!PyArg_ParseTuple(args,"LL:set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005016 return NULL;
5017 CHECK_SEQUENCE_NOT_CLOSED(self)
5018
5019 MYDB_BEGIN_ALLOW_THREADS
5020 err = self->sequence->set_range(self->sequence, min, max);
5021 MYDB_END_ALLOW_THREADS
5022
5023 RETURN_IF_ERR();
5024 RETURN_NONE();
5025}
5026
5027static PyObject*
5028DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5029{
5030 int err;
5031 db_seq_t min, max;
5032 if (!PyArg_ParseTuple(args,":get_range"))
5033 return NULL;
5034 CHECK_SEQUENCE_NOT_CLOSED(self)
5035
5036 MYDB_BEGIN_ALLOW_THREADS
5037 err = self->sequence->get_range(self->sequence, &min, &max);
5038 MYDB_END_ALLOW_THREADS
5039
5040 RETURN_IF_ERR();
5041 return Py_BuildValue("(LL)", min, max);
5042}
5043
5044static PyObject*
5045DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5046{
5047 int err, flags = 0;
5048 DB_SEQUENCE_STAT* sp = NULL;
5049 PyObject* dict_stat;
5050 static char* kwnames[] = {"flags", NULL };
5051 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5052 return NULL;
5053 CHECK_SEQUENCE_NOT_CLOSED(self);
5054
5055 MYDB_BEGIN_ALLOW_THREADS;
5056 err = self->sequence->stat(self->sequence, &sp, flags);
5057 MYDB_END_ALLOW_THREADS;
5058 RETURN_IF_ERR();
5059
5060 if ((dict_stat = PyDict_New()) == NULL) {
5061 free(sp);
5062 return NULL;
5063 }
5064
5065
5066#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5067#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5068
5069 MAKE_INT_ENTRY(wait);
5070 MAKE_INT_ENTRY(nowait);
5071 MAKE_LONG_LONG_ENTRY(current);
5072 MAKE_LONG_LONG_ENTRY(value);
5073 MAKE_LONG_LONG_ENTRY(last_value);
5074 MAKE_LONG_LONG_ENTRY(min);
5075 MAKE_LONG_LONG_ENTRY(max);
5076 MAKE_INT_ENTRY(cache_size);
5077 MAKE_INT_ENTRY(flags);
5078
5079#undef MAKE_INT_ENTRY
5080#undef MAKE_LONG_LONG_ENTRY
5081
5082 free(sp);
5083 return dict_stat;
5084}
5085#endif
5086
5087
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005088/* --------------------------------------------------------------------- */
5089/* Method definition tables and type objects */
5090
5091static PyMethodDef DB_methods[] = {
5092 {"append", (PyCFunction)DB_append, METH_VARARGS},
5093#if (DBVER >= 33)
5094 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5095#endif
5096 {"close", (PyCFunction)DB_close, METH_VARARGS},
5097#if (DBVER >= 32)
5098 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5099 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5100#endif
5101 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5102 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5103 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5104 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005105#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005106 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005107#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005108 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5109 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5110 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5111 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5112 {"join", (PyCFunction)DB_join, METH_VARARGS},
5113 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5114 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5115 {"items", (PyCFunction)DB_items, METH_VARARGS},
5116 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5117 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5118 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5119 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5120 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5121 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005122#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005123 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005124#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005125 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005126#if (DBVER >= 41)
5127 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5128#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005129 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5130 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5131 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5132 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5133 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5134 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5135 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5136 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5137 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5138#if (DBVER >= 32)
5139 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5140#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005141 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005142 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5143#if (DBVER >= 33)
5144 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5145#endif
5146 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5147 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5148 {"values", (PyCFunction)DB_values, METH_VARARGS},
5149 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5150 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5151 {NULL, NULL} /* sentinel */
5152};
5153
5154
5155static PyMappingMethods DB_mapping = {
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005156#if (PY_VERSION_HEX < 0x02050000)
5157 (inquiry)DB_length, /*mp_length*/
5158#else
Martin v. Löwis18e16552006-02-15 17:27:45 +00005159 (lenfunc)DB_length, /*mp_length*/
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005160#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005161 (binaryfunc)DB_subscript, /*mp_subscript*/
5162 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5163};
5164
5165
5166static PyMethodDef DBCursor_methods[] = {
5167 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5168 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5169 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5170 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5171 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5172 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5173 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005174#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005175 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005176#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005177 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5178 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5179 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5180 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5181 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5182 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5183 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5184 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005185 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005186 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005187 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5188 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5189 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5190 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5191 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5192 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5193 {NULL, NULL} /* sentinel */
5194};
5195
5196
5197static PyMethodDef DBEnv_methods[] = {
5198 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5199 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5200 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005201#if (DBVER >= 41)
5202 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5203 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5204 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5205#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005206#if (DBVER >= 40)
5207 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5208#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005209 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005210 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5211 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5212#if (DBVER >= 32)
5213 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5214#endif
5215 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5216 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5217 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005218#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005219 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005220#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005221 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5222 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5223#if (DBVER >= 32)
5224 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5225 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5226 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5227#endif
5228 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5229 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5230 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5231 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5232 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5233 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005234 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005235 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5236 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5237 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5238 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5239 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5240 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005241#if (DBVER >= 40)
5242 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5243#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005244#if (DBVER >= 44)
5245 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5246#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005247 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5248 {NULL, NULL} /* sentinel */
5249};
5250
5251
5252static PyMethodDef DBTxn_methods[] = {
5253 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5254 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5255 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5256 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5257 {NULL, NULL} /* sentinel */
5258};
5259
5260
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005261#if (DBVER >= 43)
5262static PyMethodDef DBSequence_methods[] = {
5263 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5264 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5265 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5266 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005267 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5268 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5269 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5270 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5271 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5272 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5273 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5274 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5275 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5276 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5277 {NULL, NULL} /* sentinel */
5278};
5279#endif
5280
5281
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005282static PyObject*
5283DB_getattr(DBObject* self, char *name)
5284{
5285 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5286}
5287
5288
5289static PyObject*
5290DBEnv_getattr(DBEnvObject* self, char *name)
5291{
5292 if (!strcmp(name, "db_home")) {
5293 CHECK_ENV_NOT_CLOSED(self);
5294 if (self->db_env->db_home == NULL) {
5295 RETURN_NONE();
5296 }
5297 return PyString_FromString(self->db_env->db_home);
5298 }
5299
5300 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5301}
5302
5303
5304static PyObject*
5305DBCursor_getattr(DBCursorObject* self, char *name)
5306{
5307 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5308}
5309
5310static PyObject*
5311DBTxn_getattr(DBTxnObject* self, char *name)
5312{
5313 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5314}
5315
5316static PyObject*
5317DBLock_getattr(DBLockObject* self, char *name)
5318{
5319 return NULL;
5320}
5321
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005322#if (DBVER >= 43)
5323static PyObject*
5324DBSequence_getattr(DBSequenceObject* self, char *name)
5325{
5326 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5327}
5328#endif
5329
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005330statichere PyTypeObject DB_Type = {
5331 PyObject_HEAD_INIT(NULL)
5332 0, /*ob_size*/
5333 "DB", /*tp_name*/
5334 sizeof(DBObject), /*tp_basicsize*/
5335 0, /*tp_itemsize*/
5336 /* methods */
5337 (destructor)DB_dealloc, /*tp_dealloc*/
5338 0, /*tp_print*/
5339 (getattrfunc)DB_getattr, /*tp_getattr*/
5340 0, /*tp_setattr*/
5341 0, /*tp_compare*/
5342 0, /*tp_repr*/
5343 0, /*tp_as_number*/
5344 0, /*tp_as_sequence*/
5345 &DB_mapping,/*tp_as_mapping*/
5346 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005347#ifdef HAVE_WEAKREF
5348 0, /* tp_call */
5349 0, /* tp_str */
5350 0, /* tp_getattro */
5351 0, /* tp_setattro */
5352 0, /* tp_as_buffer */
5353 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5354 0, /* tp_doc */
5355 0, /* tp_traverse */
5356 0, /* tp_clear */
5357 0, /* tp_richcompare */
5358 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5359#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005360};
5361
5362
5363statichere PyTypeObject DBCursor_Type = {
5364 PyObject_HEAD_INIT(NULL)
5365 0, /*ob_size*/
5366 "DBCursor", /*tp_name*/
5367 sizeof(DBCursorObject), /*tp_basicsize*/
5368 0, /*tp_itemsize*/
5369 /* methods */
5370 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5371 0, /*tp_print*/
5372 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5373 0, /*tp_setattr*/
5374 0, /*tp_compare*/
5375 0, /*tp_repr*/
5376 0, /*tp_as_number*/
5377 0, /*tp_as_sequence*/
5378 0, /*tp_as_mapping*/
5379 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005380#ifdef HAVE_WEAKREF
5381 0, /* tp_call */
5382 0, /* tp_str */
5383 0, /* tp_getattro */
5384 0, /* tp_setattro */
5385 0, /* tp_as_buffer */
5386 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5387 0, /* tp_doc */
5388 0, /* tp_traverse */
5389 0, /* tp_clear */
5390 0, /* tp_richcompare */
5391 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5392#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005393};
5394
5395
5396statichere PyTypeObject DBEnv_Type = {
5397 PyObject_HEAD_INIT(NULL)
5398 0, /*ob_size*/
5399 "DBEnv", /*tp_name*/
5400 sizeof(DBEnvObject), /*tp_basicsize*/
5401 0, /*tp_itemsize*/
5402 /* methods */
5403 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5404 0, /*tp_print*/
5405 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5406 0, /*tp_setattr*/
5407 0, /*tp_compare*/
5408 0, /*tp_repr*/
5409 0, /*tp_as_number*/
5410 0, /*tp_as_sequence*/
5411 0, /*tp_as_mapping*/
5412 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005413#ifdef HAVE_WEAKREF
5414 0, /* tp_call */
5415 0, /* tp_str */
5416 0, /* tp_getattro */
5417 0, /* tp_setattro */
5418 0, /* tp_as_buffer */
5419 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5420 0, /* tp_doc */
5421 0, /* tp_traverse */
5422 0, /* tp_clear */
5423 0, /* tp_richcompare */
5424 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5425#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005426};
5427
5428statichere PyTypeObject DBTxn_Type = {
5429 PyObject_HEAD_INIT(NULL)
5430 0, /*ob_size*/
5431 "DBTxn", /*tp_name*/
5432 sizeof(DBTxnObject), /*tp_basicsize*/
5433 0, /*tp_itemsize*/
5434 /* methods */
5435 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5436 0, /*tp_print*/
5437 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5438 0, /*tp_setattr*/
5439 0, /*tp_compare*/
5440 0, /*tp_repr*/
5441 0, /*tp_as_number*/
5442 0, /*tp_as_sequence*/
5443 0, /*tp_as_mapping*/
5444 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005445#ifdef HAVE_WEAKREF
5446 0, /* tp_call */
5447 0, /* tp_str */
5448 0, /* tp_getattro */
5449 0, /* tp_setattro */
5450 0, /* tp_as_buffer */
5451 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5452 0, /* tp_doc */
5453 0, /* tp_traverse */
5454 0, /* tp_clear */
5455 0, /* tp_richcompare */
5456 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5457#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005458};
5459
5460
5461statichere PyTypeObject DBLock_Type = {
5462 PyObject_HEAD_INIT(NULL)
5463 0, /*ob_size*/
5464 "DBLock", /*tp_name*/
5465 sizeof(DBLockObject), /*tp_basicsize*/
5466 0, /*tp_itemsize*/
5467 /* methods */
5468 (destructor)DBLock_dealloc, /*tp_dealloc*/
5469 0, /*tp_print*/
5470 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5471 0, /*tp_setattr*/
5472 0, /*tp_compare*/
5473 0, /*tp_repr*/
5474 0, /*tp_as_number*/
5475 0, /*tp_as_sequence*/
5476 0, /*tp_as_mapping*/
5477 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005478#ifdef HAVE_WEAKREF
5479 0, /* tp_call */
5480 0, /* tp_str */
5481 0, /* tp_getattro */
5482 0, /* tp_setattro */
5483 0, /* tp_as_buffer */
5484 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5485 0, /* tp_doc */
5486 0, /* tp_traverse */
5487 0, /* tp_clear */
5488 0, /* tp_richcompare */
5489 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5490#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005491};
5492
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005493#if (DBVER >= 43)
5494statichere PyTypeObject DBSequence_Type = {
5495 PyObject_HEAD_INIT(NULL)
5496 0, /*ob_size*/
5497 "DBSequence", /*tp_name*/
5498 sizeof(DBSequenceObject), /*tp_basicsize*/
5499 0, /*tp_itemsize*/
5500 /* methods */
5501 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5502 0, /*tp_print*/
5503 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5504 0, /*tp_setattr*/
5505 0, /*tp_compare*/
5506 0, /*tp_repr*/
5507 0, /*tp_as_number*/
5508 0, /*tp_as_sequence*/
5509 0, /*tp_as_mapping*/
5510 0, /*tp_hash*/
5511#ifdef HAVE_WEAKREF
5512 0, /* tp_call */
5513 0, /* tp_str */
5514 0, /* tp_getattro */
5515 0, /* tp_setattro */
5516 0, /* tp_as_buffer */
5517 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5518 0, /* tp_doc */
5519 0, /* tp_traverse */
5520 0, /* tp_clear */
5521 0, /* tp_richcompare */
5522 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5523#endif
5524};
5525#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005526
5527/* --------------------------------------------------------------------- */
5528/* Module-level functions */
5529
5530static PyObject*
5531DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5532{
5533 PyObject* dbenvobj = NULL;
5534 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005535 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005537 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5538 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005539 return NULL;
5540 if (dbenvobj == Py_None)
5541 dbenvobj = NULL;
5542 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5543 makeTypeError("DBEnv", dbenvobj);
5544 return NULL;
5545 }
5546
5547 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5548}
5549
5550
5551static PyObject*
5552DBEnv_construct(PyObject* self, PyObject* args)
5553{
5554 int flags = 0;
5555 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5556 return (PyObject* )newDBEnvObject(flags);
5557}
5558
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005559#if (DBVER >= 43)
5560static PyObject*
5561DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5562{
5563 PyObject* dbobj = NULL;
5564 int flags = 0;
5565 static char* kwnames[] = { "db", "flags", NULL};
5566
5567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5568 return NULL;
5569 if (dbobj == Py_None)
5570 dbobj = NULL;
5571 else if (dbobj && !DBObject_Check(dbobj)) {
5572 makeTypeError("DB", dbobj);
5573 return NULL;
5574 }
5575 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5576}
5577#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005578
5579static char bsddb_version_doc[] =
5580"Returns a tuple of major, minor, and patch release numbers of the\n\
5581underlying DB library.";
5582
5583static PyObject*
5584bsddb_version(PyObject* self, PyObject* args)
5585{
5586 int major, minor, patch;
5587
5588 if (!PyArg_ParseTuple(args, ":version"))
5589 return NULL;
5590 db_version(&major, &minor, &patch);
5591 return Py_BuildValue("(iii)", major, minor, patch);
5592}
5593
5594
5595/* List of functions defined in the module */
5596
5597static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005598 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5599 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5600#if (DBVER >= 43)
5601 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5602#endif
5603 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005604 {NULL, NULL} /* sentinel */
5605};
5606
5607
5608/* --------------------------------------------------------------------- */
5609/* Module initialization */
5610
5611
5612/* Convenience routine to export an integer value.
5613 * Errors are silently ignored, for better or for worse...
5614 */
5615#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5616
Gregory P. Smith41631e82003-09-21 00:08:14 +00005617#define MODULE_NAME_MAX_LEN 11
5618static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005619
5620DL_EXPORT(void) init_bsddb(void)
5621{
5622 PyObject* m;
5623 PyObject* d;
5624 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5625 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5626 PyObject* cvsid_s = PyString_FromString( rcs_id );
5627
5628 /* Initialize the type of the new type objects here; doing it here
5629 is required for portability to Windows without requiring C++. */
5630 DB_Type.ob_type = &PyType_Type;
5631 DBCursor_Type.ob_type = &PyType_Type;
5632 DBEnv_Type.ob_type = &PyType_Type;
5633 DBTxn_Type.ob_type = &PyType_Type;
5634 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005635#if (DBVER >= 43)
5636 DBSequence_Type.ob_type = &PyType_Type;
5637#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638
5639
Mark Hammonda69d4092003-04-22 23:13:27 +00005640#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005641 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005642 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005643#endif
5644
5645 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005646 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005647 if (m == NULL)
5648 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005649
5650 /* Add some symbolic constants to the module */
5651 d = PyModule_GetDict(m);
5652 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5653 PyDict_SetItemString(d, "cvsid", cvsid_s);
5654 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5655 Py_DECREF(pybsddb_version_s);
5656 pybsddb_version_s = NULL;
5657 Py_DECREF(cvsid_s);
5658 cvsid_s = NULL;
5659 Py_DECREF(db_version_s);
5660 db_version_s = NULL;
5661
5662 ADD_INT(d, DB_VERSION_MAJOR);
5663 ADD_INT(d, DB_VERSION_MINOR);
5664 ADD_INT(d, DB_VERSION_PATCH);
5665
5666 ADD_INT(d, DB_MAX_PAGES);
5667 ADD_INT(d, DB_MAX_RECORDS);
5668
Gregory P. Smith41631e82003-09-21 00:08:14 +00005669#if (DBVER >= 42)
5670 ADD_INT(d, DB_RPCCLIENT);
5671#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005672 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005673 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5674 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5675#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005676 ADD_INT(d, DB_XA_CREATE);
5677
5678 ADD_INT(d, DB_CREATE);
5679 ADD_INT(d, DB_NOMMAP);
5680 ADD_INT(d, DB_THREAD);
5681
5682 ADD_INT(d, DB_FORCE);
5683 ADD_INT(d, DB_INIT_CDB);
5684 ADD_INT(d, DB_INIT_LOCK);
5685 ADD_INT(d, DB_INIT_LOG);
5686 ADD_INT(d, DB_INIT_MPOOL);
5687 ADD_INT(d, DB_INIT_TXN);
5688#if (DBVER >= 32)
5689 ADD_INT(d, DB_JOINENV);
5690#endif
5691
5692 ADD_INT(d, DB_RECOVER);
5693 ADD_INT(d, DB_RECOVER_FATAL);
5694 ADD_INT(d, DB_TXN_NOSYNC);
5695 ADD_INT(d, DB_USE_ENVIRON);
5696 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5697
5698 ADD_INT(d, DB_LOCKDOWN);
5699 ADD_INT(d, DB_PRIVATE);
5700 ADD_INT(d, DB_SYSTEM_MEM);
5701
5702 ADD_INT(d, DB_TXN_SYNC);
5703 ADD_INT(d, DB_TXN_NOWAIT);
5704
5705 ADD_INT(d, DB_EXCL);
5706 ADD_INT(d, DB_FCNTL_LOCKING);
5707 ADD_INT(d, DB_ODDFILESIZE);
5708 ADD_INT(d, DB_RDWRMASTER);
5709 ADD_INT(d, DB_RDONLY);
5710 ADD_INT(d, DB_TRUNCATE);
5711#if (DBVER >= 32)
5712 ADD_INT(d, DB_EXTENT);
5713 ADD_INT(d, DB_CDB_ALLDB);
5714 ADD_INT(d, DB_VERIFY);
5715#endif
5716 ADD_INT(d, DB_UPGRADE);
5717
5718 ADD_INT(d, DB_AGGRESSIVE);
5719 ADD_INT(d, DB_NOORDERCHK);
5720 ADD_INT(d, DB_ORDERCHKONLY);
5721 ADD_INT(d, DB_PR_PAGE);
5722#if ! (DBVER >= 33)
5723 ADD_INT(d, DB_VRFY_FLAGMASK);
5724 ADD_INT(d, DB_PR_HEADERS);
5725#endif
5726 ADD_INT(d, DB_PR_RECOVERYTEST);
5727 ADD_INT(d, DB_SALVAGE);
5728
5729 ADD_INT(d, DB_LOCK_NORUN);
5730 ADD_INT(d, DB_LOCK_DEFAULT);
5731 ADD_INT(d, DB_LOCK_OLDEST);
5732 ADD_INT(d, DB_LOCK_RANDOM);
5733 ADD_INT(d, DB_LOCK_YOUNGEST);
5734#if (DBVER >= 33)
5735 ADD_INT(d, DB_LOCK_MAXLOCKS);
5736 ADD_INT(d, DB_LOCK_MINLOCKS);
5737 ADD_INT(d, DB_LOCK_MINWRITE);
5738#endif
5739
5740
5741#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005742 /* docs say to use zero instead */
5743 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005744#else
5745 ADD_INT(d, DB_LOCK_CONFLICT);
5746#endif
5747
5748 ADD_INT(d, DB_LOCK_DUMP);
5749 ADD_INT(d, DB_LOCK_GET);
5750 ADD_INT(d, DB_LOCK_INHERIT);
5751 ADD_INT(d, DB_LOCK_PUT);
5752 ADD_INT(d, DB_LOCK_PUT_ALL);
5753 ADD_INT(d, DB_LOCK_PUT_OBJ);
5754
5755 ADD_INT(d, DB_LOCK_NG);
5756 ADD_INT(d, DB_LOCK_READ);
5757 ADD_INT(d, DB_LOCK_WRITE);
5758 ADD_INT(d, DB_LOCK_NOWAIT);
5759#if (DBVER >= 32)
5760 ADD_INT(d, DB_LOCK_WAIT);
5761#endif
5762 ADD_INT(d, DB_LOCK_IWRITE);
5763 ADD_INT(d, DB_LOCK_IREAD);
5764 ADD_INT(d, DB_LOCK_IWR);
5765#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005766#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005767 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005768#else
5769 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5770#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005771 ADD_INT(d, DB_LOCK_WWRITE);
5772#endif
5773
5774 ADD_INT(d, DB_LOCK_RECORD);
5775 ADD_INT(d, DB_LOCK_UPGRADE);
5776#if (DBVER >= 32)
5777 ADD_INT(d, DB_LOCK_SWITCH);
5778#endif
5779#if (DBVER >= 33)
5780 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5781#endif
5782
5783 ADD_INT(d, DB_LOCK_NOWAIT);
5784 ADD_INT(d, DB_LOCK_RECORD);
5785 ADD_INT(d, DB_LOCK_UPGRADE);
5786
5787#if (DBVER >= 33)
5788 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005789#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005790 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005791#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005792 ADD_INT(d, DB_LSTAT_FREE);
5793 ADD_INT(d, DB_LSTAT_HELD);
5794#if (DBVER == 33)
5795 ADD_INT(d, DB_LSTAT_NOGRANT);
5796#endif
5797 ADD_INT(d, DB_LSTAT_PENDING);
5798 ADD_INT(d, DB_LSTAT_WAITING);
5799#endif
5800
5801 ADD_INT(d, DB_ARCH_ABS);
5802 ADD_INT(d, DB_ARCH_DATA);
5803 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005804#if (DBVER >= 42)
5805 ADD_INT(d, DB_ARCH_REMOVE);
5806#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005807
5808 ADD_INT(d, DB_BTREE);
5809 ADD_INT(d, DB_HASH);
5810 ADD_INT(d, DB_RECNO);
5811 ADD_INT(d, DB_QUEUE);
5812 ADD_INT(d, DB_UNKNOWN);
5813
5814 ADD_INT(d, DB_DUP);
5815 ADD_INT(d, DB_DUPSORT);
5816 ADD_INT(d, DB_RECNUM);
5817 ADD_INT(d, DB_RENUMBER);
5818 ADD_INT(d, DB_REVSPLITOFF);
5819 ADD_INT(d, DB_SNAPSHOT);
5820
5821 ADD_INT(d, DB_JOIN_NOSORT);
5822
5823 ADD_INT(d, DB_AFTER);
5824 ADD_INT(d, DB_APPEND);
5825 ADD_INT(d, DB_BEFORE);
5826 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005827#if (DBVER >= 41)
5828 _addIntToDict(d, "DB_CHECKPOINT", 0);
5829#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005830 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005831 ADD_INT(d, DB_CURLSN);
5832#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005833#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005834 ADD_INT(d, DB_COMMIT);
5835#endif
5836 ADD_INT(d, DB_CONSUME);
5837#if (DBVER >= 32)
5838 ADD_INT(d, DB_CONSUME_WAIT);
5839#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005840 ADD_INT(d, DB_CURRENT);
5841#if (DBVER >= 33)
5842 ADD_INT(d, DB_FAST_STAT);
5843#endif
5844 ADD_INT(d, DB_FIRST);
5845 ADD_INT(d, DB_FLUSH);
5846 ADD_INT(d, DB_GET_BOTH);
5847 ADD_INT(d, DB_GET_RECNO);
5848 ADD_INT(d, DB_JOIN_ITEM);
5849 ADD_INT(d, DB_KEYFIRST);
5850 ADD_INT(d, DB_KEYLAST);
5851 ADD_INT(d, DB_LAST);
5852 ADD_INT(d, DB_NEXT);
5853 ADD_INT(d, DB_NEXT_DUP);
5854 ADD_INT(d, DB_NEXT_NODUP);
5855 ADD_INT(d, DB_NODUPDATA);
5856 ADD_INT(d, DB_NOOVERWRITE);
5857 ADD_INT(d, DB_NOSYNC);
5858 ADD_INT(d, DB_POSITION);
5859 ADD_INT(d, DB_PREV);
5860 ADD_INT(d, DB_PREV_NODUP);
5861 ADD_INT(d, DB_RECORDCOUNT);
5862 ADD_INT(d, DB_SET);
5863 ADD_INT(d, DB_SET_RANGE);
5864 ADD_INT(d, DB_SET_RECNO);
5865 ADD_INT(d, DB_WRITECURSOR);
5866
5867 ADD_INT(d, DB_OPFLAGS_MASK);
5868 ADD_INT(d, DB_RMW);
5869#if (DBVER >= 33)
5870 ADD_INT(d, DB_DIRTY_READ);
5871 ADD_INT(d, DB_MULTIPLE);
5872 ADD_INT(d, DB_MULTIPLE_KEY);
5873#endif
5874
Gregory P. Smith29602d22006-01-24 09:46:48 +00005875#if (DBVER >= 44)
5876 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5877 ADD_INT(d, DB_READ_COMMITTED);
5878#endif
5879
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005880#if (DBVER >= 33)
5881 ADD_INT(d, DB_DONOTINDEX);
5882#endif
5883
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005884#if (DBVER >= 41)
5885 _addIntToDict(d, "DB_INCOMPLETE", 0);
5886#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005887 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005888#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005889 ADD_INT(d, DB_KEYEMPTY);
5890 ADD_INT(d, DB_KEYEXIST);
5891 ADD_INT(d, DB_LOCK_DEADLOCK);
5892 ADD_INT(d, DB_LOCK_NOTGRANTED);
5893 ADD_INT(d, DB_NOSERVER);
5894 ADD_INT(d, DB_NOSERVER_HOME);
5895 ADD_INT(d, DB_NOSERVER_ID);
5896 ADD_INT(d, DB_NOTFOUND);
5897 ADD_INT(d, DB_OLD_VERSION);
5898 ADD_INT(d, DB_RUNRECOVERY);
5899 ADD_INT(d, DB_VERIFY_BAD);
5900#if (DBVER >= 33)
5901 ADD_INT(d, DB_PAGE_NOTFOUND);
5902 ADD_INT(d, DB_SECONDARY_BAD);
5903#endif
5904#if (DBVER >= 40)
5905 ADD_INT(d, DB_STAT_CLEAR);
5906 ADD_INT(d, DB_REGION_INIT);
5907 ADD_INT(d, DB_NOLOCKING);
5908 ADD_INT(d, DB_YIELDCPU);
5909 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5910 ADD_INT(d, DB_NOPANIC);
5911#endif
5912
Gregory P. Smith41631e82003-09-21 00:08:14 +00005913#if (DBVER >= 42)
5914 ADD_INT(d, DB_TIME_NOTGRANTED);
5915 ADD_INT(d, DB_TXN_NOT_DURABLE);
5916 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5917 ADD_INT(d, DB_LOG_AUTOREMOVE);
5918 ADD_INT(d, DB_DIRECT_LOG);
5919 ADD_INT(d, DB_DIRECT_DB);
5920 ADD_INT(d, DB_INIT_REP);
5921 ADD_INT(d, DB_ENCRYPT);
5922 ADD_INT(d, DB_CHKSUM);
5923#endif
5924
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005925#if (DBVER >= 43)
5926 ADD_INT(d, DB_LOG_INMEMORY);
5927 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005928 ADD_INT(d, DB_SEQ_DEC);
5929 ADD_INT(d, DB_SEQ_INC);
5930 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005931#endif
5932
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005933#if (DBVER >= 41)
5934 ADD_INT(d, DB_ENCRYPT_AES);
5935 ADD_INT(d, DB_AUTO_COMMIT);
5936#else
5937 /* allow berkeleydb 4.1 aware apps to run on older versions */
5938 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5939#endif
5940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005941 ADD_INT(d, EINVAL);
5942 ADD_INT(d, EACCES);
5943 ADD_INT(d, ENOSPC);
5944 ADD_INT(d, ENOMEM);
5945 ADD_INT(d, EAGAIN);
5946 ADD_INT(d, EBUSY);
5947 ADD_INT(d, EEXIST);
5948 ADD_INT(d, ENOENT);
5949 ADD_INT(d, EPERM);
5950
Barry Warsaw1baa9822003-03-31 19:51:29 +00005951#if (DBVER >= 40)
5952 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5953 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5954#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005955
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005956 /* The exception name must be correct for pickled exception *
5957 * objects to unpickle properly. */
5958#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5959#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5960#else
5961#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5962#endif
5963
5964 /* All the rest of the exceptions derive only from DBError */
5965#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5966 PyDict_SetItemString(d, #name, name)
5967
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005968 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005969 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5970 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005971
Gregory P. Smithe9477062005-06-04 06:46:59 +00005972 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5973 * from both DBError and KeyError, since the API only supports
5974 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005975 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005976 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5977 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005978 Py_file_input, d, d);
5979 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005980 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981 PyDict_DelItemString(d, "KeyError");
5982
5983
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984#if !INCOMPLETE_IS_WARNING
5985 MAKE_EX(DBIncompleteError);
5986#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005987 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 MAKE_EX(DBKeyEmptyError);
5989 MAKE_EX(DBKeyExistError);
5990 MAKE_EX(DBLockDeadlockError);
5991 MAKE_EX(DBLockNotGrantedError);
5992 MAKE_EX(DBOldVersionError);
5993 MAKE_EX(DBRunRecoveryError);
5994 MAKE_EX(DBVerifyBadError);
5995 MAKE_EX(DBNoServerError);
5996 MAKE_EX(DBNoServerHomeError);
5997 MAKE_EX(DBNoServerIDError);
5998#if (DBVER >= 33)
5999 MAKE_EX(DBPageNotFoundError);
6000 MAKE_EX(DBSecondaryBadError);
6001#endif
6002
6003 MAKE_EX(DBInvalidArgError);
6004 MAKE_EX(DBAccessError);
6005 MAKE_EX(DBNoSpaceError);
6006 MAKE_EX(DBNoMemoryError);
6007 MAKE_EX(DBAgainError);
6008 MAKE_EX(DBBusyError);
6009 MAKE_EX(DBFileExistsError);
6010 MAKE_EX(DBNoSuchFileError);
6011 MAKE_EX(DBPermissionsError);
6012
6013#undef MAKE_EX
6014
6015 /* Check for errors */
6016 if (PyErr_Occurred()) {
6017 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006018 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006019 }
6020}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006021
6022/* allow this module to be named _pybsddb so that it can be installed
6023 * and imported on top of python >= 2.3 that includes its own older
6024 * copy of the library named _bsddb without importing the old version. */
6025DL_EXPORT(void) init_pybsddb(void)
6026{
6027 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6028 init_bsddb();
6029}