blob: 8e9ae3dc401a4687769e0229cfd0fab5fd210a44 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000064 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000065 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000071 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000072 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
Gregory P. Smitha703a212003-11-03 01:04:41 +000088#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000089#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000095/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
Gregory P. Smitha703a212003-11-03 01:04:41 +000097#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000100
Gregory P. Smith372b5832006-06-05 18:48:21 +0000101#define PY_BSDDB_VERSION "4.4.4"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000102static char *rcs_id = "$Id$";
103
104
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000106typedef int Py_ssize_t;
107typedef inquiry lenfunc;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000108#endif
109
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000110#ifdef WITH_THREAD
111
112/* These are for when calling Python --> C */
113#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
114#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
115
Mark Hammonda69d4092003-04-22 23:13:27 +0000116/* For 2.3, use the PyGILState_ calls */
117#if (PY_VERSION_HEX >= 0x02030000)
118#define MYDB_USE_GILSTATE
119#endif
120
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000121/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000122#if defined(MYDB_USE_GILSTATE)
123#define MYDB_BEGIN_BLOCK_THREADS \
124 PyGILState_STATE __savestate = PyGILState_Ensure();
125#define MYDB_END_BLOCK_THREADS \
126 PyGILState_Release(__savestate);
127#else /* MYDB_USE_GILSTATE */
128/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000129static PyInterpreterState* _db_interpreterState = NULL;
130#define MYDB_BEGIN_BLOCK_THREADS { \
131 PyThreadState* prevState; \
132 PyThreadState* newState; \
133 PyEval_AcquireLock(); \
134 newState = PyThreadState_New(_db_interpreterState); \
135 prevState = PyThreadState_Swap(newState);
136
137#define MYDB_END_BLOCK_THREADS \
138 newState = PyThreadState_Swap(prevState); \
139 PyThreadState_Clear(newState); \
140 PyEval_ReleaseLock(); \
141 PyThreadState_Delete(newState); \
142 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000143#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000144
145#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000146/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000147#define MYDB_BEGIN_ALLOW_THREADS
148#define MYDB_END_ALLOW_THREADS
149#define MYDB_BEGIN_BLOCK_THREADS
150#define MYDB_END_BLOCK_THREADS
151
152#endif
153
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000154/* Should DB_INCOMPLETE be turned into a warning or an exception? */
155#define INCOMPLETE_IS_WARNING 1
156
157/* --------------------------------------------------------------------- */
158/* Exceptions */
159
160static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000161static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000162static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000163static PyObject* DBKeyExistError; /* DB_KEYEXIST */
164static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
165static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
166static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
167static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
168static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
169static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
170static PyObject* DBNoServerError; /* DB_NOSERVER */
171static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
172static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
173#if (DBVER >= 33)
174static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
175static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
176#endif
177
178#if !INCOMPLETE_IS_WARNING
179static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
180#endif
181
182static PyObject* DBInvalidArgError; /* EINVAL */
183static PyObject* DBAccessError; /* EACCES */
184static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000185static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000186static PyObject* DBAgainError; /* EAGAIN */
187static PyObject* DBBusyError; /* EBUSY */
188static PyObject* DBFileExistsError; /* EEXIST */
189static PyObject* DBNoSuchFileError; /* ENOENT */
190static PyObject* DBPermissionsError; /* EPERM */
191
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000192#if (DBVER < 43)
193#define DB_BUFFER_SMALL ENOMEM
194#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000195
196
197/* --------------------------------------------------------------------- */
198/* Structure definitions */
199
Gregory P. Smitha703a212003-11-03 01:04:41 +0000200#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
201#define HAVE_WEAKREF
202#else
203#undef HAVE_WEAKREF
204#endif
205
Gregory P. Smith31c50652004-06-28 01:20:40 +0000206/* if Python >= 2.1 better support warnings */
207#if PYTHON_API_VERSION >= 1010
208#define HAVE_WARNINGS
209#else
210#undef HAVE_WARNINGS
211#endif
212
Neal Norwitzb4a55812004-07-09 23:30:57 +0000213#if PYTHON_API_VERSION <= 1007
214 /* 1.5 compatibility */
215#define PyObject_New PyObject_NEW
216#define PyObject_Del PyMem_DEL
217#endif
218
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000219struct behaviourFlags {
220 /* What is the default behaviour when DB->get or DBCursor->get returns a
Gregory P. Smithe9477062005-06-04 06:46:59 +0000221 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000222 unsigned int getReturnsNone : 1;
223 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
Gregory P. Smithe9477062005-06-04 06:46:59 +0000224 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000225 unsigned int cursorSetReturnsNone : 1;
226};
227
228#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000229#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000231typedef struct {
232 PyObject_HEAD
233 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000234 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000235 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000236 struct behaviourFlags moduleFlags;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000237#ifdef HAVE_WEAKREF
238 PyObject *in_weakreflist; /* List of weak references */
239#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240} DBEnvObject;
241
242
243typedef struct {
244 PyObject_HEAD
245 DB* db;
246 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000247 u_int32_t flags; /* saved flags from open() */
248 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000249 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000250 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000251#if (DBVER >= 33)
252 PyObject* associateCallback;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000253 PyObject* btCompareCallback;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000254 int primaryDBType;
255#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000256#ifdef HAVE_WEAKREF
257 PyObject *in_weakreflist; /* List of weak references */
258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259} DBObject;
260
261
262typedef struct {
263 PyObject_HEAD
264 DBC* dbc;
265 DBObject* mydb;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000266#ifdef HAVE_WEAKREF
267 PyObject *in_weakreflist; /* List of weak references */
268#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000269} DBCursorObject;
270
271
272typedef struct {
273 PyObject_HEAD
274 DB_TXN* txn;
Neal Norwitz62a21122006-01-25 05:21:55 +0000275 PyObject *env;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000276#ifdef HAVE_WEAKREF
277 PyObject *in_weakreflist; /* List of weak references */
278#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279} DBTxnObject;
280
281
282typedef struct {
283 PyObject_HEAD
284 DB_LOCK lock;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000285#ifdef HAVE_WEAKREF
286 PyObject *in_weakreflist; /* List of weak references */
287#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000288} DBLockObject;
289
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000290#if (DBVER >= 43)
291typedef struct {
292 PyObject_HEAD
293 DB_SEQUENCE* sequence;
294 DBObject* mydb;
295#ifdef HAVE_WEAKREF
296 PyObject *in_weakreflist; /* List of weak references */
297#endif
298} DBSequenceObject;
299staticforward PyTypeObject DBSequence_Type;
300#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301
302staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
303
304#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
305#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
306#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
307#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
308#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000309#if (DBVER >= 43)
310#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
311#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000312
313
314/* --------------------------------------------------------------------- */
315/* Utility macros and functions */
316
317#define RETURN_IF_ERR() \
318 if (makeDBError(err)) { \
319 return NULL; \
320 }
321
322#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
323
Gregory P. Smithe2767172003-11-02 08:06:29 +0000324#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
325 if ((nonNull) == NULL) { \
326 PyObject *errTuple = NULL; \
327 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
328 PyErr_SetObject((pyErrObj), errTuple); \
329 Py_DECREF(errTuple); \
330 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000331 }
332
Gregory P. Smithe2767172003-11-02 08:06:29 +0000333#define CHECK_DB_NOT_CLOSED(dbobj) \
334 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
335
336#define CHECK_ENV_NOT_CLOSED(env) \
337 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000338
339#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000340 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000341
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000342#if (DBVER >= 43)
343#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
344 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
345#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000346
347#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
348 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
349
350#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
351
352#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000353 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000354
355
356static int makeDBError(int err);
357
358
359/* Return the access method type of the DBObject */
360static int _DB_get_type(DBObject* self)
361{
362#if (DBVER >= 33)
363 DBTYPE type;
364 int err;
365 err = self->db->get_type(self->db, &type);
366 if (makeDBError(err)) {
367 return -1;
368 }
369 return type;
370#else
371 return self->db->get_type(self->db);
372#endif
373}
374
375
376/* Create a DBT structure (containing key and data values) from Python
377 strings. Returns 1 on success, 0 on an error. */
378static int make_dbt(PyObject* obj, DBT* dbt)
379{
380 CLEAR_DBT(*dbt);
381 if (obj == Py_None) {
382 /* no need to do anything, the structure has already been zeroed */
383 }
384 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
385 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000386 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000387 return 0;
388 }
389 return 1;
390}
391
392
393/* Recno and Queue DBs can have integer keys. This function figures out
394 what's been given, verifies that it's allowed, and then makes the DBT.
395
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000396 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000397static int
398make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000399{
400 db_recno_t recno;
401 int type;
402
403 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000404 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000405 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000406 if (type == -1)
407 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000408 if (type == DB_RECNO || type == DB_QUEUE) {
409 PyErr_SetString(
410 PyExc_TypeError,
411 "None keys not allowed for Recno and Queue DB's");
412 return 0;
413 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000414 /* no need to do anything, the structure has already been zeroed */
415 }
416
417 else if (PyString_Check(keyobj)) {
418 /* verify access method type */
419 type = _DB_get_type(self);
420 if (type == -1)
421 return 0;
422 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000423 PyErr_SetString(
424 PyExc_TypeError,
425 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000426 return 0;
427 }
428
429 key->data = PyString_AS_STRING(keyobj);
430 key->size = PyString_GET_SIZE(keyobj);
431 }
432
433 else if (PyInt_Check(keyobj)) {
434 /* verify access method type */
435 type = _DB_get_type(self);
436 if (type == -1)
437 return 0;
438 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000439 /* if BTREE then an Integer key is allowed with the
440 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000441 *pflags |= DB_SET_RECNO;
442 }
443 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000444 PyErr_SetString(
445 PyExc_TypeError,
446 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 return 0;
448 }
449
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000450 /* Make a key out of the requested recno, use allocated space so DB
451 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000452 recno = PyInt_AS_LONG(keyobj);
453 key->data = malloc(sizeof(db_recno_t));
454 if (key->data == NULL) {
455 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
456 return 0;
457 }
458 key->ulen = key->size = sizeof(db_recno_t);
459 memcpy(key->data, &recno, sizeof(db_recno_t));
460 key->flags = DB_DBT_REALLOC;
461 }
462 else {
463 PyErr_Format(PyExc_TypeError,
464 "String or Integer object expected for key, %s found",
465 keyobj->ob_type->tp_name);
466 return 0;
467 }
468
469 return 1;
470}
471
472
473/* Add partial record access to an existing DBT data struct.
474 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
475 and the data storage/retrieval will be done using dlen and doff. */
476static int add_partial_dbt(DBT* d, int dlen, int doff) {
477 /* if neither were set we do nothing (-1 is the default value) */
478 if ((dlen == -1) && (doff == -1)) {
479 return 1;
480 }
481
482 if ((dlen < 0) || (doff < 0)) {
483 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
484 return 0;
485 }
486
487 d->flags = d->flags | DB_DBT_PARTIAL;
488 d->dlen = (unsigned int) dlen;
489 d->doff = (unsigned int) doff;
490 return 1;
491}
492
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000493/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
494/* TODO: make this use the native libc strlcpy() when available (BSD) */
495unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
496{
497 unsigned int srclen, copylen;
498
499 srclen = strlen(src);
500 if (n <= 0)
501 return srclen;
502 copylen = (srclen > n-1) ? n-1 : srclen;
503 /* populate dest[0] thru dest[copylen-1] */
504 memcpy(dest, src, copylen);
505 /* guarantee null termination */
506 dest[copylen] = 0;
507
508 return srclen;
509}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000510
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000511/* Callback used to save away more information about errors from the DB
512 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000515static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000516#else
517static void _db_errorCallback(const DB_ENV *db_env,
518 const char* prefix, const char* msg)
519#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000521 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000522}
523
524
525/* make a nice exception object to raise for errors. */
526static int makeDBError(int err)
527{
528 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000529 PyObject *errObj = NULL;
530 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000531 int exceptionRaised = 0;
532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000536#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000539 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000540 if (_db_errmsg[0]) {
541 strcat(errTxt, " -- ");
542 strcat(errTxt, _db_errmsg);
543 _db_errmsg[0] = 0;
544 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000545#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000546 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
547#else
548 fprintf(stderr, errTxt);
549 fprintf(stderr, "\n");
550#endif
551
552#else /* do an exception instead */
553 errObj = DBIncompleteError;
554#endif
555 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000556#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000557
558 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
559 case DB_KEYEXIST: errObj = DBKeyExistError; break;
560 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
561 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
562 case DB_NOTFOUND: errObj = DBNotFoundError; break;
563 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
564 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
565 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
566 case DB_NOSERVER: errObj = DBNoServerError; break;
567 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
568 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
569#if (DBVER >= 33)
570 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
571 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
572#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000573 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000574
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000575#if (DBVER >= 43)
576 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
577 case ENOMEM: errObj = PyExc_MemoryError; break;
578#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000579 case EINVAL: errObj = DBInvalidArgError; break;
580 case EACCES: errObj = DBAccessError; break;
581 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000582 case EAGAIN: errObj = DBAgainError; break;
583 case EBUSY : errObj = DBBusyError; break;
584 case EEXIST: errObj = DBFileExistsError; break;
585 case ENOENT: errObj = DBNoSuchFileError; break;
586 case EPERM : errObj = DBPermissionsError; break;
587
588 default: errObj = DBError; break;
589 }
590
591 if (errObj != NULL) {
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000592 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000593 if (_db_errmsg[0]) {
594 strcat(errTxt, " -- ");
595 strcat(errTxt, _db_errmsg);
596 _db_errmsg[0] = 0;
597 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000598
599 errTuple = Py_BuildValue("(is)", err, errTxt);
600 PyErr_SetObject(errObj, errTuple);
601 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 }
603
604 return ((errObj != NULL) || exceptionRaised);
605}
606
607
608
609/* set a type exception */
610static void makeTypeError(char* expected, PyObject* found)
611{
612 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
613 expected, found->ob_type->tp_name);
614}
615
616
617/* verify that an obj is either None or a DBTxn, and set the txn pointer */
618static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
619{
620 if (txnobj == Py_None || txnobj == NULL) {
621 *txn = NULL;
622 return 1;
623 }
624 if (DBTxnObject_Check(txnobj)) {
625 *txn = ((DBTxnObject*)txnobj)->txn;
626 return 1;
627 }
628 else
629 makeTypeError("DBTxn", txnobj);
630 return 0;
631}
632
633
634/* Delete a key from a database
635 Returns 0 on success, -1 on an error. */
636static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
637{
638 int err;
639
640 MYDB_BEGIN_ALLOW_THREADS;
641 err = self->db->del(self->db, txn, key, 0);
642 MYDB_END_ALLOW_THREADS;
643 if (makeDBError(err)) {
644 return -1;
645 }
646 self->haveStat = 0;
647 return 0;
648}
649
650
651/* Store a key into a database
652 Returns 0 on success, -1 on an error. */
653static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
654{
655 int err;
656
657 MYDB_BEGIN_ALLOW_THREADS;
658 err = self->db->put(self->db, txn, key, data, flags);
659 MYDB_END_ALLOW_THREADS;
660 if (makeDBError(err)) {
661 return -1;
662 }
663 self->haveStat = 0;
664 return 0;
665}
666
667/* Get a key/data pair from a cursor */
668static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
669 PyObject *args, PyObject *kwargs, char *format)
670{
671 int err;
672 PyObject* retval = NULL;
673 DBT key, data;
674 int dlen = -1;
675 int doff = -1;
676 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000677 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678
679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
680 &flags, &dlen, &doff))
681 return NULL;
682
683 CHECK_CURSOR_NOT_CLOSED(self);
684
685 flags |= extra_flags;
686 CLEAR_DBT(key);
687 CLEAR_DBT(data);
688 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
689 /* Tell BerkeleyDB to malloc the return value (thread safe) */
690 data.flags = DB_DBT_MALLOC;
691 key.flags = DB_DBT_MALLOC;
692 }
693 if (!add_partial_dbt(&data, dlen, doff))
694 return NULL;
695
696 MYDB_BEGIN_ALLOW_THREADS;
697 err = self->dbc->c_get(self->dbc, &key, &data, flags);
698 MYDB_END_ALLOW_THREADS;
699
Gregory P. Smithe9477062005-06-04 06:46:59 +0000700 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
701 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000702 Py_INCREF(Py_None);
703 retval = Py_None;
704 }
705 else if (makeDBError(err)) {
706 retval = NULL;
707 }
708 else { /* otherwise, success! */
709
710 /* if Recno or Queue, return the key as an Int */
711 switch (_DB_get_type(self->mydb)) {
712 case -1:
713 retval = NULL;
714 break;
715
716 case DB_RECNO:
717 case DB_QUEUE:
718 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
719 data.data, data.size);
720 break;
721 case DB_HASH:
722 case DB_BTREE:
723 default:
724 retval = Py_BuildValue("s#s#", key.data, key.size,
725 data.data, data.size);
726 break;
727 }
728 }
729 if (!err) {
730 FREE_DBT(key);
731 FREE_DBT(data);
732 }
733 return retval;
734}
735
736
737/* add an integer to a dictionary using the given name as a key */
738static void _addIntToDict(PyObject* dict, char *name, int value)
739{
740 PyObject* v = PyInt_FromLong((long) value);
741 if (!v || PyDict_SetItemString(dict, name, v))
742 PyErr_Clear();
743
744 Py_XDECREF(v);
745}
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000746#if (DBVER >= 43)
747/* add an db_seq_t to a dictionary using the given name as a key */
748static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
749{
750 PyObject* v = PyLong_FromLongLong(value);
751 if (!v || PyDict_SetItemString(dict, name, v))
752 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000753
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000754 Py_XDECREF(v);
755}
756#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757
758
759
760/* --------------------------------------------------------------------- */
761/* Allocators and deallocators */
762
763static DBObject*
764newDBObject(DBEnvObject* arg, int flags)
765{
766 DBObject* self;
767 DB_ENV* db_env = NULL;
768 int err;
769
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000770 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000771 if (self == NULL)
772 return NULL;
773
774 self->haveStat = 0;
775 self->flags = 0;
776 self->setflags = 0;
777 self->myenvobj = NULL;
778#if (DBVER >= 33)
779 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000780 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000781 self->primaryDBType = 0;
782#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000783#ifdef HAVE_WEAKREF
784 self->in_weakreflist = NULL;
785#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786
787 /* keep a reference to our python DBEnv object */
788 if (arg) {
789 Py_INCREF(arg);
790 self->myenvobj = arg;
791 db_env = arg->db_env;
792 }
793
794 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000795 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000796 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000797 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
798 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000799
800 MYDB_BEGIN_ALLOW_THREADS;
801 err = db_create(&self->db, db_env, flags);
802 self->db->set_errcall(self->db, _db_errorCallback);
803#if (DBVER >= 33)
804 self->db->app_private = (void*)self;
805#endif
806 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000807 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
808 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000809 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000810 if (makeDBError(err)) {
811 if (self->myenvobj) {
812 Py_DECREF(self->myenvobj);
813 self->myenvobj = NULL;
814 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000815 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816 self = NULL;
817 }
818 return self;
819}
820
821
822static void
823DB_dealloc(DBObject* self)
824{
825 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000826 /* avoid closing a DB when its DBEnv has been closed out from under
827 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000829 (self->myenvobj && self->myenvobj->db_env))
830 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000831 MYDB_BEGIN_ALLOW_THREADS;
832 self->db->close(self->db, 0);
833 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000834#ifdef HAVE_WARNINGS
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835 } else {
836 PyErr_Warn(PyExc_RuntimeWarning,
837 "DB could not be closed in destructor: DBEnv already closed");
838#endif
839 }
840 self->db = NULL;
841 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000842#ifdef HAVE_WEAKREF
843 if (self->in_weakreflist != NULL) {
844 PyObject_ClearWeakRefs((PyObject *) self);
845 }
846#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847 if (self->myenvobj) {
848 Py_DECREF(self->myenvobj);
849 self->myenvobj = NULL;
850 }
851#if (DBVER >= 33)
852 if (self->associateCallback != NULL) {
853 Py_DECREF(self->associateCallback);
854 self->associateCallback = NULL;
855 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000856 if (self->btCompareCallback != NULL) {
857 Py_DECREF(self->btCompareCallback);
858 self->btCompareCallback = NULL;
859 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000860#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862}
863
864
865static DBCursorObject*
866newDBCursorObject(DBC* dbc, DBObject* db)
867{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000868 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000869 if (self == NULL)
870 return NULL;
871
872 self->dbc = dbc;
873 self->mydb = db;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000874#ifdef HAVE_WEAKREF
875 self->in_weakreflist = NULL;
876#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000877 Py_INCREF(self->mydb);
878 return self;
879}
880
881
882static void
883DBCursor_dealloc(DBCursorObject* self)
884{
885 int err;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000886
887#ifdef HAVE_WEAKREF
888 if (self->in_weakreflist != NULL) {
889 PyObject_ClearWeakRefs((PyObject *) self);
890 }
891#endif
892
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893 if (self->dbc != NULL) {
894 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000895 /* If the underlying database has been closed, we don't
896 need to do anything. If the environment has been closed
897 we need to leak, as BerkeleyDB will crash trying to access
898 the environment. There was an exception when the
899 user closed the environment even though there still was
900 a database open. */
901 if (self->mydb->db && self->mydb->myenvobj &&
902 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000903 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000904 self->dbc = NULL;
905 MYDB_END_ALLOW_THREADS;
906 }
907 Py_XDECREF( self->mydb );
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909}
910
911
912static DBEnvObject*
913newDBEnvObject(int flags)
914{
915 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000916 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917 if (self == NULL)
918 return NULL;
919
920 self->closed = 1;
921 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000922 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
923 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000924#ifdef HAVE_WEAKREF
925 self->in_weakreflist = NULL;
926#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927
928 MYDB_BEGIN_ALLOW_THREADS;
929 err = db_env_create(&self->db_env, flags);
930 MYDB_END_ALLOW_THREADS;
931 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +0000932 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000933 self = NULL;
934 }
935 else {
936 self->db_env->set_errcall(self->db_env, _db_errorCallback);
937 }
938 return self;
939}
940
941
942static void
943DBEnv_dealloc(DBEnvObject* self)
944{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000945#ifdef HAVE_WEAKREF
946 if (self->in_weakreflist != NULL) {
947 PyObject_ClearWeakRefs((PyObject *) self);
948 }
949#endif
950
Gregory P. Smith4e414d82006-01-24 19:55:02 +0000951 if (self->db_env && !self->closed) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000952 MYDB_BEGIN_ALLOW_THREADS;
953 self->db_env->close(self->db_env, 0);
954 MYDB_END_ALLOW_THREADS;
955 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000957}
958
959
960static DBTxnObject*
961newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
962{
963 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000964 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 if (self == NULL)
966 return NULL;
Neal Norwitz62a21122006-01-25 05:21:55 +0000967 Py_INCREF(myenv);
968 self->env = (PyObject*)myenv;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000969#ifdef HAVE_WEAKREF
970 self->in_weakreflist = NULL;
971#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972
973 MYDB_BEGIN_ALLOW_THREADS;
974#if (DBVER >= 40)
975 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
976#else
977 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
978#endif
979 MYDB_END_ALLOW_THREADS;
980 if (makeDBError(err)) {
Neal Norwitz62a21122006-01-25 05:21:55 +0000981 Py_DECREF(self->env);
982 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983 self = NULL;
984 }
985 return self;
986}
987
988
989static void
990DBTxn_dealloc(DBTxnObject* self)
991{
Gregory P. Smith31c50652004-06-28 01:20:40 +0000992#ifdef HAVE_WEAKREF
993 if (self->in_weakreflist != NULL) {
994 PyObject_ClearWeakRefs((PyObject *) self);
995 }
996#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000997
Gregory P. Smith31c50652004-06-28 01:20:40 +0000998#ifdef HAVE_WARNINGS
999 if (self->txn) {
1000 /* it hasn't been finalized, abort it! */
1001 MYDB_BEGIN_ALLOW_THREADS;
1002#if (DBVER >= 40)
1003 self->txn->abort(self->txn);
1004#else
1005 txn_abort(self->txn);
1006#endif
1007 MYDB_END_ALLOW_THREADS;
1008 PyErr_Warn(PyExc_RuntimeWarning,
1009 "DBTxn aborted in destructor. No prior commit() or abort().");
1010 }
1011#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001012
Neal Norwitz62a21122006-01-25 05:21:55 +00001013 Py_DECREF(self->env);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001015}
1016
1017
1018static DBLockObject*
1019newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1020 db_lockmode_t lock_mode, int flags)
1021{
1022 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001023 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024 if (self == NULL)
1025 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001026#ifdef HAVE_WEAKREF
1027 self->in_weakreflist = NULL;
1028#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029
1030 MYDB_BEGIN_ALLOW_THREADS;
1031#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001032 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1033 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001034#else
1035 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1036#endif
1037 MYDB_END_ALLOW_THREADS;
1038 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001039 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001040 self = NULL;
1041 }
1042
1043 return self;
1044}
1045
1046
1047static void
1048DBLock_dealloc(DBLockObject* self)
1049{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001050#ifdef HAVE_WEAKREF
1051 if (self->in_weakreflist != NULL) {
1052 PyObject_ClearWeakRefs((PyObject *) self);
1053 }
1054#endif
1055 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058}
1059
1060
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001061#if (DBVER >= 43)
1062static DBSequenceObject*
1063newDBSequenceObject(DBObject* mydb, int flags)
1064{
1065 int err;
1066 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1067 if (self == NULL)
1068 return NULL;
1069 Py_INCREF(mydb);
1070 self->mydb = mydb;
1071#ifdef HAVE_WEAKREF
1072 self->in_weakreflist = NULL;
1073#endif
1074
1075
1076 MYDB_BEGIN_ALLOW_THREADS;
1077 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1078 MYDB_END_ALLOW_THREADS;
1079 if (makeDBError(err)) {
1080 Py_DECREF(self->mydb);
1081 PyObject_Del(self);
1082 self = NULL;
1083 }
1084
1085 return self;
1086}
1087
1088
1089static void
1090DBSequence_dealloc(DBSequenceObject* self)
1091{
1092#ifdef HAVE_WEAKREF
1093 if (self->in_weakreflist != NULL) {
1094 PyObject_ClearWeakRefs((PyObject *) self);
1095 }
1096#endif
1097
1098 Py_DECREF(self->mydb);
1099 PyObject_Del(self);
1100}
1101#endif
1102
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001103/* --------------------------------------------------------------------- */
1104/* DB methods */
1105
1106static PyObject*
1107DB_append(DBObject* self, PyObject* args)
1108{
1109 PyObject* txnobj = NULL;
1110 PyObject* dataobj;
1111 db_recno_t recno;
1112 DBT key, data;
1113 DB_TXN *txn = NULL;
1114
Georg Brandl96a8c392006-05-29 21:04:52 +00001115 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001116 return NULL;
1117
1118 CHECK_DB_NOT_CLOSED(self);
1119
1120 /* make a dummy key out of a recno */
1121 recno = 0;
1122 CLEAR_DBT(key);
1123 key.data = &recno;
1124 key.size = sizeof(recno);
1125 key.ulen = key.size;
1126 key.flags = DB_DBT_USERMEM;
1127
1128 if (!make_dbt(dataobj, &data)) return NULL;
1129 if (!checkTxnObj(txnobj, &txn)) return NULL;
1130
1131 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1132 return NULL;
1133
1134 return PyInt_FromLong(recno);
1135}
1136
1137
1138#if (DBVER >= 33)
1139
1140static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001141_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1142 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001143{
1144 int retval = DB_DONOTINDEX;
1145 DBObject* secondaryDB = (DBObject*)db->app_private;
1146 PyObject* callback = secondaryDB->associateCallback;
1147 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001148 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001149 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001150
1151
1152 if (callback != NULL) {
1153 MYDB_BEGIN_BLOCK_THREADS;
1154
Thomas Woutersb3153832006-03-08 01:47:19 +00001155 if (type == DB_RECNO || type == DB_QUEUE)
1156 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1157 priData->data, priData->size);
1158 else
1159 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1160 priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001161 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001162 result = PyEval_CallObject(callback, args);
1163 }
1164 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001165 PyErr_Print();
1166 }
1167 else if (result == Py_None) {
1168 retval = DB_DONOTINDEX;
1169 }
1170 else if (PyInt_Check(result)) {
1171 retval = PyInt_AsLong(result);
1172 }
1173 else if (PyString_Check(result)) {
1174 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001175 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176
1177 CLEAR_DBT(*secKey);
1178#if PYTHON_API_VERSION <= 1007
1179 /* 1.5 compatibility */
1180 size = PyString_Size(result);
1181 data = PyString_AsString(result);
1182#else
1183 PyString_AsStringAndSize(result, &data, &size);
1184#endif
1185 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1186 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001187 if (secKey->data) {
1188 memcpy(secKey->data, data, size);
1189 secKey->size = size;
1190 retval = 0;
1191 }
1192 else {
1193 PyErr_SetString(PyExc_MemoryError,
1194 "malloc failed in _db_associateCallback");
1195 PyErr_Print();
1196 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001197 }
1198 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001199 PyErr_SetString(
1200 PyExc_TypeError,
1201 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001202 PyErr_Print();
1203 }
1204
Thomas Woutersb3153832006-03-08 01:47:19 +00001205 Py_XDECREF(args);
1206 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207
1208 MYDB_END_BLOCK_THREADS;
1209 }
1210 return retval;
1211}
1212
1213
1214static PyObject*
1215DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1216{
1217 int err, flags=0;
1218 DBObject* secondaryDB;
1219 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001220#if (DBVER >= 41)
1221 PyObject *txnobj = NULL;
1222 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001223 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001224 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001225#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001226 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001227#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001228
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001229#if (DBVER >= 41)
1230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1231 &secondaryDB, &callback, &flags,
1232 &txnobj)) {
1233#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001235 &secondaryDB, &callback, &flags)) {
1236#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001238 }
1239
1240#if (DBVER >= 41)
1241 if (!checkTxnObj(txnobj, &txn)) return NULL;
1242#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001243
1244 CHECK_DB_NOT_CLOSED(self);
1245 if (!DBObject_Check(secondaryDB)) {
1246 makeTypeError("DB", (PyObject*)secondaryDB);
1247 return NULL;
1248 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001249 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250 if (callback == Py_None) {
1251 callback = NULL;
1252 }
1253 else if (!PyCallable_Check(callback)) {
1254 makeTypeError("Callable", callback);
1255 return NULL;
1256 }
1257
1258 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001259 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001260 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001261 secondaryDB->associateCallback = callback;
1262 secondaryDB->primaryDBType = _DB_get_type(self);
1263
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001264 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1265 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1266 * The global interepreter lock is not initialized until the first
1267 * thread is created using thread.start_new_thread() or fork() is
1268 * called. that would cause the ALLOW_THREADS here to segfault due
1269 * to a null pointer reference if no threads or child processes
1270 * have been created. This works around that and is a no-op if
1271 * threads have already been initialized.
1272 * (see pybsddb-users mailing list post on 2002-08-07)
1273 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001274#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001275 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001276#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001278#if (DBVER >= 41)
1279 err = self->db->associate(self->db,
1280 txn,
1281 secondaryDB->db,
1282 _db_associateCallback,
1283 flags);
1284#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 err = self->db->associate(self->db,
1286 secondaryDB->db,
1287 _db_associateCallback,
1288 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001289#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290 MYDB_END_ALLOW_THREADS;
1291
1292 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001293 Py_XDECREF(secondaryDB->associateCallback);
1294 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001295 secondaryDB->primaryDBType = 0;
1296 }
1297
1298 RETURN_IF_ERR();
1299 RETURN_NONE();
1300}
1301
1302
1303#endif
1304
1305
1306static PyObject*
1307DB_close(DBObject* self, PyObject* args)
1308{
1309 int err, flags=0;
1310 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1311 return NULL;
1312 if (self->db != NULL) {
1313 if (self->myenvobj)
1314 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001315 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 self->db = NULL;
1317 RETURN_IF_ERR();
1318 }
1319 RETURN_NONE();
1320}
1321
1322
1323#if (DBVER >= 32)
1324static PyObject*
1325_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1326{
1327 int err, flags=0, type;
1328 PyObject* txnobj = NULL;
1329 PyObject* retval = NULL;
1330 DBT key, data;
1331 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001332 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333
1334 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1335 &txnobj, &flags))
1336 return NULL;
1337
1338 CHECK_DB_NOT_CLOSED(self);
1339 type = _DB_get_type(self);
1340 if (type == -1)
1341 return NULL;
1342 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001343 PyErr_SetString(PyExc_TypeError,
1344 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345 return NULL;
1346 }
1347 if (!checkTxnObj(txnobj, &txn))
1348 return NULL;
1349
1350 CLEAR_DBT(key);
1351 CLEAR_DBT(data);
1352 if (CHECK_DBFLAG(self, DB_THREAD)) {
1353 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1354 data.flags = DB_DBT_MALLOC;
1355 key.flags = DB_DBT_MALLOC;
1356 }
1357
1358 MYDB_BEGIN_ALLOW_THREADS;
1359 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1360 MYDB_END_ALLOW_THREADS;
1361
Gregory P. Smithe9477062005-06-04 06:46:59 +00001362 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1363 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364 err = 0;
1365 Py_INCREF(Py_None);
1366 retval = Py_None;
1367 }
1368 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1370 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 FREE_DBT(key);
1372 FREE_DBT(data);
1373 }
1374
1375 RETURN_IF_ERR();
1376 return retval;
1377}
1378
1379static PyObject*
1380DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1381{
1382 return _DB_consume(self, args, kwargs, DB_CONSUME);
1383}
1384
1385static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001386DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1387 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001388{
1389 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1390}
1391#endif
1392
1393
1394
1395static PyObject*
1396DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1397{
1398 int err, flags=0;
1399 DBC* dbc;
1400 PyObject* txnobj = NULL;
1401 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001402 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403
1404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1405 &txnobj, &flags))
1406 return NULL;
1407 CHECK_DB_NOT_CLOSED(self);
1408 if (!checkTxnObj(txnobj, &txn))
1409 return NULL;
1410
1411 MYDB_BEGIN_ALLOW_THREADS;
1412 err = self->db->cursor(self->db, txn, &dbc, flags);
1413 MYDB_END_ALLOW_THREADS;
1414 RETURN_IF_ERR();
1415 return (PyObject*) newDBCursorObject(dbc, self);
1416}
1417
1418
1419static PyObject*
1420DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1421{
1422 PyObject* txnobj = NULL;
1423 int flags = 0;
1424 PyObject* keyobj;
1425 DBT key;
1426 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001427 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428
1429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1430 &keyobj, &txnobj, &flags))
1431 return NULL;
1432 CHECK_DB_NOT_CLOSED(self);
1433 if (!make_key_dbt(self, keyobj, &key, NULL))
1434 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001435 if (!checkTxnObj(txnobj, &txn)) {
1436 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001438 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001440 if (-1 == _DB_delete(self, txn, &key, 0)) {
1441 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001443 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001444
1445 FREE_DBT(key);
1446 RETURN_NONE();
1447}
1448
1449
1450static PyObject*
1451DB_fd(DBObject* self, PyObject* args)
1452{
1453 int err, the_fd;
1454
1455 if (!PyArg_ParseTuple(args,":fd"))
1456 return NULL;
1457 CHECK_DB_NOT_CLOSED(self);
1458
1459 MYDB_BEGIN_ALLOW_THREADS;
1460 err = self->db->fd(self->db, &the_fd);
1461 MYDB_END_ALLOW_THREADS;
1462 RETURN_IF_ERR();
1463 return PyInt_FromLong(the_fd);
1464}
1465
1466
1467static PyObject*
1468DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1469{
1470 int err, flags=0;
1471 PyObject* txnobj = NULL;
1472 PyObject* keyobj;
1473 PyObject* dfltobj = NULL;
1474 PyObject* retval = NULL;
1475 int dlen = -1;
1476 int doff = -1;
1477 DBT key, data;
1478 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001479 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001480 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001481
1482 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001483 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1484 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001485 return NULL;
1486
1487 CHECK_DB_NOT_CLOSED(self);
1488 if (!make_key_dbt(self, keyobj, &key, &flags))
1489 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001490 if (!checkTxnObj(txnobj, &txn)) {
1491 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001492 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001493 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001494
1495 CLEAR_DBT(data);
1496 if (CHECK_DBFLAG(self, DB_THREAD)) {
1497 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1498 data.flags = DB_DBT_MALLOC;
1499 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001500 if (!add_partial_dbt(&data, dlen, doff)) {
1501 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001502 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001503 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001504
1505 MYDB_BEGIN_ALLOW_THREADS;
1506 err = self->db->get(self->db, txn, &key, &data, flags);
1507 MYDB_END_ALLOW_THREADS;
1508
Gregory P. Smithe9477062005-06-04 06:46:59 +00001509 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001510 err = 0;
1511 Py_INCREF(dfltobj);
1512 retval = dfltobj;
1513 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001514 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1515 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001516 err = 0;
1517 Py_INCREF(Py_None);
1518 retval = Py_None;
1519 }
1520 else if (!err) {
1521 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001522 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1523 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 else /* return just the data */
1525 retval = PyString_FromStringAndSize((char*)data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001526 FREE_DBT(data);
1527 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001528 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529
1530 RETURN_IF_ERR();
1531 return retval;
1532}
1533
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001534#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001535static PyObject*
1536DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1537{
1538 int err, flags=0;
1539 PyObject* txnobj = NULL;
1540 PyObject* keyobj;
1541 PyObject* dfltobj = NULL;
1542 PyObject* retval = NULL;
1543 int dlen = -1;
1544 int doff = -1;
1545 DBT key, pkey, data;
1546 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001547 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001548 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001549
1550 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1551 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1552 &doff))
1553 return NULL;
1554
1555 CHECK_DB_NOT_CLOSED(self);
1556 if (!make_key_dbt(self, keyobj, &key, &flags))
1557 return NULL;
1558 if (!checkTxnObj(txnobj, &txn)) {
1559 FREE_DBT(key);
1560 return NULL;
1561 }
1562
1563 CLEAR_DBT(data);
1564 if (CHECK_DBFLAG(self, DB_THREAD)) {
1565 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1566 data.flags = DB_DBT_MALLOC;
1567 }
1568 if (!add_partial_dbt(&data, dlen, doff)) {
1569 FREE_DBT(key);
1570 return NULL;
1571 }
1572
1573 CLEAR_DBT(pkey);
1574 pkey.flags = DB_DBT_MALLOC;
1575
1576 MYDB_BEGIN_ALLOW_THREADS;
1577 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1578 MYDB_END_ALLOW_THREADS;
1579
Gregory P. Smithe9477062005-06-04 06:46:59 +00001580 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001581 err = 0;
1582 Py_INCREF(dfltobj);
1583 retval = dfltobj;
1584 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001585 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1586 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001587 err = 0;
1588 Py_INCREF(Py_None);
1589 retval = Py_None;
1590 }
1591 else if (!err) {
1592 PyObject *pkeyObj;
1593 PyObject *dataObj;
1594 dataObj = PyString_FromStringAndSize(data.data, data.size);
1595
1596 if (self->primaryDBType == DB_RECNO ||
1597 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001598 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001599 else
1600 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1601
1602 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1603 {
1604 PyObject *keyObj;
1605 int type = _DB_get_type(self);
1606 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001607 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001608 else
1609 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001610#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001611 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001612#else
1613 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1614#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001615 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001616 }
1617 else /* return just the pkey and data */
1618 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001619#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001620 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001621#else
1622 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1623#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001624 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001625 Py_DECREF(dataObj);
1626 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001627 FREE_DBT(pkey);
1628 FREE_DBT(data);
1629 }
1630 FREE_DBT(key);
1631
1632 RETURN_IF_ERR();
1633 return retval;
1634}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001635#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001636
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637
1638/* Return size of entry */
1639static PyObject*
1640DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1641{
1642 int err, flags=0;
1643 PyObject* txnobj = NULL;
1644 PyObject* keyobj;
1645 PyObject* retval = NULL;
1646 DBT key, data;
1647 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001648 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649
1650 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1651 &keyobj, &txnobj))
1652 return NULL;
1653 CHECK_DB_NOT_CLOSED(self);
1654 if (!make_key_dbt(self, keyobj, &key, &flags))
1655 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001656 if (!checkTxnObj(txnobj, &txn)) {
1657 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001659 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001660 CLEAR_DBT(data);
1661
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001662 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1663 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 data.flags = DB_DBT_USERMEM;
1665 data.ulen = 0;
1666 MYDB_BEGIN_ALLOW_THREADS;
1667 err = self->db->get(self->db, txn, &key, &data, flags);
1668 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001669 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001670 retval = PyInt_FromLong((long)data.size);
1671 err = 0;
1672 }
1673
1674 FREE_DBT(key);
1675 FREE_DBT(data);
1676 RETURN_IF_ERR();
1677 return retval;
1678}
1679
1680
1681static PyObject*
1682DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1683{
1684 int err, flags=0;
1685 PyObject* txnobj = NULL;
1686 PyObject* keyobj;
1687 PyObject* dataobj;
1688 PyObject* retval = NULL;
1689 DBT key, data;
1690 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001691 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001692
1693
1694 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1695 &keyobj, &dataobj, &txnobj, &flags))
1696 return NULL;
1697
1698 CHECK_DB_NOT_CLOSED(self);
1699 if (!make_key_dbt(self, keyobj, &key, NULL))
1700 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001701 if ( !make_dbt(dataobj, &data) ||
1702 !checkTxnObj(txnobj, &txn) )
1703 {
1704 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001705 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001706 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001707
1708 flags |= DB_GET_BOTH;
1709
1710 if (CHECK_DBFLAG(self, DB_THREAD)) {
1711 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1712 data.flags = DB_DBT_MALLOC;
1713 /* TODO: Is this flag needed? We're passing a data object that should
1714 match what's in the DB, so there should be no need to malloc.
1715 We run the risk of freeing something twice! Check this. */
1716 }
1717
1718 MYDB_BEGIN_ALLOW_THREADS;
1719 err = self->db->get(self->db, txn, &key, &data, flags);
1720 MYDB_END_ALLOW_THREADS;
1721
Gregory P. Smithe9477062005-06-04 06:46:59 +00001722 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1723 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001724 err = 0;
1725 Py_INCREF(Py_None);
1726 retval = Py_None;
1727 }
1728 else if (!err) {
1729 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1730 FREE_DBT(data); /* Only if retrieval was successful */
1731 }
1732
1733 FREE_DBT(key);
1734 RETURN_IF_ERR();
1735 return retval;
1736}
1737
1738
1739static PyObject*
1740DB_get_byteswapped(DBObject* self, PyObject* args)
1741{
1742#if (DBVER >= 33)
1743 int err = 0;
1744#endif
1745 int retval = -1;
1746
1747 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1748 return NULL;
1749 CHECK_DB_NOT_CLOSED(self);
1750
1751#if (DBVER >= 33)
1752 MYDB_BEGIN_ALLOW_THREADS;
1753 err = self->db->get_byteswapped(self->db, &retval);
1754 MYDB_END_ALLOW_THREADS;
1755 RETURN_IF_ERR();
1756#else
1757 MYDB_BEGIN_ALLOW_THREADS;
1758 retval = self->db->get_byteswapped(self->db);
1759 MYDB_END_ALLOW_THREADS;
1760#endif
1761 return PyInt_FromLong(retval);
1762}
1763
1764
1765static PyObject*
1766DB_get_type(DBObject* self, PyObject* args)
1767{
1768 int type;
1769
1770 if (!PyArg_ParseTuple(args,":get_type"))
1771 return NULL;
1772 CHECK_DB_NOT_CLOSED(self);
1773
1774 MYDB_BEGIN_ALLOW_THREADS;
1775 type = _DB_get_type(self);
1776 MYDB_END_ALLOW_THREADS;
1777 if (type == -1)
1778 return NULL;
1779 return PyInt_FromLong(type);
1780}
1781
1782
1783static PyObject*
1784DB_join(DBObject* self, PyObject* args)
1785{
1786 int err, flags=0;
1787 int length, x;
1788 PyObject* cursorsObj;
1789 DBC** cursors;
1790 DBC* dbc;
1791
1792
1793 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1794 return NULL;
1795
1796 CHECK_DB_NOT_CLOSED(self);
1797
1798 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001799 PyErr_SetString(PyExc_TypeError,
1800 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 return NULL;
1802 }
1803
1804 length = PyObject_Length(cursorsObj);
1805 cursors = malloc((length+1) * sizeof(DBC*));
1806 cursors[length] = NULL;
1807 for (x=0; x<length; x++) {
1808 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001809 if (item == NULL) {
1810 free(cursors);
1811 return NULL;
1812 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001813 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001814 PyErr_SetString(PyExc_TypeError,
1815 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001816 free(cursors);
1817 return NULL;
1818 }
1819 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001820 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 }
1822
1823 MYDB_BEGIN_ALLOW_THREADS;
1824 err = self->db->join(self->db, cursors, &dbc, flags);
1825 MYDB_END_ALLOW_THREADS;
1826 free(cursors);
1827 RETURN_IF_ERR();
1828
Gregory P. Smith7441e652003-11-03 21:35:31 +00001829 /* FIXME: this is a buggy interface. The returned cursor
1830 contains internal references to the passed in cursors
1831 but does not hold python references to them or prevent
1832 them from being closed prematurely. This can cause
1833 python to crash when things are done in the wrong order. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001834 return (PyObject*) newDBCursorObject(dbc, self);
1835}
1836
1837
1838static PyObject*
1839DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1840{
1841 int err, flags=0;
1842 PyObject* txnobj = NULL;
1843 PyObject* keyobj;
1844 DBT key;
1845 DB_TXN *txn = NULL;
1846 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001847 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848
1849 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1850 &keyobj, &txnobj, &flags))
1851 return NULL;
1852 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001853 if (!make_dbt(keyobj, &key))
1854 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 return NULL;
1856 if (!checkTxnObj(txnobj, &txn))
1857 return NULL;
1858
1859 MYDB_BEGIN_ALLOW_THREADS;
1860 err = self->db->key_range(self->db, txn, &key, &range, flags);
1861 MYDB_END_ALLOW_THREADS;
1862
1863 RETURN_IF_ERR();
1864 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1865}
1866
1867
1868static PyObject*
1869DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1870{
1871 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1872 char* filename = NULL;
1873 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001874#if (DBVER >= 41)
1875 PyObject *txnobj = NULL;
1876 DB_TXN *txn = NULL;
1877 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001878 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001879 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1880 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00001881 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001882 "filename", "dbtype", "flags", "mode", "txn", NULL};
1883#else
1884 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001885 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001886 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1887 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001888 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001889 "filename", "dbtype", "flags", "mode", NULL};
1890#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001891
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001892#if (DBVER >= 41)
1893 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1894 &filename, &dbname, &type, &flags, &mode,
1895 &txnobj))
1896#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001897 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001898 &filename, &dbname, &type, &flags,
1899 &mode))
1900#endif
1901 {
1902 PyErr_Clear();
1903 type = DB_UNKNOWN; flags = 0; mode = 0660;
1904 filename = NULL; dbname = NULL;
1905#if (DBVER >= 41)
1906 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1907 kwnames_basic,
1908 &filename, &type, &flags, &mode,
1909 &txnobj))
1910 return NULL;
1911#else
1912 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1913 kwnames_basic,
1914 &filename, &type, &flags, &mode))
1915 return NULL;
1916#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 }
1918
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001919#if (DBVER >= 41)
1920 if (!checkTxnObj(txnobj, &txn)) return NULL;
1921#endif
1922
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001923 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001924 PyObject *t = Py_BuildValue("(is)", 0,
1925 "Cannot call open() twice for DB object");
1926 PyErr_SetObject(DBError, t);
1927 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 return NULL;
1929 }
1930
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001931#if 0 && (DBVER >= 41)
1932 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1933 && (self->myenvobj->flags & DB_INIT_TXN))
1934 {
1935 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1936 * explicitly passed) but we are in a transaction ready environment:
1937 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1938 * to work on BerkeleyDB 4.1 without needing to modify their
1939 * DBEnv or DB open calls.
1940 * TODO make this behaviour of the library configurable.
1941 */
1942 flags |= DB_AUTO_COMMIT;
1943 }
1944#endif
1945
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001947#if (DBVER >= 41)
1948 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1949#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001951#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 MYDB_END_ALLOW_THREADS;
1953 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001954 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001955 self->db = NULL;
1956 return NULL;
1957 }
1958
1959 self->flags = flags;
1960 RETURN_NONE();
1961}
1962
1963
1964static PyObject*
1965DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1966{
1967 int flags=0;
1968 PyObject* txnobj = NULL;
1969 int dlen = -1;
1970 int doff = -1;
1971 PyObject* keyobj, *dataobj, *retval;
1972 DBT key, data;
1973 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001974 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001975 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001976
1977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1978 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1979 return NULL;
1980
1981 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001982 if (!make_key_dbt(self, keyobj, &key, NULL))
1983 return NULL;
1984 if ( !make_dbt(dataobj, &data) ||
1985 !add_partial_dbt(&data, dlen, doff) ||
1986 !checkTxnObj(txnobj, &txn) )
1987 {
1988 FREE_DBT(key);
1989 return NULL;
1990 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001991
1992 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1993 FREE_DBT(key);
1994 return NULL;
1995 }
1996
1997 if (flags & DB_APPEND)
1998 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1999 else {
2000 retval = Py_None;
2001 Py_INCREF(retval);
2002 }
2003 FREE_DBT(key);
2004 return retval;
2005}
2006
2007
2008
2009static PyObject*
2010DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2011{
2012 char* filename;
2013 char* database = NULL;
2014 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002015 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002016
2017 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2018 &filename, &database, &flags))
2019 return NULL;
2020 CHECK_DB_NOT_CLOSED(self);
2021
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002022 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002023 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002024 RETURN_IF_ERR();
2025 RETURN_NONE();
2026}
2027
2028
2029
2030static PyObject*
2031DB_rename(DBObject* self, PyObject* args)
2032{
2033 char* filename;
2034 char* database;
2035 char* newname;
2036 int err, flags=0;
2037
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002038 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2039 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002040 return NULL;
2041 CHECK_DB_NOT_CLOSED(self);
2042
2043 MYDB_BEGIN_ALLOW_THREADS;
2044 err = self->db->rename(self->db, filename, database, newname, flags);
2045 MYDB_END_ALLOW_THREADS;
2046 RETURN_IF_ERR();
2047 RETURN_NONE();
2048}
2049
2050
2051static PyObject*
2052DB_set_bt_minkey(DBObject* self, PyObject* args)
2053{
2054 int err, minkey;
2055
2056 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2057 return NULL;
2058 CHECK_DB_NOT_CLOSED(self);
2059
2060 MYDB_BEGIN_ALLOW_THREADS;
2061 err = self->db->set_bt_minkey(self->db, minkey);
2062 MYDB_END_ALLOW_THREADS;
2063 RETURN_IF_ERR();
2064 RETURN_NONE();
2065}
2066
Neal Norwitz84562352005-10-20 04:30:15 +00002067#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002068static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002069_default_cmp(const DBT *leftKey,
2070 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002071{
2072 int res;
2073 int lsize = leftKey->size, rsize = rightKey->size;
2074
Georg Brandlef1701f2006-03-07 14:57:48 +00002075 res = memcmp(leftKey->data, rightKey->data,
2076 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002077
2078 if (res == 0) {
2079 if (lsize < rsize) {
2080 res = -1;
2081 }
2082 else if (lsize > rsize) {
2083 res = 1;
2084 }
2085 }
2086 return res;
2087}
2088
2089static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002090_db_compareCallback(DB* db,
2091 const DBT *leftKey,
2092 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002093{
2094 int res = 0;
2095 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002096 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002097 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002098
2099 if (self == NULL || self->btCompareCallback == NULL) {
2100 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002101 PyErr_SetString(PyExc_TypeError,
2102 (self == 0
2103 ? "DB_bt_compare db is NULL."
2104 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002105 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002106 PyErr_Print();
2107 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002108 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002109 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002110 MYDB_BEGIN_BLOCK_THREADS;
2111
Thomas Woutersb3153832006-03-08 01:47:19 +00002112 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2113 rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002114 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002115 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002116 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002117 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002118 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002119 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002120 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002121 PyErr_Print();
2122 res = _default_cmp(leftKey, rightKey);
2123 } else if (PyInt_Check(result)) {
2124 res = PyInt_AsLong(result);
2125 } else {
2126 PyErr_SetString(PyExc_TypeError,
2127 "DB_bt_compare callback MUST return an int.");
2128 /* we're in a callback within the DB code, we can't raise */
2129 PyErr_Print();
2130 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002131 }
2132
Thomas Woutersb3153832006-03-08 01:47:19 +00002133 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002134 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002135
2136 MYDB_END_BLOCK_THREADS;
2137 }
2138 return res;
2139}
2140
2141static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002142DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002143{
2144 int err;
2145 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002146 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002147
Georg Brandlef1701f2006-03-07 14:57:48 +00002148 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002149 return NULL;
2150
Georg Brandlef1701f2006-03-07 14:57:48 +00002151 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002152
Georg Brandlef1701f2006-03-07 14:57:48 +00002153 if (!PyCallable_Check(comparator)) {
2154 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002155 return NULL;
2156 }
2157
2158 /*
2159 * Perform a test call of the comparator function with two empty
2160 * string objects here. verify that it returns an int (0).
2161 * err if not.
2162 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002163 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002164 result = PyEval_CallObject(comparator, tuple);
2165 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002166 if (result == NULL)
2167 return NULL;
2168 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002169 PyErr_SetString(PyExc_TypeError,
2170 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002171 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002172 } else if (PyInt_AsLong(result) != 0) {
2173 PyErr_SetString(PyExc_TypeError,
2174 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002175 return NULL;
2176 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002177 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002178
2179 /* We don't accept multiple set_bt_compare operations, in order to
2180 * simplify the code. This would have no real use, as one cannot
2181 * change the function once the db is opened anyway */
2182 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002183 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002184 return NULL;
2185 }
2186
Georg Brandlef1701f2006-03-07 14:57:48 +00002187 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002188 self->btCompareCallback = comparator;
2189
2190 /* This is to workaround a problem with un-initialized threads (see
2191 comment in DB_associate) */
2192#ifdef WITH_THREAD
2193 PyEval_InitThreads();
2194#endif
2195
Thomas Woutersb3153832006-03-08 01:47:19 +00002196 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002197
2198 if (err) {
2199 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002200 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002201 self->btCompareCallback = NULL;
2202 }
2203
Georg Brandlef1701f2006-03-07 14:57:48 +00002204 RETURN_IF_ERR();
2205 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002206}
Neal Norwitz84562352005-10-20 04:30:15 +00002207#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002208
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002209
2210static PyObject*
2211DB_set_cachesize(DBObject* self, PyObject* args)
2212{
2213 int err;
2214 int gbytes = 0, bytes = 0, ncache = 0;
2215
2216 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2217 &gbytes,&bytes,&ncache))
2218 return NULL;
2219 CHECK_DB_NOT_CLOSED(self);
2220
2221 MYDB_BEGIN_ALLOW_THREADS;
2222 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2223 MYDB_END_ALLOW_THREADS;
2224 RETURN_IF_ERR();
2225 RETURN_NONE();
2226}
2227
2228
2229static PyObject*
2230DB_set_flags(DBObject* self, PyObject* args)
2231{
2232 int err, flags;
2233
2234 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2235 return NULL;
2236 CHECK_DB_NOT_CLOSED(self);
2237
2238 MYDB_BEGIN_ALLOW_THREADS;
2239 err = self->db->set_flags(self->db, flags);
2240 MYDB_END_ALLOW_THREADS;
2241 RETURN_IF_ERR();
2242
2243 self->setflags |= flags;
2244 RETURN_NONE();
2245}
2246
2247
2248static PyObject*
2249DB_set_h_ffactor(DBObject* self, PyObject* args)
2250{
2251 int err, ffactor;
2252
2253 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2254 return NULL;
2255 CHECK_DB_NOT_CLOSED(self);
2256
2257 MYDB_BEGIN_ALLOW_THREADS;
2258 err = self->db->set_h_ffactor(self->db, ffactor);
2259 MYDB_END_ALLOW_THREADS;
2260 RETURN_IF_ERR();
2261 RETURN_NONE();
2262}
2263
2264
2265static PyObject*
2266DB_set_h_nelem(DBObject* self, PyObject* args)
2267{
2268 int err, nelem;
2269
2270 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2271 return NULL;
2272 CHECK_DB_NOT_CLOSED(self);
2273
2274 MYDB_BEGIN_ALLOW_THREADS;
2275 err = self->db->set_h_nelem(self->db, nelem);
2276 MYDB_END_ALLOW_THREADS;
2277 RETURN_IF_ERR();
2278 RETURN_NONE();
2279}
2280
2281
2282static PyObject*
2283DB_set_lorder(DBObject* self, PyObject* args)
2284{
2285 int err, lorder;
2286
2287 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2288 return NULL;
2289 CHECK_DB_NOT_CLOSED(self);
2290
2291 MYDB_BEGIN_ALLOW_THREADS;
2292 err = self->db->set_lorder(self->db, lorder);
2293 MYDB_END_ALLOW_THREADS;
2294 RETURN_IF_ERR();
2295 RETURN_NONE();
2296}
2297
2298
2299static PyObject*
2300DB_set_pagesize(DBObject* self, PyObject* args)
2301{
2302 int err, pagesize;
2303
2304 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2305 return NULL;
2306 CHECK_DB_NOT_CLOSED(self);
2307
2308 MYDB_BEGIN_ALLOW_THREADS;
2309 err = self->db->set_pagesize(self->db, pagesize);
2310 MYDB_END_ALLOW_THREADS;
2311 RETURN_IF_ERR();
2312 RETURN_NONE();
2313}
2314
2315
2316static PyObject*
2317DB_set_re_delim(DBObject* self, PyObject* args)
2318{
2319 int err;
2320 char delim;
2321
2322 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2323 PyErr_Clear();
2324 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2325 return NULL;
2326 }
2327
2328 CHECK_DB_NOT_CLOSED(self);
2329
2330 MYDB_BEGIN_ALLOW_THREADS;
2331 err = self->db->set_re_delim(self->db, delim);
2332 MYDB_END_ALLOW_THREADS;
2333 RETURN_IF_ERR();
2334 RETURN_NONE();
2335}
2336
2337static PyObject*
2338DB_set_re_len(DBObject* self, PyObject* args)
2339{
2340 int err, len;
2341
2342 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2343 return NULL;
2344 CHECK_DB_NOT_CLOSED(self);
2345
2346 MYDB_BEGIN_ALLOW_THREADS;
2347 err = self->db->set_re_len(self->db, len);
2348 MYDB_END_ALLOW_THREADS;
2349 RETURN_IF_ERR();
2350 RETURN_NONE();
2351}
2352
2353
2354static PyObject*
2355DB_set_re_pad(DBObject* self, PyObject* args)
2356{
2357 int err;
2358 char pad;
2359
2360 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2361 PyErr_Clear();
2362 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2363 return NULL;
2364 }
2365 CHECK_DB_NOT_CLOSED(self);
2366
2367 MYDB_BEGIN_ALLOW_THREADS;
2368 err = self->db->set_re_pad(self->db, pad);
2369 MYDB_END_ALLOW_THREADS;
2370 RETURN_IF_ERR();
2371 RETURN_NONE();
2372}
2373
2374
2375static PyObject*
2376DB_set_re_source(DBObject* self, PyObject* args)
2377{
2378 int err;
2379 char *re_source;
2380
2381 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2382 return NULL;
2383 CHECK_DB_NOT_CLOSED(self);
2384
2385 MYDB_BEGIN_ALLOW_THREADS;
2386 err = self->db->set_re_source(self->db, re_source);
2387 MYDB_END_ALLOW_THREADS;
2388 RETURN_IF_ERR();
2389 RETURN_NONE();
2390}
2391
2392
2393#if (DBVER >= 32)
2394static PyObject*
2395DB_set_q_extentsize(DBObject* self, PyObject* args)
2396{
2397 int err;
2398 int extentsize;
2399
2400 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2401 return NULL;
2402 CHECK_DB_NOT_CLOSED(self);
2403
2404 MYDB_BEGIN_ALLOW_THREADS;
2405 err = self->db->set_q_extentsize(self->db, extentsize);
2406 MYDB_END_ALLOW_THREADS;
2407 RETURN_IF_ERR();
2408 RETURN_NONE();
2409}
2410#endif
2411
2412static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002413DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002414{
2415 int err, flags = 0, type;
2416 void* sp;
2417 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002418#if (DBVER >= 43)
2419 PyObject* txnobj = NULL;
2420 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002421 static char* kwnames[] = { "txn", "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002422#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002423 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002424#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002425
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002426#if (DBVER >= 43)
2427 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2428 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002429 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002430 if (!checkTxnObj(txnobj, &txn))
2431 return NULL;
2432#else
2433 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2434 return NULL;
2435#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002436 CHECK_DB_NOT_CLOSED(self);
2437
2438 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002439#if (DBVER >= 43)
2440 err = self->db->stat(self->db, txn, &sp, flags);
2441#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002442 err = self->db->stat(self->db, &sp, flags);
2443#else
2444 err = self->db->stat(self->db, &sp, NULL, flags);
2445#endif
2446 MYDB_END_ALLOW_THREADS;
2447 RETURN_IF_ERR();
2448
2449 self->haveStat = 1;
2450
2451 /* Turn the stat structure into a dictionary */
2452 type = _DB_get_type(self);
2453 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2454 free(sp);
2455 return NULL;
2456 }
2457
2458#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2459#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2460#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2461
2462 switch (type) {
2463 case DB_HASH:
2464 MAKE_HASH_ENTRY(magic);
2465 MAKE_HASH_ENTRY(version);
2466 MAKE_HASH_ENTRY(nkeys);
2467 MAKE_HASH_ENTRY(ndata);
2468 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002469#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002470 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002471#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002472 MAKE_HASH_ENTRY(ffactor);
2473 MAKE_HASH_ENTRY(buckets);
2474 MAKE_HASH_ENTRY(free);
2475 MAKE_HASH_ENTRY(bfree);
2476 MAKE_HASH_ENTRY(bigpages);
2477 MAKE_HASH_ENTRY(big_bfree);
2478 MAKE_HASH_ENTRY(overflows);
2479 MAKE_HASH_ENTRY(ovfl_free);
2480 MAKE_HASH_ENTRY(dup);
2481 MAKE_HASH_ENTRY(dup_free);
2482 break;
2483
2484 case DB_BTREE:
2485 case DB_RECNO:
2486 MAKE_BT_ENTRY(magic);
2487 MAKE_BT_ENTRY(version);
2488 MAKE_BT_ENTRY(nkeys);
2489 MAKE_BT_ENTRY(ndata);
2490 MAKE_BT_ENTRY(pagesize);
2491 MAKE_BT_ENTRY(minkey);
2492 MAKE_BT_ENTRY(re_len);
2493 MAKE_BT_ENTRY(re_pad);
2494 MAKE_BT_ENTRY(levels);
2495 MAKE_BT_ENTRY(int_pg);
2496 MAKE_BT_ENTRY(leaf_pg);
2497 MAKE_BT_ENTRY(dup_pg);
2498 MAKE_BT_ENTRY(over_pg);
2499 MAKE_BT_ENTRY(free);
2500 MAKE_BT_ENTRY(int_pgfree);
2501 MAKE_BT_ENTRY(leaf_pgfree);
2502 MAKE_BT_ENTRY(dup_pgfree);
2503 MAKE_BT_ENTRY(over_pgfree);
2504 break;
2505
2506 case DB_QUEUE:
2507 MAKE_QUEUE_ENTRY(magic);
2508 MAKE_QUEUE_ENTRY(version);
2509 MAKE_QUEUE_ENTRY(nkeys);
2510 MAKE_QUEUE_ENTRY(ndata);
2511 MAKE_QUEUE_ENTRY(pagesize);
2512 MAKE_QUEUE_ENTRY(pages);
2513 MAKE_QUEUE_ENTRY(re_len);
2514 MAKE_QUEUE_ENTRY(re_pad);
2515 MAKE_QUEUE_ENTRY(pgfree);
2516#if (DBVER == 31)
2517 MAKE_QUEUE_ENTRY(start);
2518#endif
2519 MAKE_QUEUE_ENTRY(first_recno);
2520 MAKE_QUEUE_ENTRY(cur_recno);
2521 break;
2522
2523 default:
2524 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2525 Py_DECREF(d);
2526 d = NULL;
2527 }
2528
2529#undef MAKE_HASH_ENTRY
2530#undef MAKE_BT_ENTRY
2531#undef MAKE_QUEUE_ENTRY
2532
2533 free(sp);
2534 return d;
2535}
2536
2537static PyObject*
2538DB_sync(DBObject* self, PyObject* args)
2539{
2540 int err;
2541 int flags = 0;
2542
2543 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2544 return NULL;
2545 CHECK_DB_NOT_CLOSED(self);
2546
2547 MYDB_BEGIN_ALLOW_THREADS;
2548 err = self->db->sync(self->db, flags);
2549 MYDB_END_ALLOW_THREADS;
2550 RETURN_IF_ERR();
2551 RETURN_NONE();
2552}
2553
2554
2555#if (DBVER >= 33)
2556static PyObject*
2557DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2558{
2559 int err, flags=0;
2560 u_int32_t count=0;
2561 PyObject* txnobj = NULL;
2562 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002563 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002564
2565 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2566 &txnobj, &flags))
2567 return NULL;
2568 CHECK_DB_NOT_CLOSED(self);
2569 if (!checkTxnObj(txnobj, &txn))
2570 return NULL;
2571
2572 MYDB_BEGIN_ALLOW_THREADS;
2573 err = self->db->truncate(self->db, txn, &count, flags);
2574 MYDB_END_ALLOW_THREADS;
2575 RETURN_IF_ERR();
2576 return PyInt_FromLong(count);
2577}
2578#endif
2579
2580
2581static PyObject*
2582DB_upgrade(DBObject* self, PyObject* args)
2583{
2584 int err, flags=0;
2585 char *filename;
2586
2587 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2588 return NULL;
2589 CHECK_DB_NOT_CLOSED(self);
2590
2591 MYDB_BEGIN_ALLOW_THREADS;
2592 err = self->db->upgrade(self->db, filename, flags);
2593 MYDB_END_ALLOW_THREADS;
2594 RETURN_IF_ERR();
2595 RETURN_NONE();
2596}
2597
2598
2599static PyObject*
2600DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2601{
2602 int err, flags=0;
2603 char* fileName;
2604 char* dbName=NULL;
2605 char* outFileName=NULL;
2606 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002607 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002608 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002609
2610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2611 &fileName, &dbName, &outFileName, &flags))
2612 return NULL;
2613
2614 CHECK_DB_NOT_CLOSED(self);
2615 if (outFileName)
2616 outFile = fopen(outFileName, "w");
2617
2618 MYDB_BEGIN_ALLOW_THREADS;
2619 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2620 MYDB_END_ALLOW_THREADS;
2621 if (outFileName)
2622 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002623
2624 /* DB.verify acts as a DB handle destructor (like close); this was
2625 * documented in BerkeleyDB 4.2 but had the undocumented effect
2626 * of not being safe in prior versions while still requiring an explicit
2627 * DB.close call afterwards. Lets call close for the user to emulate
2628 * the safe 4.2 behaviour. */
2629#if (DBVER <= 41)
2630 self->db->close(self->db, 0);
2631#endif
2632 self->db = NULL;
2633
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002634 RETURN_IF_ERR();
2635 RETURN_NONE();
2636}
2637
2638
2639static PyObject*
2640DB_set_get_returns_none(DBObject* self, PyObject* args)
2641{
2642 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002643 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644
2645 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2646 return NULL;
2647 CHECK_DB_NOT_CLOSED(self);
2648
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002649 if (self->moduleFlags.getReturnsNone)
2650 ++oldValue;
2651 if (self->moduleFlags.cursorSetReturnsNone)
2652 ++oldValue;
2653 self->moduleFlags.getReturnsNone = (flags >= 1);
2654 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002655 return PyInt_FromLong(oldValue);
2656}
2657
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002658#if (DBVER >= 41)
2659static PyObject*
2660DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2661{
2662 int err;
2663 u_int32_t flags=0;
2664 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002665 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002666
2667 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2668 &passwd, &flags)) {
2669 return NULL;
2670 }
2671
2672 MYDB_BEGIN_ALLOW_THREADS;
2673 err = self->db->set_encrypt(self->db, passwd, flags);
2674 MYDB_END_ALLOW_THREADS;
2675
2676 RETURN_IF_ERR();
2677 RETURN_NONE();
2678}
2679#endif /* DBVER >= 41 */
2680
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002681
2682/*-------------------------------------------------------------- */
2683/* Mapping and Dictionary-like access routines */
2684
Martin v. Löwis18e16552006-02-15 17:27:45 +00002685Py_ssize_t DB_length(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686{
2687 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002688 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002689 int flags = 0;
2690 void* sp;
2691
2692 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002693 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2694 PyErr_SetObject(DBError, t);
2695 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 return -1;
2697 }
2698
2699 if (self->haveStat) { /* Has the stat function been called recently? If
2700 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002701 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002702 }
2703
2704 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002705redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002706#if (DBVER >= 43)
2707 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2708#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 err = self->db->stat(self->db, &sp, flags);
2710#else
2711 err = self->db->stat(self->db, &sp, NULL, flags);
2712#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002713
2714 /* All the stat structures have matching fields upto the ndata field,
2715 so we can use any of them for the type cast */
2716 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2717
2718 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2719 * redo a full stat to make sure.
2720 * Fixes SF python bug 1493322, pybsddb bug 1184012
2721 */
2722 if (size == 0 && (flags & DB_FAST_STAT)) {
2723 flags = 0;
2724 goto redo_stat_for_length;
2725 }
2726
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002727 MYDB_END_ALLOW_THREADS;
2728
2729 if (err)
2730 return -1;
2731
2732 self->haveStat = 1;
2733
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 free(sp);
2735 return size;
2736}
2737
2738
2739PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2740{
2741 int err;
2742 PyObject* retval;
2743 DBT key;
2744 DBT data;
2745
2746 CHECK_DB_NOT_CLOSED(self);
2747 if (!make_key_dbt(self, keyobj, &key, NULL))
2748 return NULL;
2749
2750 CLEAR_DBT(data);
2751 if (CHECK_DBFLAG(self, DB_THREAD)) {
2752 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2753 data.flags = DB_DBT_MALLOC;
2754 }
2755 MYDB_BEGIN_ALLOW_THREADS;
2756 err = self->db->get(self->db, NULL, &key, &data, 0);
2757 MYDB_END_ALLOW_THREADS;
2758 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2759 PyErr_SetObject(PyExc_KeyError, keyobj);
2760 retval = NULL;
2761 }
2762 else if (makeDBError(err)) {
2763 retval = NULL;
2764 }
2765 else {
2766 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2767 FREE_DBT(data);
2768 }
2769
2770 FREE_DBT(key);
2771 return retval;
2772}
2773
2774
2775static int
2776DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2777{
2778 DBT key, data;
2779 int retval;
2780 int flags = 0;
2781
2782 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002783 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2784 PyErr_SetObject(DBError, t);
2785 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786 return -1;
2787 }
2788
2789 if (!make_key_dbt(self, keyobj, &key, NULL))
2790 return -1;
2791
2792 if (dataobj != NULL) {
2793 if (!make_dbt(dataobj, &data))
2794 retval = -1;
2795 else {
2796 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002797 /* dictionaries shouldn't have duplicate keys */
2798 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002799 retval = _DB_put(self, NULL, &key, &data, flags);
2800
2801 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002802 /* try deleting any old record that matches and then PUT it
2803 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002804 _DB_delete(self, NULL, &key, 0);
2805 PyErr_Clear();
2806 retval = _DB_put(self, NULL, &key, &data, flags);
2807 }
2808 }
2809 }
2810 else {
2811 /* dataobj == NULL, so delete the key */
2812 retval = _DB_delete(self, NULL, &key, 0);
2813 }
2814 FREE_DBT(key);
2815 return retval;
2816}
2817
2818
2819static PyObject*
2820DB_has_key(DBObject* self, PyObject* args)
2821{
2822 int err;
2823 PyObject* keyobj;
2824 DBT key, data;
2825 PyObject* txnobj = NULL;
2826 DB_TXN *txn = NULL;
2827
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002828 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002829 return NULL;
2830 CHECK_DB_NOT_CLOSED(self);
2831 if (!make_key_dbt(self, keyobj, &key, NULL))
2832 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002833 if (!checkTxnObj(txnobj, &txn)) {
2834 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002835 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002836 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002837
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002838 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839 it has a record but can't allocate a buffer for the data. This saves
2840 having to deal with data we won't be using.
2841 */
2842 CLEAR_DBT(data);
2843 data.flags = DB_DBT_USERMEM;
2844
2845 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00002846 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 MYDB_END_ALLOW_THREADS;
2848 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00002849
2850 if (err == DB_BUFFER_SMALL || err == 0) {
2851 return PyInt_FromLong(1);
2852 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2853 return PyInt_FromLong(0);
2854 }
2855
2856 makeDBError(err);
2857 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858}
2859
2860
2861#define _KEYS_LIST 1
2862#define _VALUES_LIST 2
2863#define _ITEMS_LIST 3
2864
2865static PyObject*
2866_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2867{
2868 int err, dbtype;
2869 DBT key;
2870 DBT data;
2871 DBC *cursor;
2872 PyObject* list;
2873 PyObject* item = NULL;
2874
2875 CHECK_DB_NOT_CLOSED(self);
2876 CLEAR_DBT(key);
2877 CLEAR_DBT(data);
2878
2879 dbtype = _DB_get_type(self);
2880 if (dbtype == -1)
2881 return NULL;
2882
2883 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00002884 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002885 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002886
2887 /* get a cursor */
2888 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00002889 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002890 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00002891 if (makeDBError(err)) {
2892 Py_DECREF(list);
2893 return NULL;
2894 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002895
2896 if (CHECK_DBFLAG(self, DB_THREAD)) {
2897 key.flags = DB_DBT_REALLOC;
2898 data.flags = DB_DBT_REALLOC;
2899 }
2900
2901 while (1) { /* use the cursor to traverse the DB, collecting items */
2902 MYDB_BEGIN_ALLOW_THREADS;
2903 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2904 MYDB_END_ALLOW_THREADS;
2905
2906 if (err) {
2907 /* for any error, break out of the loop */
2908 break;
2909 }
2910
2911 switch (type) {
2912 case _KEYS_LIST:
2913 switch(dbtype) {
2914 case DB_BTREE:
2915 case DB_HASH:
2916 default:
2917 item = PyString_FromStringAndSize((char*)key.data, key.size);
2918 break;
2919 case DB_RECNO:
2920 case DB_QUEUE:
2921 item = PyInt_FromLong(*((db_recno_t*)key.data));
2922 break;
2923 }
2924 break;
2925
2926 case _VALUES_LIST:
2927 item = PyString_FromStringAndSize((char*)data.data, data.size);
2928 break;
2929
2930 case _ITEMS_LIST:
2931 switch(dbtype) {
2932 case DB_BTREE:
2933 case DB_HASH:
2934 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002935 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2936 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937 break;
2938 case DB_RECNO:
2939 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002940 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2941 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002942 break;
2943 }
2944 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00002945 default:
2946 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2947 item = NULL;
2948 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002949 }
2950 if (item == NULL) {
2951 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002952 list = NULL;
2953 goto done;
2954 }
2955 PyList_Append(list, item);
2956 Py_DECREF(item);
2957 }
2958
Gregory P. Smithe9477062005-06-04 06:46:59 +00002959 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2960 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 Py_DECREF(list);
2962 list = NULL;
2963 }
2964
2965 done:
2966 FREE_DBT(key);
2967 FREE_DBT(data);
2968 MYDB_BEGIN_ALLOW_THREADS;
2969 cursor->c_close(cursor);
2970 MYDB_END_ALLOW_THREADS;
2971 return list;
2972}
2973
2974
2975static PyObject*
2976DB_keys(DBObject* self, PyObject* args)
2977{
2978 PyObject* txnobj = NULL;
2979 DB_TXN *txn = NULL;
2980
Georg Brandl96a8c392006-05-29 21:04:52 +00002981 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982 return NULL;
2983 if (!checkTxnObj(txnobj, &txn))
2984 return NULL;
2985 return _DB_make_list(self, txn, _KEYS_LIST);
2986}
2987
2988
2989static PyObject*
2990DB_items(DBObject* self, PyObject* args)
2991{
2992 PyObject* txnobj = NULL;
2993 DB_TXN *txn = NULL;
2994
Georg Brandl96a8c392006-05-29 21:04:52 +00002995 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 return NULL;
2997 if (!checkTxnObj(txnobj, &txn))
2998 return NULL;
2999 return _DB_make_list(self, txn, _ITEMS_LIST);
3000}
3001
3002
3003static PyObject*
3004DB_values(DBObject* self, PyObject* args)
3005{
3006 PyObject* txnobj = NULL;
3007 DB_TXN *txn = NULL;
3008
Georg Brandl96a8c392006-05-29 21:04:52 +00003009 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003010 return NULL;
3011 if (!checkTxnObj(txnobj, &txn))
3012 return NULL;
3013 return _DB_make_list(self, txn, _VALUES_LIST);
3014}
3015
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016/* --------------------------------------------------------------------- */
3017/* DBCursor methods */
3018
3019
3020static PyObject*
3021DBC_close(DBCursorObject* self, PyObject* args)
3022{
3023 int err = 0;
3024
3025 if (!PyArg_ParseTuple(args, ":close"))
3026 return NULL;
3027
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 if (self->dbc != NULL) {
3029 MYDB_BEGIN_ALLOW_THREADS;
3030 err = self->dbc->c_close(self->dbc);
3031 self->dbc = NULL;
3032 MYDB_END_ALLOW_THREADS;
3033 }
3034 RETURN_IF_ERR();
3035 RETURN_NONE();
3036}
3037
3038
3039static PyObject*
3040DBC_count(DBCursorObject* self, PyObject* args)
3041{
3042 int err = 0;
3043 db_recno_t count;
3044 int flags = 0;
3045
3046 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3047 return NULL;
3048
3049 CHECK_CURSOR_NOT_CLOSED(self);
3050
3051 MYDB_BEGIN_ALLOW_THREADS;
3052 err = self->dbc->c_count(self->dbc, &count, flags);
3053 MYDB_END_ALLOW_THREADS;
3054 RETURN_IF_ERR();
3055
3056 return PyInt_FromLong(count);
3057}
3058
3059
3060static PyObject*
3061DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3062{
3063 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3064}
3065
3066
3067static PyObject*
3068DBC_delete(DBCursorObject* self, PyObject* args)
3069{
3070 int err, flags=0;
3071
3072 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3073 return NULL;
3074
3075 CHECK_CURSOR_NOT_CLOSED(self);
3076
3077 MYDB_BEGIN_ALLOW_THREADS;
3078 err = self->dbc->c_del(self->dbc, flags);
3079 MYDB_END_ALLOW_THREADS;
3080 RETURN_IF_ERR();
3081
3082 self->mydb->haveStat = 0;
3083 RETURN_NONE();
3084}
3085
3086
3087static PyObject*
3088DBC_dup(DBCursorObject* self, PyObject* args)
3089{
3090 int err, flags =0;
3091 DBC* dbc = NULL;
3092
3093 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3094 return NULL;
3095
3096 CHECK_CURSOR_NOT_CLOSED(self);
3097
3098 MYDB_BEGIN_ALLOW_THREADS;
3099 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3100 MYDB_END_ALLOW_THREADS;
3101 RETURN_IF_ERR();
3102
3103 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3104}
3105
3106static PyObject*
3107DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3108{
3109 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3110}
3111
3112
3113static PyObject*
3114DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3115{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003116 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 PyObject* keyobj = NULL;
3118 PyObject* dataobj = NULL;
3119 PyObject* retval = NULL;
3120 int dlen = -1;
3121 int doff = -1;
3122 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003123 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003124 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003125
3126 CLEAR_DBT(key);
3127 CLEAR_DBT(data);
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003129 &flags, &dlen, &doff))
3130 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3133 &kwnames[1],
3134 &keyobj, &flags, &dlen, &doff))
3135 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003136 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003137 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3138 kwnames, &keyobj, &dataobj,
3139 &flags, &dlen, &doff))
3140 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141 return NULL;
3142 }
3143 }
3144 }
3145
3146 CHECK_CURSOR_NOT_CLOSED(self);
3147
3148 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3149 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003150 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3151 (!add_partial_dbt(&data, dlen, doff)) )
3152 {
3153 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003154 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003155 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003156
3157 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3158 data.flags = DB_DBT_MALLOC;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003159 if (!(key.flags & DB_DBT_REALLOC)) {
3160 key.flags |= DB_DBT_MALLOC;
3161 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 }
3163
3164 MYDB_BEGIN_ALLOW_THREADS;
3165 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3166 MYDB_END_ALLOW_THREADS;
3167
Gregory P. Smithe9477062005-06-04 06:46:59 +00003168 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3169 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003170 Py_INCREF(Py_None);
3171 retval = Py_None;
3172 }
3173 else if (makeDBError(err)) {
3174 retval = NULL;
3175 }
3176 else {
3177 switch (_DB_get_type(self->mydb)) {
3178 case -1:
3179 retval = NULL;
3180 break;
3181 case DB_BTREE:
3182 case DB_HASH:
3183 default:
3184 retval = Py_BuildValue("s#s#", key.data, key.size,
3185 data.data, data.size);
3186 break;
3187 case DB_RECNO:
3188 case DB_QUEUE:
3189 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3190 data.data, data.size);
3191 break;
3192 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003193 FREE_DBT(data);
3194 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003195 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 return retval;
3197}
3198
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003199#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003200static PyObject*
3201DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3202{
3203 int err, flags=0;
3204 PyObject* keyobj = NULL;
3205 PyObject* dataobj = NULL;
3206 PyObject* retval = NULL;
3207 int dlen = -1;
3208 int doff = -1;
3209 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003210 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3211 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003212
3213 CLEAR_DBT(key);
3214 CLEAR_DBT(data);
3215 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3216 &flags, &dlen, &doff))
3217 {
3218 PyErr_Clear();
3219 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003220 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003221 &keyobj, &flags, &dlen, &doff))
3222 {
3223 PyErr_Clear();
3224 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3225 kwnames, &keyobj, &dataobj,
3226 &flags, &dlen, &doff))
3227 {
3228 return NULL;
3229 }
3230 }
3231 }
3232
3233 CHECK_CURSOR_NOT_CLOSED(self);
3234
3235 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3236 return NULL;
3237 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3238 (!add_partial_dbt(&data, dlen, doff)) ) {
3239 FREE_DBT(key);
3240 return NULL;
3241 }
3242
3243 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3244 data.flags = DB_DBT_MALLOC;
3245 if (!(key.flags & DB_DBT_REALLOC)) {
3246 key.flags |= DB_DBT_MALLOC;
3247 }
3248 }
3249
3250 CLEAR_DBT(pkey);
3251 pkey.flags = DB_DBT_MALLOC;
3252
3253 MYDB_BEGIN_ALLOW_THREADS;
3254 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3255 MYDB_END_ALLOW_THREADS;
3256
Gregory P. Smithe9477062005-06-04 06:46:59 +00003257 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3258 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003259 Py_INCREF(Py_None);
3260 retval = Py_None;
3261 }
3262 else if (makeDBError(err)) {
3263 retval = NULL;
3264 }
3265 else {
3266 PyObject *pkeyObj;
3267 PyObject *dataObj;
3268 dataObj = PyString_FromStringAndSize(data.data, data.size);
3269
3270 if (self->mydb->primaryDBType == DB_RECNO ||
3271 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003272 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003273 else
3274 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3275
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003276 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003277 {
3278 PyObject *keyObj;
3279 int type = _DB_get_type(self->mydb);
3280 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003281 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003282 else
3283 keyObj = PyString_FromStringAndSize(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003284#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003285 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003286#else
3287 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3288#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003289 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003290 FREE_DBT(key);
3291 }
3292 else /* return just the pkey and data */
3293 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003294#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003295 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003296#else
3297 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3298#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003299 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003300 Py_DECREF(dataObj);
3301 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003302 FREE_DBT(pkey);
3303 FREE_DBT(data);
3304 }
3305 /* the only time REALLOC should be set is if we used an integer
3306 * key that make_key_dbt malloc'd for us. always free these. */
3307 if (key.flags & DB_DBT_REALLOC) {
3308 FREE_DBT(key);
3309 }
3310 return retval;
3311}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003312#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003313
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003314
3315static PyObject*
3316DBC_get_recno(DBCursorObject* self, PyObject* args)
3317{
3318 int err;
3319 db_recno_t recno;
3320 DBT key;
3321 DBT data;
3322
3323 if (!PyArg_ParseTuple(args, ":get_recno"))
3324 return NULL;
3325
3326 CHECK_CURSOR_NOT_CLOSED(self);
3327
3328 CLEAR_DBT(key);
3329 CLEAR_DBT(data);
3330 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3331 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3332 data.flags = DB_DBT_MALLOC;
3333 key.flags = DB_DBT_MALLOC;
3334 }
3335
3336 MYDB_BEGIN_ALLOW_THREADS;
3337 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3338 MYDB_END_ALLOW_THREADS;
3339 RETURN_IF_ERR();
3340
3341 recno = *((db_recno_t*)data.data);
3342 FREE_DBT(key);
3343 FREE_DBT(data);
3344 return PyInt_FromLong(recno);
3345}
3346
3347
3348static PyObject*
3349DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3350{
3351 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3352}
3353
3354
3355static PyObject*
3356DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3357{
3358 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3359}
3360
3361
3362static PyObject*
3363DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3364{
3365 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3366}
3367
3368
3369static PyObject*
3370DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3371{
3372 int err, flags = 0;
3373 PyObject* keyobj, *dataobj;
3374 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003375 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003376 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003377 int dlen = -1;
3378 int doff = -1;
3379
3380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3381 &keyobj, &dataobj, &flags, &dlen, &doff))
3382 return NULL;
3383
3384 CHECK_CURSOR_NOT_CLOSED(self);
3385
3386 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3387 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003388 if (!make_dbt(dataobj, &data) ||
3389 !add_partial_dbt(&data, dlen, doff) )
3390 {
3391 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003392 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003393 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394
3395 MYDB_BEGIN_ALLOW_THREADS;
3396 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3397 MYDB_END_ALLOW_THREADS;
3398 FREE_DBT(key);
3399 RETURN_IF_ERR();
3400 self->mydb->haveStat = 0;
3401 RETURN_NONE();
3402}
3403
3404
3405static PyObject*
3406DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3407{
3408 int err, flags = 0;
3409 DBT key, data;
3410 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003411 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003412 int dlen = -1;
3413 int doff = -1;
3414
3415 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3416 &keyobj, &flags, &dlen, &doff))
3417 return NULL;
3418
3419 CHECK_CURSOR_NOT_CLOSED(self);
3420
3421 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3422 return NULL;
3423
3424 CLEAR_DBT(data);
3425 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3426 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3427 data.flags = DB_DBT_MALLOC;
3428 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003429 if (!add_partial_dbt(&data, dlen, doff)) {
3430 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003431 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003432 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433
3434 MYDB_BEGIN_ALLOW_THREADS;
3435 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3436 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003437 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3438 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003439 Py_INCREF(Py_None);
3440 retval = Py_None;
3441 }
3442 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003443 retval = NULL;
3444 }
3445 else {
3446 switch (_DB_get_type(self->mydb)) {
3447 case -1:
3448 retval = NULL;
3449 break;
3450 case DB_BTREE:
3451 case DB_HASH:
3452 default:
3453 retval = Py_BuildValue("s#s#", key.data, key.size,
3454 data.data, data.size);
3455 break;
3456 case DB_RECNO:
3457 case DB_QUEUE:
3458 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3459 data.data, data.size);
3460 break;
3461 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003462 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003463 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003464 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003465 /* the only time REALLOC should be set is if we used an integer
3466 * key that make_key_dbt malloc'd for us. always free these. */
3467 if (key.flags & DB_DBT_REALLOC) {
3468 FREE_DBT(key);
3469 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470
3471 return retval;
3472}
3473
3474
3475static PyObject*
3476DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3477{
3478 int err, flags = 0;
3479 DBT key, data;
3480 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003481 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 int dlen = -1;
3483 int doff = -1;
3484
3485 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3486 &keyobj, &flags, &dlen, &doff))
3487 return NULL;
3488
3489 CHECK_CURSOR_NOT_CLOSED(self);
3490
3491 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3492 return NULL;
3493
3494 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003495 if (!add_partial_dbt(&data, dlen, doff)) {
3496 FREE_DBT(key);
3497 return NULL;
3498 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003499 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3500 /* Tell BerkeleyDB to malloc the return value (thread safe) */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003501 data.flags |= DB_DBT_MALLOC;
3502 /* only BTREE databases will return anything in the key */
3503 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3504 key.flags |= DB_DBT_MALLOC;
3505 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003506 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003507 MYDB_BEGIN_ALLOW_THREADS;
3508 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3509 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003510 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3511 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003512 Py_INCREF(Py_None);
3513 retval = Py_None;
3514 }
3515 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 retval = NULL;
3517 }
3518 else {
3519 switch (_DB_get_type(self->mydb)) {
3520 case -1:
3521 retval = NULL;
3522 break;
3523 case DB_BTREE:
3524 case DB_HASH:
3525 default:
3526 retval = Py_BuildValue("s#s#", key.data, key.size,
3527 data.data, data.size);
3528 break;
3529 case DB_RECNO:
3530 case DB_QUEUE:
3531 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3532 data.data, data.size);
3533 break;
3534 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003535 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 FREE_DBT(data);
3537 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003538 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003539 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003540 if (key.flags & DB_DBT_REALLOC) {
3541 FREE_DBT(key);
3542 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003543
3544 return retval;
3545}
3546
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003548_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3549 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003551 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003553 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003554
Gregory P. Smith7441e652003-11-03 21:35:31 +00003555 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003556 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3557 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003558 if (!make_dbt(dataobj, &data)) {
3559 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003560 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003561 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562
3563 MYDB_BEGIN_ALLOW_THREADS;
3564 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3565 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003566 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003567 Py_INCREF(Py_None);
3568 retval = Py_None;
3569 }
3570 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 retval = NULL;
3572 }
3573 else {
3574 switch (_DB_get_type(self->mydb)) {
3575 case -1:
3576 retval = NULL;
3577 break;
3578 case DB_BTREE:
3579 case DB_HASH:
3580 default:
3581 retval = Py_BuildValue("s#s#", key.data, key.size,
3582 data.data, data.size);
3583 break;
3584 case DB_RECNO:
3585 case DB_QUEUE:
3586 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3587 data.data, data.size);
3588 break;
3589 }
3590 }
3591
3592 FREE_DBT(key);
3593 return retval;
3594}
3595
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003596static PyObject*
3597DBC_get_both(DBCursorObject* self, PyObject* args)
3598{
3599 int flags=0;
3600 PyObject *keyobj, *dataobj;
3601
3602 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3603 return NULL;
3604
Gregory P. Smith7441e652003-11-03 21:35:31 +00003605 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003606 CHECK_CURSOR_NOT_CLOSED(self);
3607
3608 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3609 self->mydb->moduleFlags.getReturnsNone);
3610}
3611
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003612/* Return size of entry */
3613static PyObject*
3614DBC_get_current_size(DBCursorObject* self, PyObject* args)
3615{
3616 int err, flags=DB_CURRENT;
3617 PyObject* retval = NULL;
3618 DBT key, data;
3619
3620 if (!PyArg_ParseTuple(args, ":get_current_size"))
3621 return NULL;
3622 CHECK_CURSOR_NOT_CLOSED(self);
3623 CLEAR_DBT(key);
3624 CLEAR_DBT(data);
3625
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003626 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003627 getting the record size. */
3628 data.flags = DB_DBT_USERMEM;
3629 data.ulen = 0;
3630 MYDB_BEGIN_ALLOW_THREADS;
3631 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3632 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003633 if (err == DB_BUFFER_SMALL || !err) {
3634 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003635 retval = PyInt_FromLong((long)data.size);
3636 err = 0;
3637 }
3638
3639 FREE_DBT(key);
3640 FREE_DBT(data);
3641 RETURN_IF_ERR();
3642 return retval;
3643}
3644
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003645static PyObject*
3646DBC_set_both(DBCursorObject* self, PyObject* args)
3647{
3648 int flags=0;
3649 PyObject *keyobj, *dataobj;
3650
3651 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3652 return NULL;
3653
Gregory P. Smith7441e652003-11-03 21:35:31 +00003654 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003655 CHECK_CURSOR_NOT_CLOSED(self);
3656
3657 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3658 self->mydb->moduleFlags.cursorSetReturnsNone);
3659}
3660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661
3662static PyObject*
3663DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3664{
3665 int err, irecno, flags=0;
3666 db_recno_t recno;
3667 DBT key, data;
3668 PyObject* retval;
3669 int dlen = -1;
3670 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003671 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3674 &irecno, &flags, &dlen, &doff))
3675 return NULL;
3676
3677 CHECK_CURSOR_NOT_CLOSED(self);
3678
3679 CLEAR_DBT(key);
3680 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003681 /* use allocated space so DB will be able to realloc room for the real
3682 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683 key.data = malloc(sizeof(db_recno_t));
3684 if (key.data == NULL) {
3685 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3686 return NULL;
3687 }
3688 key.size = sizeof(db_recno_t);
3689 key.ulen = key.size;
3690 memcpy(key.data, &recno, sizeof(db_recno_t));
3691 key.flags = DB_DBT_REALLOC;
3692
3693 CLEAR_DBT(data);
3694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3696 data.flags = DB_DBT_MALLOC;
3697 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003698 if (!add_partial_dbt(&data, dlen, doff)) {
3699 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003700 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003701 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702
3703 MYDB_BEGIN_ALLOW_THREADS;
3704 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3705 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3707 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003708 Py_INCREF(Py_None);
3709 retval = Py_None;
3710 }
3711 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 retval = NULL;
3713 }
3714 else { /* Can only be used for BTrees, so no need to return int key */
3715 retval = Py_BuildValue("s#s#", key.data, key.size,
3716 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717 FREE_DBT(data);
3718 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003719 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003720
3721 return retval;
3722}
3723
3724
3725static PyObject*
3726DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3727{
3728 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3729}
3730
3731
3732static PyObject*
3733DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3734{
3735 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3736}
3737
3738
3739static PyObject*
3740DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3741{
3742 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3743}
3744
3745
3746static PyObject*
3747DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3748{
3749 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3750}
3751
3752
3753static PyObject*
3754DBC_join_item(DBCursorObject* self, PyObject* args)
3755{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003756 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757 DBT key, data;
3758 PyObject* retval;
3759
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003760 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003761 return NULL;
3762
3763 CHECK_CURSOR_NOT_CLOSED(self);
3764
3765 CLEAR_DBT(key);
3766 CLEAR_DBT(data);
3767 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3768 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3769 key.flags = DB_DBT_MALLOC;
3770 }
3771
3772 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003773 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003774 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003775 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3776 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003777 Py_INCREF(Py_None);
3778 retval = Py_None;
3779 }
3780 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003781 retval = NULL;
3782 }
3783 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003784 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003785 FREE_DBT(key);
3786 }
3787
3788 return retval;
3789}
3790
3791
3792
3793/* --------------------------------------------------------------------- */
3794/* DBEnv methods */
3795
3796
3797static PyObject*
3798DBEnv_close(DBEnvObject* self, PyObject* args)
3799{
3800 int err, flags = 0;
3801
3802 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3803 return NULL;
3804 if (!self->closed) { /* Don't close more than once */
3805 MYDB_BEGIN_ALLOW_THREADS;
3806 err = self->db_env->close(self->db_env, flags);
3807 MYDB_END_ALLOW_THREADS;
3808 /* after calling DBEnv->close, regardless of error, this DBEnv
3809 * may not be accessed again (BerkeleyDB docs). */
3810 self->closed = 1;
3811 self->db_env = NULL;
3812 RETURN_IF_ERR();
3813 }
3814 RETURN_NONE();
3815}
3816
3817
3818static PyObject*
3819DBEnv_open(DBEnvObject* self, PyObject* args)
3820{
3821 int err, flags=0, mode=0660;
3822 char *db_home;
3823
3824 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3825 return NULL;
3826
3827 CHECK_ENV_NOT_CLOSED(self);
3828
3829 MYDB_BEGIN_ALLOW_THREADS;
3830 err = self->db_env->open(self->db_env, db_home, flags, mode);
3831 MYDB_END_ALLOW_THREADS;
3832 RETURN_IF_ERR();
3833 self->closed = 0;
3834 self->flags = flags;
3835 RETURN_NONE();
3836}
3837
3838
3839static PyObject*
3840DBEnv_remove(DBEnvObject* self, PyObject* args)
3841{
3842 int err, flags=0;
3843 char *db_home;
3844
3845 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3846 return NULL;
3847 CHECK_ENV_NOT_CLOSED(self);
3848 MYDB_BEGIN_ALLOW_THREADS;
3849 err = self->db_env->remove(self->db_env, db_home, flags);
3850 MYDB_END_ALLOW_THREADS;
3851 RETURN_IF_ERR();
3852 RETURN_NONE();
3853}
3854
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003855#if (DBVER >= 41)
3856static PyObject*
3857DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3858{
3859 int err;
3860 u_int32_t flags=0;
3861 char *file = NULL;
3862 char *database = NULL;
3863 PyObject *txnobj = NULL;
3864 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003865 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003866 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003867
3868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3869 &file, &database, &txnobj, &flags)) {
3870 return NULL;
3871 }
3872 if (!checkTxnObj(txnobj, &txn)) {
3873 return NULL;
3874 }
3875 CHECK_ENV_NOT_CLOSED(self);
3876 MYDB_BEGIN_ALLOW_THREADS;
3877 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3878 MYDB_END_ALLOW_THREADS;
3879 RETURN_IF_ERR();
3880 RETURN_NONE();
3881}
3882
3883static PyObject*
3884DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3885{
3886 int err;
3887 u_int32_t flags=0;
3888 char *file = NULL;
3889 char *database = NULL;
3890 char *newname = NULL;
3891 PyObject *txnobj = NULL;
3892 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003893 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003894 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003895
3896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3897 &file, &database, &newname, &txnobj, &flags)) {
3898 return NULL;
3899 }
3900 if (!checkTxnObj(txnobj, &txn)) {
3901 return NULL;
3902 }
3903 CHECK_ENV_NOT_CLOSED(self);
3904 MYDB_BEGIN_ALLOW_THREADS;
3905 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3906 flags);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3910}
3911
3912static PyObject*
3913DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3914{
3915 int err;
3916 u_int32_t flags=0;
3917 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003918 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003919
3920 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3921 &passwd, &flags)) {
3922 return NULL;
3923 }
3924
3925 MYDB_BEGIN_ALLOW_THREADS;
3926 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3927 MYDB_END_ALLOW_THREADS;
3928
3929 RETURN_IF_ERR();
3930 RETURN_NONE();
3931}
3932#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003933
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003934#if (DBVER >= 40)
3935static PyObject*
3936DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3937{
3938 int err;
3939 u_int32_t flags=0;
3940 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003941 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003942
3943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3944 &timeout, &flags)) {
3945 return NULL;
3946 }
3947
3948 MYDB_BEGIN_ALLOW_THREADS;
3949 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3950 MYDB_END_ALLOW_THREADS;
3951
3952 RETURN_IF_ERR();
3953 RETURN_NONE();
3954}
3955#endif /* DBVER >= 40 */
3956
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003957static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003958DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3959{
3960 int err;
3961 long shm_key = 0;
3962
3963 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3964 return NULL;
3965 CHECK_ENV_NOT_CLOSED(self);
3966
3967 err = self->db_env->set_shm_key(self->db_env, shm_key);
3968 RETURN_IF_ERR();
3969 RETURN_NONE();
3970}
3971
3972static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003973DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3974{
3975 int err, gbytes=0, bytes=0, ncache=0;
3976
3977 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3978 &gbytes, &bytes, &ncache))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3981
3982 MYDB_BEGIN_ALLOW_THREADS;
3983 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3984 MYDB_END_ALLOW_THREADS;
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988
3989
3990#if (DBVER >= 32)
3991static PyObject*
3992DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3993{
3994 int err, flags=0, onoff=0;
3995
3996 if (!PyArg_ParseTuple(args, "ii:set_flags",
3997 &flags, &onoff))
3998 return NULL;
3999 CHECK_ENV_NOT_CLOSED(self);
4000
4001 MYDB_BEGIN_ALLOW_THREADS;
4002 err = self->db_env->set_flags(self->db_env, flags, onoff);
4003 MYDB_END_ALLOW_THREADS;
4004 RETURN_IF_ERR();
4005 RETURN_NONE();
4006}
4007#endif
4008
4009
4010static PyObject*
4011DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4012{
4013 int err;
4014 char *dir;
4015
4016 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4017 return NULL;
4018 CHECK_ENV_NOT_CLOSED(self);
4019
4020 MYDB_BEGIN_ALLOW_THREADS;
4021 err = self->db_env->set_data_dir(self->db_env, dir);
4022 MYDB_END_ALLOW_THREADS;
4023 RETURN_IF_ERR();
4024 RETURN_NONE();
4025}
4026
4027
4028static PyObject*
4029DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4030{
4031 int err, lg_bsize;
4032
4033 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045static PyObject*
4046DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4047{
4048 int err;
4049 char *dir;
4050
4051 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4052 return NULL;
4053 CHECK_ENV_NOT_CLOSED(self);
4054
4055 MYDB_BEGIN_ALLOW_THREADS;
4056 err = self->db_env->set_lg_dir(self->db_env, dir);
4057 MYDB_END_ALLOW_THREADS;
4058 RETURN_IF_ERR();
4059 RETURN_NONE();
4060}
4061
4062static PyObject*
4063DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4064{
4065 int err, lg_max;
4066
4067 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4068 return NULL;
4069 CHECK_ENV_NOT_CLOSED(self);
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_lg_max(self->db_env, lg_max);
4073 MYDB_END_ALLOW_THREADS;
4074 RETURN_IF_ERR();
4075 RETURN_NONE();
4076}
4077
4078
Neal Norwitz84562352005-10-20 04:30:15 +00004079#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004080static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004081DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4082{
4083 int err, lg_max;
4084
4085 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4086 return NULL;
4087 CHECK_ENV_NOT_CLOSED(self);
4088
4089 MYDB_BEGIN_ALLOW_THREADS;
4090 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4091 MYDB_END_ALLOW_THREADS;
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
Neal Norwitz84562352005-10-20 04:30:15 +00004095#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004096
4097
4098static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004099DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4100{
4101 int err, lk_detect;
4102
4103 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4104 return NULL;
4105 CHECK_ENV_NOT_CLOSED(self);
4106
4107 MYDB_BEGIN_ALLOW_THREADS;
4108 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4109 MYDB_END_ALLOW_THREADS;
4110 RETURN_IF_ERR();
4111 RETURN_NONE();
4112}
4113
4114
4115static PyObject*
4116DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4117{
4118 int err, max;
4119
4120 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_lk_max(self->db_env, max);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
4130
4131
4132#if (DBVER >= 32)
4133
4134static PyObject*
4135DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4136{
4137 int err, max;
4138
4139 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4142
4143 MYDB_BEGIN_ALLOW_THREADS;
4144 err = self->db_env->set_lk_max_locks(self->db_env, max);
4145 MYDB_END_ALLOW_THREADS;
4146 RETURN_IF_ERR();
4147 RETURN_NONE();
4148}
4149
4150
4151static PyObject*
4152DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4153{
4154 int err, max;
4155
4156 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4157 return NULL;
4158 CHECK_ENV_NOT_CLOSED(self);
4159
4160 MYDB_BEGIN_ALLOW_THREADS;
4161 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4162 MYDB_END_ALLOW_THREADS;
4163 RETURN_IF_ERR();
4164 RETURN_NONE();
4165}
4166
4167
4168static PyObject*
4169DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4170{
4171 int err, max;
4172
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_objects(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184#endif
4185
4186
4187static PyObject*
4188DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4189{
4190 int err, mp_mmapsize;
4191
4192 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4193 return NULL;
4194 CHECK_ENV_NOT_CLOSED(self);
4195
4196 MYDB_BEGIN_ALLOW_THREADS;
4197 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4198 MYDB_END_ALLOW_THREADS;
4199 RETURN_IF_ERR();
4200 RETURN_NONE();
4201}
4202
4203
4204static PyObject*
4205DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4206{
4207 int err;
4208 char *dir;
4209
4210 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4211 return NULL;
4212 CHECK_ENV_NOT_CLOSED(self);
4213
4214 MYDB_BEGIN_ALLOW_THREADS;
4215 err = self->db_env->set_tmp_dir(self->db_env, dir);
4216 MYDB_END_ALLOW_THREADS;
4217 RETURN_IF_ERR();
4218 RETURN_NONE();
4219}
4220
4221
4222static PyObject*
4223DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4224{
4225 int flags = 0;
4226 PyObject* txnobj = NULL;
4227 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004228 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004229
4230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4231 &txnobj, &flags))
4232 return NULL;
4233
4234 if (!checkTxnObj(txnobj, &txn))
4235 return NULL;
4236 CHECK_ENV_NOT_CLOSED(self);
4237
4238 return (PyObject*)newDBTxnObject(self, txn, flags);
4239}
4240
4241
4242static PyObject*
4243DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4244{
4245 int err, kbyte=0, min=0, flags=0;
4246
4247 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4248 return NULL;
4249 CHECK_ENV_NOT_CLOSED(self);
4250
4251 MYDB_BEGIN_ALLOW_THREADS;
4252#if (DBVER >= 40)
4253 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4254#else
4255 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4256#endif
4257 MYDB_END_ALLOW_THREADS;
4258 RETURN_IF_ERR();
4259 RETURN_NONE();
4260}
4261
4262
4263static PyObject*
4264DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4265{
4266 int err, max;
4267
4268 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4269 return NULL;
4270 CHECK_ENV_NOT_CLOSED(self);
4271
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004272 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004273 RETURN_IF_ERR();
4274 RETURN_NONE();
4275}
4276
4277
4278static PyObject*
4279DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4280{
4281 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004282 long stamp;
4283 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004284
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004285 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004288 timestamp = (time_t)stamp;
4289 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004290 RETURN_IF_ERR();
4291 RETURN_NONE();
4292}
4293
4294
4295static PyObject*
4296DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4297{
4298 int err, atype, flags=0;
4299 int aborted = 0;
4300
4301 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4302 return NULL;
4303 CHECK_ENV_NOT_CLOSED(self);
4304
4305 MYDB_BEGIN_ALLOW_THREADS;
4306#if (DBVER >= 40)
4307 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4308#else
4309 err = lock_detect(self->db_env, flags, atype, &aborted);
4310#endif
4311 MYDB_END_ALLOW_THREADS;
4312 RETURN_IF_ERR();
4313 return PyInt_FromLong(aborted);
4314}
4315
4316
4317static PyObject*
4318DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4319{
4320 int flags=0;
4321 int locker, lock_mode;
4322 DBT obj;
4323 PyObject* objobj;
4324
4325 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4326 return NULL;
4327
4328
4329 if (!make_dbt(objobj, &obj))
4330 return NULL;
4331
4332 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4333}
4334
4335
4336static PyObject*
4337DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4338{
4339 int err;
4340 u_int32_t theID;
4341
4342 if (!PyArg_ParseTuple(args, ":lock_id"))
4343 return NULL;
4344
4345 CHECK_ENV_NOT_CLOSED(self);
4346 MYDB_BEGIN_ALLOW_THREADS;
4347#if (DBVER >= 40)
4348 err = self->db_env->lock_id(self->db_env, &theID);
4349#else
4350 err = lock_id(self->db_env, &theID);
4351#endif
4352 MYDB_END_ALLOW_THREADS;
4353 RETURN_IF_ERR();
4354
4355 return PyInt_FromLong((long)theID);
4356}
4357
4358
4359static PyObject*
4360DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4361{
4362 int err;
4363 DBLockObject* dblockobj;
4364
4365 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4366 return NULL;
4367
4368 CHECK_ENV_NOT_CLOSED(self);
4369 MYDB_BEGIN_ALLOW_THREADS;
4370#if (DBVER >= 40)
4371 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4372#else
4373 err = lock_put(self->db_env, &dblockobj->lock);
4374#endif
4375 MYDB_END_ALLOW_THREADS;
4376 RETURN_IF_ERR();
4377 RETURN_NONE();
4378}
4379
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004380#if (DBVER >= 44)
4381static PyObject*
4382DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4383{
4384 int err;
4385 char *file;
4386 u_int32_t flags = 0;
4387 static char* kwnames[] = { "file", "flags", NULL};
4388
4389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4390 &file, &flags))
4391 return NULL;
4392 CHECK_ENV_NOT_CLOSED(self);
4393
4394 MYDB_BEGIN_ALLOW_THREADS;
4395 err = self->db_env->lsn_reset(self->db_env, file, flags);
4396 MYDB_END_ALLOW_THREADS;
4397 RETURN_IF_ERR();
4398 RETURN_NONE();
4399}
4400#endif /* DBVER >= 4.4 */
4401
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004402#if (DBVER >= 40)
4403static PyObject*
4404DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4405{
4406 int err;
4407 DB_LOG_STAT* statp = NULL;
4408 PyObject* d = NULL;
4409 u_int32_t flags = 0;
4410
4411 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4412 return NULL;
4413 CHECK_ENV_NOT_CLOSED(self);
4414
4415 MYDB_BEGIN_ALLOW_THREADS;
4416 err = self->db_env->log_stat(self->db_env, &statp, flags);
4417 MYDB_END_ALLOW_THREADS;
4418 RETURN_IF_ERR();
4419
4420 /* Turn the stat structure into a dictionary */
4421 d = PyDict_New();
4422 if (d == NULL) {
4423 if (statp)
4424 free(statp);
4425 return NULL;
4426 }
4427
4428#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4429
4430 MAKE_ENTRY(magic);
4431 MAKE_ENTRY(version);
4432 MAKE_ENTRY(mode);
4433 MAKE_ENTRY(lg_bsize);
4434#if (DBVER >= 44)
4435 MAKE_ENTRY(lg_size);
4436 MAKE_ENTRY(record);
4437#endif
4438#if (DBVER <= 40)
4439 MAKE_ENTRY(lg_max);
4440#endif
4441 MAKE_ENTRY(w_mbytes);
4442 MAKE_ENTRY(w_bytes);
4443 MAKE_ENTRY(wc_mbytes);
4444 MAKE_ENTRY(wc_bytes);
4445 MAKE_ENTRY(wcount);
4446 MAKE_ENTRY(wcount_fill);
4447#if (DBVER >= 44)
4448 MAKE_ENTRY(rcount);
4449#endif
4450 MAKE_ENTRY(scount);
4451 MAKE_ENTRY(cur_file);
4452 MAKE_ENTRY(cur_offset);
4453 MAKE_ENTRY(disk_file);
4454 MAKE_ENTRY(disk_offset);
4455 MAKE_ENTRY(maxcommitperflush);
4456 MAKE_ENTRY(mincommitperflush);
4457 MAKE_ENTRY(regsize);
4458 MAKE_ENTRY(region_wait);
4459 MAKE_ENTRY(region_nowait);
4460
4461#undef MAKE_ENTRY
4462 free(statp);
4463 return d;
4464} /* DBEnv_log_stat */
4465#endif /* DBVER >= 4.0 for log_stat method */
4466
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004467
4468static PyObject*
4469DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4470{
4471 int err;
4472 DB_LOCK_STAT* sp;
4473 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004474 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004475
4476 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4477 return NULL;
4478 CHECK_ENV_NOT_CLOSED(self);
4479
4480 MYDB_BEGIN_ALLOW_THREADS;
4481#if (DBVER >= 40)
4482 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4483#else
4484#if (DBVER >= 33)
4485 err = lock_stat(self->db_env, &sp);
4486#else
4487 err = lock_stat(self->db_env, &sp, NULL);
4488#endif
4489#endif
4490 MYDB_END_ALLOW_THREADS;
4491 RETURN_IF_ERR();
4492
4493 /* Turn the stat structure into a dictionary */
4494 d = PyDict_New();
4495 if (d == NULL) {
4496 free(sp);
4497 return NULL;
4498 }
4499
4500#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4501
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004502#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004503 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004504#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004505 MAKE_ENTRY(nmodes);
4506#if (DBVER >= 32)
4507 MAKE_ENTRY(maxlocks);
4508 MAKE_ENTRY(maxlockers);
4509 MAKE_ENTRY(maxobjects);
4510 MAKE_ENTRY(nlocks);
4511 MAKE_ENTRY(maxnlocks);
4512#endif
4513 MAKE_ENTRY(nlockers);
4514 MAKE_ENTRY(maxnlockers);
4515#if (DBVER >= 32)
4516 MAKE_ENTRY(nobjects);
4517 MAKE_ENTRY(maxnobjects);
4518#endif
4519 MAKE_ENTRY(nrequests);
4520 MAKE_ENTRY(nreleases);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004521#if (DBVER < 44)
4522 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004523 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004524#else
4525 MAKE_ENTRY(lock_nowait);
4526 MAKE_ENTRY(lock_wait);
4527#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004528 MAKE_ENTRY(ndeadlocks);
4529 MAKE_ENTRY(regsize);
4530 MAKE_ENTRY(region_wait);
4531 MAKE_ENTRY(region_nowait);
4532
4533#undef MAKE_ENTRY
4534 free(sp);
4535 return d;
4536}
4537
4538
4539static PyObject*
4540DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4541{
4542 int flags=0;
4543 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004544 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 PyObject* list;
4546 PyObject* item = NULL;
4547
4548 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4549 return NULL;
4550
4551 CHECK_ENV_NOT_CLOSED(self);
4552 MYDB_BEGIN_ALLOW_THREADS;
4553#if (DBVER >= 40)
4554 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4555#elif (DBVER == 33)
4556 err = log_archive(self->db_env, &log_list, flags);
4557#else
4558 err = log_archive(self->db_env, &log_list, flags, NULL);
4559#endif
4560 MYDB_END_ALLOW_THREADS;
4561 RETURN_IF_ERR();
4562
Gregory P. Smithbad47452006-06-05 00:33:35 +00004563 list = PyList_New(0);
4564 if (list == NULL) {
4565 if (log_list)
4566 free(log_list);
4567 return NULL;
4568 }
4569
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004570 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004571 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004572 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4573 item = PyString_FromString (*log_list);
4574 if (item == NULL) {
4575 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576 list = NULL;
4577 break;
4578 }
4579 PyList_Append(list, item);
4580 Py_DECREF(item);
4581 }
4582 free(log_list_start);
4583 }
4584 return list;
4585}
4586
4587
4588static PyObject*
4589DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4590{
4591 int err;
4592 DB_TXN_STAT* sp;
4593 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004594 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004595
4596 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4597 return NULL;
4598 CHECK_ENV_NOT_CLOSED(self);
4599
4600 MYDB_BEGIN_ALLOW_THREADS;
4601#if (DBVER >= 40)
4602 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4603#elif (DBVER == 33)
4604 err = txn_stat(self->db_env, &sp);
4605#else
4606 err = txn_stat(self->db_env, &sp, NULL);
4607#endif
4608 MYDB_END_ALLOW_THREADS;
4609 RETURN_IF_ERR();
4610
4611 /* Turn the stat structure into a dictionary */
4612 d = PyDict_New();
4613 if (d == NULL) {
4614 free(sp);
4615 return NULL;
4616 }
4617
4618#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4619
4620 MAKE_ENTRY(time_ckp);
4621 MAKE_ENTRY(last_txnid);
4622 MAKE_ENTRY(maxtxns);
4623 MAKE_ENTRY(nactive);
4624 MAKE_ENTRY(maxnactive);
4625 MAKE_ENTRY(nbegins);
4626 MAKE_ENTRY(naborts);
4627 MAKE_ENTRY(ncommits);
4628 MAKE_ENTRY(regsize);
4629 MAKE_ENTRY(region_wait);
4630 MAKE_ENTRY(region_nowait);
4631
4632#undef MAKE_ENTRY
4633 free(sp);
4634 return d;
4635}
4636
4637
4638static PyObject*
4639DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4640{
4641 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004642 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004643
4644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4645 return NULL;
4646 CHECK_ENV_NOT_CLOSED(self);
4647
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004648 if (self->moduleFlags.getReturnsNone)
4649 ++oldValue;
4650 if (self->moduleFlags.cursorSetReturnsNone)
4651 ++oldValue;
4652 self->moduleFlags.getReturnsNone = (flags >= 1);
4653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004654 return PyInt_FromLong(oldValue);
4655}
4656
4657
4658/* --------------------------------------------------------------------- */
4659/* DBTxn methods */
4660
4661
4662static PyObject*
4663DBTxn_commit(DBTxnObject* self, PyObject* args)
4664{
4665 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004666 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004667
4668 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4669 return NULL;
4670
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004671 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004672 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4673 "after txn_commit or txn_abort");
4674 PyErr_SetObject(DBError, t);
4675 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004676 return NULL;
4677 }
4678 txn = self->txn;
4679 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680 MYDB_BEGIN_ALLOW_THREADS;
4681#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004682 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004684 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004685#endif
4686 MYDB_END_ALLOW_THREADS;
4687 RETURN_IF_ERR();
4688 RETURN_NONE();
4689}
4690
4691static PyObject*
4692DBTxn_prepare(DBTxnObject* self, PyObject* args)
4693{
4694#if (DBVER >= 33)
4695 int err;
4696 char* gid=NULL;
4697 int gid_size=0;
4698
4699 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4700 return NULL;
4701
4702 if (gid_size != DB_XIDDATASIZE) {
4703 PyErr_SetString(PyExc_TypeError,
4704 "gid must be DB_XIDDATASIZE bytes long");
4705 return NULL;
4706 }
4707
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004708 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004709 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4710 "after txn_commit or txn_abort");
4711 PyErr_SetObject(DBError, t);
4712 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004713 return NULL;
4714 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004715 MYDB_BEGIN_ALLOW_THREADS;
4716#if (DBVER >= 40)
4717 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4718#else
4719 err = txn_prepare(self->txn, (u_int8_t*)gid);
4720#endif
4721 MYDB_END_ALLOW_THREADS;
4722 RETURN_IF_ERR();
4723 RETURN_NONE();
4724#else
4725 int err;
4726
4727 if (!PyArg_ParseTuple(args, ":prepare"))
4728 return NULL;
4729
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004730 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004731 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4732 "after txn_commit or txn_abort");
4733 PyErr_SetObject(DBError, t);
4734 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004735 return NULL;
4736 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004737 MYDB_BEGIN_ALLOW_THREADS;
4738 err = txn_prepare(self->txn);
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4742#endif
4743}
4744
4745
4746static PyObject*
4747DBTxn_abort(DBTxnObject* self, PyObject* args)
4748{
4749 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004750 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004751
4752 if (!PyArg_ParseTuple(args, ":abort"))
4753 return NULL;
4754
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004755 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004756 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4757 "after txn_commit or txn_abort");
4758 PyErr_SetObject(DBError, t);
4759 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004760 return NULL;
4761 }
4762 txn = self->txn;
4763 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004764 MYDB_BEGIN_ALLOW_THREADS;
4765#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004766 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004767#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004768 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769#endif
4770 MYDB_END_ALLOW_THREADS;
4771 RETURN_IF_ERR();
4772 RETURN_NONE();
4773}
4774
4775
4776static PyObject*
4777DBTxn_id(DBTxnObject* self, PyObject* args)
4778{
4779 int id;
4780
4781 if (!PyArg_ParseTuple(args, ":id"))
4782 return NULL;
4783
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004784 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00004785 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4786 "after txn_commit or txn_abort");
4787 PyErr_SetObject(DBError, t);
4788 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004789 return NULL;
4790 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791 MYDB_BEGIN_ALLOW_THREADS;
4792#if (DBVER >= 40)
4793 id = self->txn->id(self->txn);
4794#else
4795 id = txn_id(self->txn);
4796#endif
4797 MYDB_END_ALLOW_THREADS;
4798 return PyInt_FromLong(id);
4799}
4800
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004801#if (DBVER >= 43)
4802/* --------------------------------------------------------------------- */
4803/* DBSequence methods */
4804
4805
4806static PyObject*
4807DBSequence_close(DBSequenceObject* self, PyObject* args)
4808{
4809 int err, flags=0;
4810 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4811 return NULL;
4812 CHECK_SEQUENCE_NOT_CLOSED(self)
4813
4814 MYDB_BEGIN_ALLOW_THREADS
4815 err = self->sequence->close(self->sequence, flags);
4816 self->sequence = NULL;
4817 MYDB_END_ALLOW_THREADS
4818
4819 RETURN_IF_ERR();
4820
4821 RETURN_NONE();
4822}
4823
4824static PyObject*
4825DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4826{
4827 int err, flags = 0;
4828 int delta = 1;
4829 db_seq_t value;
4830 PyObject *txnobj = NULL;
4831 DB_TXN *txn = NULL;
4832 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4834 return NULL;
4835 CHECK_SEQUENCE_NOT_CLOSED(self)
4836
4837 if (!checkTxnObj(txnobj, &txn))
4838 return NULL;
4839
4840 MYDB_BEGIN_ALLOW_THREADS
4841 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4842 MYDB_END_ALLOW_THREADS
4843
4844 RETURN_IF_ERR();
4845 return PyLong_FromLongLong(value);
4846
4847}
4848
4849static PyObject*
4850DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4851{
4852 if (!PyArg_ParseTuple(args,":get_dbp"))
4853 return NULL;
4854 CHECK_SEQUENCE_NOT_CLOSED(self)
4855 Py_INCREF(self->mydb);
4856 return (PyObject* )self->mydb;
4857}
4858
4859static PyObject*
4860DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4861{
4862 int err;
4863 DBT key;
4864 CHECK_SEQUENCE_NOT_CLOSED(self)
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err = self->sequence->get_key(self->sequence, &key);
4867 MYDB_END_ALLOW_THREADS
4868
4869 RETURN_IF_ERR();
4870
4871 return PyString_FromStringAndSize(key.data, key.size);
4872}
4873
4874static PyObject*
4875DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4876{
4877 int err;
4878 db_seq_t value;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004879 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004880 return NULL;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882
4883 MYDB_BEGIN_ALLOW_THREADS
4884 err = self->sequence->initial_value(self->sequence, value);
4885 MYDB_END_ALLOW_THREADS
4886
4887 RETURN_IF_ERR();
4888
4889 RETURN_NONE();
4890}
4891
4892static PyObject*
4893DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4894{
4895 int err, flags = 0;
4896 PyObject* keyobj;
4897 PyObject *txnobj = NULL;
4898 DB_TXN *txn = NULL;
4899 DBT key;
4900
4901 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004903 return NULL;
4904
4905 if (!checkTxnObj(txnobj, &txn))
4906 return NULL;
4907
4908 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4909 return NULL;
4910
4911 MYDB_BEGIN_ALLOW_THREADS
4912 err = self->sequence->open(self->sequence, txn, &key, flags);
4913 MYDB_END_ALLOW_THREADS
4914
4915 CLEAR_DBT(key);
4916 RETURN_IF_ERR();
4917
4918 RETURN_NONE();
4919}
4920
4921static PyObject*
4922DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4923{
4924 int err, flags = 0;
4925 PyObject *txnobj = NULL;
4926 DB_TXN *txn = NULL;
4927
4928 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004930 return NULL;
4931
4932 if (!checkTxnObj(txnobj, &txn))
4933 return NULL;
4934
4935 CHECK_SEQUENCE_NOT_CLOSED(self)
4936
4937 MYDB_BEGIN_ALLOW_THREADS
4938 err = self->sequence->remove(self->sequence, txn, flags);
4939 MYDB_END_ALLOW_THREADS
4940
4941 RETURN_IF_ERR();
4942 RETURN_NONE();
4943}
4944
4945static PyObject*
4946DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4947{
4948 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004949 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004950 return NULL;
4951 CHECK_SEQUENCE_NOT_CLOSED(self)
4952
4953 MYDB_BEGIN_ALLOW_THREADS
4954 err = self->sequence->set_cachesize(self->sequence, size);
4955 MYDB_END_ALLOW_THREADS
4956
4957 RETURN_IF_ERR();
4958 RETURN_NONE();
4959}
4960
4961static PyObject*
4962DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4963{
4964 int err, size;
4965 if (!PyArg_ParseTuple(args,":get_cachesize"))
4966 return NULL;
4967 CHECK_SEQUENCE_NOT_CLOSED(self)
4968
4969 MYDB_BEGIN_ALLOW_THREADS
4970 err = self->sequence->get_cachesize(self->sequence, &size);
4971 MYDB_END_ALLOW_THREADS
4972
4973 RETURN_IF_ERR();
4974 return PyInt_FromLong(size);
4975}
4976
4977static PyObject*
4978DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4979{
4980 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004981 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00004982 return NULL;
4983 CHECK_SEQUENCE_NOT_CLOSED(self)
4984
4985 MYDB_BEGIN_ALLOW_THREADS
4986 err = self->sequence->set_flags(self->sequence, flags);
4987 MYDB_END_ALLOW_THREADS
4988
4989 RETURN_IF_ERR();
4990 RETURN_NONE();
4991
4992}
4993
4994static PyObject*
4995DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4996{
4997 unsigned int flags;
4998 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00004999 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005000 return NULL;
5001 CHECK_SEQUENCE_NOT_CLOSED(self)
5002
5003 MYDB_BEGIN_ALLOW_THREADS
5004 err = self->sequence->get_flags(self->sequence, &flags);
5005 MYDB_END_ALLOW_THREADS
5006
5007 RETURN_IF_ERR();
5008 return PyInt_FromLong((int)flags);
5009}
5010
5011static PyObject*
5012DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5013{
5014 int err;
5015 db_seq_t min, max;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005016 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5019
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->set_range(self->sequence, min, max);
5022 MYDB_END_ALLOW_THREADS
5023
5024 RETURN_IF_ERR();
5025 RETURN_NONE();
5026}
5027
5028static PyObject*
5029DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5030{
5031 int err;
5032 db_seq_t min, max;
5033 if (!PyArg_ParseTuple(args,":get_range"))
5034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5036
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->get_range(self->sequence, &min, &max);
5039 MYDB_END_ALLOW_THREADS
5040
5041 RETURN_IF_ERR();
5042 return Py_BuildValue("(LL)", min, max);
5043}
5044
5045static PyObject*
5046DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5047{
5048 int err, flags = 0;
5049 DB_SEQUENCE_STAT* sp = NULL;
5050 PyObject* dict_stat;
5051 static char* kwnames[] = {"flags", NULL };
5052 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5053 return NULL;
5054 CHECK_SEQUENCE_NOT_CLOSED(self);
5055
5056 MYDB_BEGIN_ALLOW_THREADS;
5057 err = self->sequence->stat(self->sequence, &sp, flags);
5058 MYDB_END_ALLOW_THREADS;
5059 RETURN_IF_ERR();
5060
5061 if ((dict_stat = PyDict_New()) == NULL) {
5062 free(sp);
5063 return NULL;
5064 }
5065
5066
5067#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5068#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5069
5070 MAKE_INT_ENTRY(wait);
5071 MAKE_INT_ENTRY(nowait);
5072 MAKE_LONG_LONG_ENTRY(current);
5073 MAKE_LONG_LONG_ENTRY(value);
5074 MAKE_LONG_LONG_ENTRY(last_value);
5075 MAKE_LONG_LONG_ENTRY(min);
5076 MAKE_LONG_LONG_ENTRY(max);
5077 MAKE_INT_ENTRY(cache_size);
5078 MAKE_INT_ENTRY(flags);
5079
5080#undef MAKE_INT_ENTRY
5081#undef MAKE_LONG_LONG_ENTRY
5082
5083 free(sp);
5084 return dict_stat;
5085}
5086#endif
5087
5088
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005089/* --------------------------------------------------------------------- */
5090/* Method definition tables and type objects */
5091
5092static PyMethodDef DB_methods[] = {
5093 {"append", (PyCFunction)DB_append, METH_VARARGS},
5094#if (DBVER >= 33)
5095 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5096#endif
5097 {"close", (PyCFunction)DB_close, METH_VARARGS},
5098#if (DBVER >= 32)
5099 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5100 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5101#endif
5102 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5103 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5104 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5105 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005106#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005107 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005108#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005109 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5110 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5111 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5112 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5113 {"join", (PyCFunction)DB_join, METH_VARARGS},
5114 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5115 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5116 {"items", (PyCFunction)DB_items, METH_VARARGS},
5117 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5118 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5119 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5120 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5121 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5122 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005123#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00005124 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005126 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005127#if (DBVER >= 41)
5128 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5129#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005130 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5131 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5132 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5133 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5134 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5135 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5136 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5137 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5138 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5139#if (DBVER >= 32)
5140 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5141#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005142 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005143 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5144#if (DBVER >= 33)
5145 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5146#endif
5147 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5148 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5149 {"values", (PyCFunction)DB_values, METH_VARARGS},
5150 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5151 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5152 {NULL, NULL} /* sentinel */
5153};
5154
5155
5156static PyMappingMethods DB_mapping = {
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005157 (inquiry)DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005158 (binaryfunc)DB_subscript, /*mp_subscript*/
5159 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5160};
5161
5162
5163static PyMethodDef DBCursor_methods[] = {
5164 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5165 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5166 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5167 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5168 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5169 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5170 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005171#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005172 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005173#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005174 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5175 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5176 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5177 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5178 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5179 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5180 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5181 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00005182 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005183 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005184 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5185 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5186 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5187 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5188 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5189 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5190 {NULL, NULL} /* sentinel */
5191};
5192
5193
5194static PyMethodDef DBEnv_methods[] = {
5195 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5196 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5197 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005198#if (DBVER >= 41)
5199 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5200 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5201 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5202#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00005203#if (DBVER >= 40)
5204 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5205#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00005206 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005207 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5208 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5209#if (DBVER >= 32)
5210 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5211#endif
5212 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5213 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5214 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005215#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00005216 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00005217#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005218 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5219 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5220#if (DBVER >= 32)
5221 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5222 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5223 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5224#endif
5225 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5226 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5227 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5228 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5229 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5230 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00005231 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005232 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5233 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5234 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5235 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5236 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5237 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00005238#if (DBVER >= 40)
5239 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5240#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00005241#if (DBVER >= 44)
5242 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5243#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005244 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5245 {NULL, NULL} /* sentinel */
5246};
5247
5248
5249static PyMethodDef DBTxn_methods[] = {
5250 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5251 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5252 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5253 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5254 {NULL, NULL} /* sentinel */
5255};
5256
5257
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005258#if (DBVER >= 43)
5259static PyMethodDef DBSequence_methods[] = {
5260 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5261 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5262 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5263 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005264 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5265 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5266 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5267 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5268 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5269 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5270 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5271 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5272 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5273 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5274 {NULL, NULL} /* sentinel */
5275};
5276#endif
5277
5278
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005279static PyObject*
5280DB_getattr(DBObject* self, char *name)
5281{
5282 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5283}
5284
5285
5286static PyObject*
5287DBEnv_getattr(DBEnvObject* self, char *name)
5288{
5289 if (!strcmp(name, "db_home")) {
5290 CHECK_ENV_NOT_CLOSED(self);
5291 if (self->db_env->db_home == NULL) {
5292 RETURN_NONE();
5293 }
5294 return PyString_FromString(self->db_env->db_home);
5295 }
5296
5297 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5298}
5299
5300
5301static PyObject*
5302DBCursor_getattr(DBCursorObject* self, char *name)
5303{
5304 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5305}
5306
5307static PyObject*
5308DBTxn_getattr(DBTxnObject* self, char *name)
5309{
5310 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5311}
5312
5313static PyObject*
5314DBLock_getattr(DBLockObject* self, char *name)
5315{
5316 return NULL;
5317}
5318
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005319#if (DBVER >= 43)
5320static PyObject*
5321DBSequence_getattr(DBSequenceObject* self, char *name)
5322{
5323 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5324}
5325#endif
5326
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005327statichere PyTypeObject DB_Type = {
5328 PyObject_HEAD_INIT(NULL)
5329 0, /*ob_size*/
5330 "DB", /*tp_name*/
5331 sizeof(DBObject), /*tp_basicsize*/
5332 0, /*tp_itemsize*/
5333 /* methods */
5334 (destructor)DB_dealloc, /*tp_dealloc*/
5335 0, /*tp_print*/
5336 (getattrfunc)DB_getattr, /*tp_getattr*/
5337 0, /*tp_setattr*/
5338 0, /*tp_compare*/
5339 0, /*tp_repr*/
5340 0, /*tp_as_number*/
5341 0, /*tp_as_sequence*/
5342 &DB_mapping,/*tp_as_mapping*/
5343 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005344#ifdef HAVE_WEAKREF
5345 0, /* tp_call */
5346 0, /* tp_str */
5347 0, /* tp_getattro */
5348 0, /* tp_setattro */
5349 0, /* tp_as_buffer */
5350 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5351 0, /* tp_doc */
5352 0, /* tp_traverse */
5353 0, /* tp_clear */
5354 0, /* tp_richcompare */
5355 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5356#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005357};
5358
5359
5360statichere PyTypeObject DBCursor_Type = {
5361 PyObject_HEAD_INIT(NULL)
5362 0, /*ob_size*/
5363 "DBCursor", /*tp_name*/
5364 sizeof(DBCursorObject), /*tp_basicsize*/
5365 0, /*tp_itemsize*/
5366 /* methods */
5367 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5368 0, /*tp_print*/
5369 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5370 0, /*tp_setattr*/
5371 0, /*tp_compare*/
5372 0, /*tp_repr*/
5373 0, /*tp_as_number*/
5374 0, /*tp_as_sequence*/
5375 0, /*tp_as_mapping*/
5376 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00005377#ifdef HAVE_WEAKREF
5378 0, /* tp_call */
5379 0, /* tp_str */
5380 0, /* tp_getattro */
5381 0, /* tp_setattro */
5382 0, /* tp_as_buffer */
5383 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5384 0, /* tp_doc */
5385 0, /* tp_traverse */
5386 0, /* tp_clear */
5387 0, /* tp_richcompare */
5388 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5389#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005390};
5391
5392
5393statichere PyTypeObject DBEnv_Type = {
5394 PyObject_HEAD_INIT(NULL)
5395 0, /*ob_size*/
5396 "DBEnv", /*tp_name*/
5397 sizeof(DBEnvObject), /*tp_basicsize*/
5398 0, /*tp_itemsize*/
5399 /* methods */
5400 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5401 0, /*tp_print*/
5402 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5403 0, /*tp_setattr*/
5404 0, /*tp_compare*/
5405 0, /*tp_repr*/
5406 0, /*tp_as_number*/
5407 0, /*tp_as_sequence*/
5408 0, /*tp_as_mapping*/
5409 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005410#ifdef HAVE_WEAKREF
5411 0, /* tp_call */
5412 0, /* tp_str */
5413 0, /* tp_getattro */
5414 0, /* tp_setattro */
5415 0, /* tp_as_buffer */
5416 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5417 0, /* tp_doc */
5418 0, /* tp_traverse */
5419 0, /* tp_clear */
5420 0, /* tp_richcompare */
5421 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5422#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005423};
5424
5425statichere PyTypeObject DBTxn_Type = {
5426 PyObject_HEAD_INIT(NULL)
5427 0, /*ob_size*/
5428 "DBTxn", /*tp_name*/
5429 sizeof(DBTxnObject), /*tp_basicsize*/
5430 0, /*tp_itemsize*/
5431 /* methods */
5432 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5433 0, /*tp_print*/
5434 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5435 0, /*tp_setattr*/
5436 0, /*tp_compare*/
5437 0, /*tp_repr*/
5438 0, /*tp_as_number*/
5439 0, /*tp_as_sequence*/
5440 0, /*tp_as_mapping*/
5441 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005442#ifdef HAVE_WEAKREF
5443 0, /* tp_call */
5444 0, /* tp_str */
5445 0, /* tp_getattro */
5446 0, /* tp_setattro */
5447 0, /* tp_as_buffer */
5448 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5449 0, /* tp_doc */
5450 0, /* tp_traverse */
5451 0, /* tp_clear */
5452 0, /* tp_richcompare */
5453 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5454#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005455};
5456
5457
5458statichere PyTypeObject DBLock_Type = {
5459 PyObject_HEAD_INIT(NULL)
5460 0, /*ob_size*/
5461 "DBLock", /*tp_name*/
5462 sizeof(DBLockObject), /*tp_basicsize*/
5463 0, /*tp_itemsize*/
5464 /* methods */
5465 (destructor)DBLock_dealloc, /*tp_dealloc*/
5466 0, /*tp_print*/
5467 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5468 0, /*tp_setattr*/
5469 0, /*tp_compare*/
5470 0, /*tp_repr*/
5471 0, /*tp_as_number*/
5472 0, /*tp_as_sequence*/
5473 0, /*tp_as_mapping*/
5474 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00005475#ifdef HAVE_WEAKREF
5476 0, /* tp_call */
5477 0, /* tp_str */
5478 0, /* tp_getattro */
5479 0, /* tp_setattro */
5480 0, /* tp_as_buffer */
5481 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5482 0, /* tp_doc */
5483 0, /* tp_traverse */
5484 0, /* tp_clear */
5485 0, /* tp_richcompare */
5486 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5487#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005488};
5489
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005490#if (DBVER >= 43)
5491statichere PyTypeObject DBSequence_Type = {
5492 PyObject_HEAD_INIT(NULL)
5493 0, /*ob_size*/
5494 "DBSequence", /*tp_name*/
5495 sizeof(DBSequenceObject), /*tp_basicsize*/
5496 0, /*tp_itemsize*/
5497 /* methods */
5498 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5499 0, /*tp_print*/
5500 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5501 0, /*tp_setattr*/
5502 0, /*tp_compare*/
5503 0, /*tp_repr*/
5504 0, /*tp_as_number*/
5505 0, /*tp_as_sequence*/
5506 0, /*tp_as_mapping*/
5507 0, /*tp_hash*/
5508#ifdef HAVE_WEAKREF
5509 0, /* tp_call */
5510 0, /* tp_str */
5511 0, /* tp_getattro */
5512 0, /* tp_setattro */
5513 0, /* tp_as_buffer */
5514 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5515 0, /* tp_doc */
5516 0, /* tp_traverse */
5517 0, /* tp_clear */
5518 0, /* tp_richcompare */
5519 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5520#endif
5521};
5522#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005523
5524/* --------------------------------------------------------------------- */
5525/* Module-level functions */
5526
5527static PyObject*
5528DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5529{
5530 PyObject* dbenvobj = NULL;
5531 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00005532 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005533
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005534 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5535 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536 return NULL;
5537 if (dbenvobj == Py_None)
5538 dbenvobj = NULL;
5539 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5540 makeTypeError("DBEnv", dbenvobj);
5541 return NULL;
5542 }
5543
5544 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5545}
5546
5547
5548static PyObject*
5549DBEnv_construct(PyObject* self, PyObject* args)
5550{
5551 int flags = 0;
5552 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5553 return (PyObject* )newDBEnvObject(flags);
5554}
5555
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005556#if (DBVER >= 43)
5557static PyObject*
5558DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5559{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005560 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005561 int flags = 0;
5562 static char* kwnames[] = { "db", "flags", NULL};
5563
5564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5565 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00005566 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005567 makeTypeError("DB", dbobj);
5568 return NULL;
5569 }
5570 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5571}
5572#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005573
5574static char bsddb_version_doc[] =
5575"Returns a tuple of major, minor, and patch release numbers of the\n\
5576underlying DB library.";
5577
5578static PyObject*
5579bsddb_version(PyObject* self, PyObject* args)
5580{
5581 int major, minor, patch;
5582
5583 if (!PyArg_ParseTuple(args, ":version"))
5584 return NULL;
5585 db_version(&major, &minor, &patch);
5586 return Py_BuildValue("(iii)", major, minor, patch);
5587}
5588
5589
5590/* List of functions defined in the module */
5591
5592static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005593 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5594 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5595#if (DBVER >= 43)
5596 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5597#endif
5598 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005599 {NULL, NULL} /* sentinel */
5600};
5601
5602
5603/* --------------------------------------------------------------------- */
5604/* Module initialization */
5605
5606
5607/* Convenience routine to export an integer value.
5608 * Errors are silently ignored, for better or for worse...
5609 */
5610#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5611
Gregory P. Smith41631e82003-09-21 00:08:14 +00005612#define MODULE_NAME_MAX_LEN 11
5613static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005614
5615DL_EXPORT(void) init_bsddb(void)
5616{
5617 PyObject* m;
5618 PyObject* d;
5619 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5620 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5621 PyObject* cvsid_s = PyString_FromString( rcs_id );
5622
5623 /* Initialize the type of the new type objects here; doing it here
5624 is required for portability to Windows without requiring C++. */
5625 DB_Type.ob_type = &PyType_Type;
5626 DBCursor_Type.ob_type = &PyType_Type;
5627 DBEnv_Type.ob_type = &PyType_Type;
5628 DBTxn_Type.ob_type = &PyType_Type;
5629 DBLock_Type.ob_type = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005630#if (DBVER >= 43)
5631 DBSequence_Type.ob_type = &PyType_Type;
5632#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633
5634
Mark Hammonda69d4092003-04-22 23:13:27 +00005635#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005636 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00005637 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005638#endif
5639
5640 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00005641 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00005642 if (m == NULL)
5643 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005644
5645 /* Add some symbolic constants to the module */
5646 d = PyModule_GetDict(m);
5647 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5648 PyDict_SetItemString(d, "cvsid", cvsid_s);
5649 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5650 Py_DECREF(pybsddb_version_s);
5651 pybsddb_version_s = NULL;
5652 Py_DECREF(cvsid_s);
5653 cvsid_s = NULL;
5654 Py_DECREF(db_version_s);
5655 db_version_s = NULL;
5656
5657 ADD_INT(d, DB_VERSION_MAJOR);
5658 ADD_INT(d, DB_VERSION_MINOR);
5659 ADD_INT(d, DB_VERSION_PATCH);
5660
5661 ADD_INT(d, DB_MAX_PAGES);
5662 ADD_INT(d, DB_MAX_RECORDS);
5663
Gregory P. Smith41631e82003-09-21 00:08:14 +00005664#if (DBVER >= 42)
5665 ADD_INT(d, DB_RPCCLIENT);
5666#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005667 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00005668 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5669 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5670#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005671 ADD_INT(d, DB_XA_CREATE);
5672
5673 ADD_INT(d, DB_CREATE);
5674 ADD_INT(d, DB_NOMMAP);
5675 ADD_INT(d, DB_THREAD);
5676
5677 ADD_INT(d, DB_FORCE);
5678 ADD_INT(d, DB_INIT_CDB);
5679 ADD_INT(d, DB_INIT_LOCK);
5680 ADD_INT(d, DB_INIT_LOG);
5681 ADD_INT(d, DB_INIT_MPOOL);
5682 ADD_INT(d, DB_INIT_TXN);
5683#if (DBVER >= 32)
5684 ADD_INT(d, DB_JOINENV);
5685#endif
5686
5687 ADD_INT(d, DB_RECOVER);
5688 ADD_INT(d, DB_RECOVER_FATAL);
5689 ADD_INT(d, DB_TXN_NOSYNC);
5690 ADD_INT(d, DB_USE_ENVIRON);
5691 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5692
5693 ADD_INT(d, DB_LOCKDOWN);
5694 ADD_INT(d, DB_PRIVATE);
5695 ADD_INT(d, DB_SYSTEM_MEM);
5696
5697 ADD_INT(d, DB_TXN_SYNC);
5698 ADD_INT(d, DB_TXN_NOWAIT);
5699
5700 ADD_INT(d, DB_EXCL);
5701 ADD_INT(d, DB_FCNTL_LOCKING);
5702 ADD_INT(d, DB_ODDFILESIZE);
5703 ADD_INT(d, DB_RDWRMASTER);
5704 ADD_INT(d, DB_RDONLY);
5705 ADD_INT(d, DB_TRUNCATE);
5706#if (DBVER >= 32)
5707 ADD_INT(d, DB_EXTENT);
5708 ADD_INT(d, DB_CDB_ALLDB);
5709 ADD_INT(d, DB_VERIFY);
5710#endif
5711 ADD_INT(d, DB_UPGRADE);
5712
5713 ADD_INT(d, DB_AGGRESSIVE);
5714 ADD_INT(d, DB_NOORDERCHK);
5715 ADD_INT(d, DB_ORDERCHKONLY);
5716 ADD_INT(d, DB_PR_PAGE);
5717#if ! (DBVER >= 33)
5718 ADD_INT(d, DB_VRFY_FLAGMASK);
5719 ADD_INT(d, DB_PR_HEADERS);
5720#endif
5721 ADD_INT(d, DB_PR_RECOVERYTEST);
5722 ADD_INT(d, DB_SALVAGE);
5723
5724 ADD_INT(d, DB_LOCK_NORUN);
5725 ADD_INT(d, DB_LOCK_DEFAULT);
5726 ADD_INT(d, DB_LOCK_OLDEST);
5727 ADD_INT(d, DB_LOCK_RANDOM);
5728 ADD_INT(d, DB_LOCK_YOUNGEST);
5729#if (DBVER >= 33)
5730 ADD_INT(d, DB_LOCK_MAXLOCKS);
5731 ADD_INT(d, DB_LOCK_MINLOCKS);
5732 ADD_INT(d, DB_LOCK_MINWRITE);
5733#endif
5734
5735
5736#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005737 /* docs say to use zero instead */
5738 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005739#else
5740 ADD_INT(d, DB_LOCK_CONFLICT);
5741#endif
5742
5743 ADD_INT(d, DB_LOCK_DUMP);
5744 ADD_INT(d, DB_LOCK_GET);
5745 ADD_INT(d, DB_LOCK_INHERIT);
5746 ADD_INT(d, DB_LOCK_PUT);
5747 ADD_INT(d, DB_LOCK_PUT_ALL);
5748 ADD_INT(d, DB_LOCK_PUT_OBJ);
5749
5750 ADD_INT(d, DB_LOCK_NG);
5751 ADD_INT(d, DB_LOCK_READ);
5752 ADD_INT(d, DB_LOCK_WRITE);
5753 ADD_INT(d, DB_LOCK_NOWAIT);
5754#if (DBVER >= 32)
5755 ADD_INT(d, DB_LOCK_WAIT);
5756#endif
5757 ADD_INT(d, DB_LOCK_IWRITE);
5758 ADD_INT(d, DB_LOCK_IREAD);
5759 ADD_INT(d, DB_LOCK_IWR);
5760#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00005761#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005762 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00005763#else
5764 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5765#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005766 ADD_INT(d, DB_LOCK_WWRITE);
5767#endif
5768
5769 ADD_INT(d, DB_LOCK_RECORD);
5770 ADD_INT(d, DB_LOCK_UPGRADE);
5771#if (DBVER >= 32)
5772 ADD_INT(d, DB_LOCK_SWITCH);
5773#endif
5774#if (DBVER >= 33)
5775 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5776#endif
5777
5778 ADD_INT(d, DB_LOCK_NOWAIT);
5779 ADD_INT(d, DB_LOCK_RECORD);
5780 ADD_INT(d, DB_LOCK_UPGRADE);
5781
5782#if (DBVER >= 33)
5783 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005784#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005785 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005786#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005787 ADD_INT(d, DB_LSTAT_FREE);
5788 ADD_INT(d, DB_LSTAT_HELD);
5789#if (DBVER == 33)
5790 ADD_INT(d, DB_LSTAT_NOGRANT);
5791#endif
5792 ADD_INT(d, DB_LSTAT_PENDING);
5793 ADD_INT(d, DB_LSTAT_WAITING);
5794#endif
5795
5796 ADD_INT(d, DB_ARCH_ABS);
5797 ADD_INT(d, DB_ARCH_DATA);
5798 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00005799#if (DBVER >= 42)
5800 ADD_INT(d, DB_ARCH_REMOVE);
5801#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005802
5803 ADD_INT(d, DB_BTREE);
5804 ADD_INT(d, DB_HASH);
5805 ADD_INT(d, DB_RECNO);
5806 ADD_INT(d, DB_QUEUE);
5807 ADD_INT(d, DB_UNKNOWN);
5808
5809 ADD_INT(d, DB_DUP);
5810 ADD_INT(d, DB_DUPSORT);
5811 ADD_INT(d, DB_RECNUM);
5812 ADD_INT(d, DB_RENUMBER);
5813 ADD_INT(d, DB_REVSPLITOFF);
5814 ADD_INT(d, DB_SNAPSHOT);
5815
5816 ADD_INT(d, DB_JOIN_NOSORT);
5817
5818 ADD_INT(d, DB_AFTER);
5819 ADD_INT(d, DB_APPEND);
5820 ADD_INT(d, DB_BEFORE);
5821 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005822#if (DBVER >= 41)
5823 _addIntToDict(d, "DB_CHECKPOINT", 0);
5824#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005825 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005826 ADD_INT(d, DB_CURLSN);
5827#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00005828#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005829 ADD_INT(d, DB_COMMIT);
5830#endif
5831 ADD_INT(d, DB_CONSUME);
5832#if (DBVER >= 32)
5833 ADD_INT(d, DB_CONSUME_WAIT);
5834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005835 ADD_INT(d, DB_CURRENT);
5836#if (DBVER >= 33)
5837 ADD_INT(d, DB_FAST_STAT);
5838#endif
5839 ADD_INT(d, DB_FIRST);
5840 ADD_INT(d, DB_FLUSH);
5841 ADD_INT(d, DB_GET_BOTH);
5842 ADD_INT(d, DB_GET_RECNO);
5843 ADD_INT(d, DB_JOIN_ITEM);
5844 ADD_INT(d, DB_KEYFIRST);
5845 ADD_INT(d, DB_KEYLAST);
5846 ADD_INT(d, DB_LAST);
5847 ADD_INT(d, DB_NEXT);
5848 ADD_INT(d, DB_NEXT_DUP);
5849 ADD_INT(d, DB_NEXT_NODUP);
5850 ADD_INT(d, DB_NODUPDATA);
5851 ADD_INT(d, DB_NOOVERWRITE);
5852 ADD_INT(d, DB_NOSYNC);
5853 ADD_INT(d, DB_POSITION);
5854 ADD_INT(d, DB_PREV);
5855 ADD_INT(d, DB_PREV_NODUP);
5856 ADD_INT(d, DB_RECORDCOUNT);
5857 ADD_INT(d, DB_SET);
5858 ADD_INT(d, DB_SET_RANGE);
5859 ADD_INT(d, DB_SET_RECNO);
5860 ADD_INT(d, DB_WRITECURSOR);
5861
5862 ADD_INT(d, DB_OPFLAGS_MASK);
5863 ADD_INT(d, DB_RMW);
5864#if (DBVER >= 33)
5865 ADD_INT(d, DB_DIRTY_READ);
5866 ADD_INT(d, DB_MULTIPLE);
5867 ADD_INT(d, DB_MULTIPLE_KEY);
5868#endif
5869
Gregory P. Smith29602d22006-01-24 09:46:48 +00005870#if (DBVER >= 44)
5871 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5872 ADD_INT(d, DB_READ_COMMITTED);
5873#endif
5874
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005875#if (DBVER >= 33)
5876 ADD_INT(d, DB_DONOTINDEX);
5877#endif
5878
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005879#if (DBVER >= 41)
5880 _addIntToDict(d, "DB_INCOMPLETE", 0);
5881#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005882 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005883#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005884 ADD_INT(d, DB_KEYEMPTY);
5885 ADD_INT(d, DB_KEYEXIST);
5886 ADD_INT(d, DB_LOCK_DEADLOCK);
5887 ADD_INT(d, DB_LOCK_NOTGRANTED);
5888 ADD_INT(d, DB_NOSERVER);
5889 ADD_INT(d, DB_NOSERVER_HOME);
5890 ADD_INT(d, DB_NOSERVER_ID);
5891 ADD_INT(d, DB_NOTFOUND);
5892 ADD_INT(d, DB_OLD_VERSION);
5893 ADD_INT(d, DB_RUNRECOVERY);
5894 ADD_INT(d, DB_VERIFY_BAD);
5895#if (DBVER >= 33)
5896 ADD_INT(d, DB_PAGE_NOTFOUND);
5897 ADD_INT(d, DB_SECONDARY_BAD);
5898#endif
5899#if (DBVER >= 40)
5900 ADD_INT(d, DB_STAT_CLEAR);
5901 ADD_INT(d, DB_REGION_INIT);
5902 ADD_INT(d, DB_NOLOCKING);
5903 ADD_INT(d, DB_YIELDCPU);
5904 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5905 ADD_INT(d, DB_NOPANIC);
5906#endif
5907
Gregory P. Smith41631e82003-09-21 00:08:14 +00005908#if (DBVER >= 42)
5909 ADD_INT(d, DB_TIME_NOTGRANTED);
5910 ADD_INT(d, DB_TXN_NOT_DURABLE);
5911 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5912 ADD_INT(d, DB_LOG_AUTOREMOVE);
5913 ADD_INT(d, DB_DIRECT_LOG);
5914 ADD_INT(d, DB_DIRECT_DB);
5915 ADD_INT(d, DB_INIT_REP);
5916 ADD_INT(d, DB_ENCRYPT);
5917 ADD_INT(d, DB_CHKSUM);
5918#endif
5919
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005920#if (DBVER >= 43)
5921 ADD_INT(d, DB_LOG_INMEMORY);
5922 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005923 ADD_INT(d, DB_SEQ_DEC);
5924 ADD_INT(d, DB_SEQ_INC);
5925 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00005926#endif
5927
Barry Warsaw9a0d7792002-12-30 20:53:52 +00005928#if (DBVER >= 41)
5929 ADD_INT(d, DB_ENCRYPT_AES);
5930 ADD_INT(d, DB_AUTO_COMMIT);
5931#else
5932 /* allow berkeleydb 4.1 aware apps to run on older versions */
5933 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5934#endif
5935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005936 ADD_INT(d, EINVAL);
5937 ADD_INT(d, EACCES);
5938 ADD_INT(d, ENOSPC);
5939 ADD_INT(d, ENOMEM);
5940 ADD_INT(d, EAGAIN);
5941 ADD_INT(d, EBUSY);
5942 ADD_INT(d, EEXIST);
5943 ADD_INT(d, ENOENT);
5944 ADD_INT(d, EPERM);
5945
Barry Warsaw1baa9822003-03-31 19:51:29 +00005946#if (DBVER >= 40)
5947 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5948 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5949#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005950
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005951 /* The exception name must be correct for pickled exception *
5952 * objects to unpickle properly. */
5953#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5954#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5955#else
5956#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5957#endif
5958
5959 /* All the rest of the exceptions derive only from DBError */
5960#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5961 PyDict_SetItemString(d, #name, name)
5962
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005963 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00005964 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5965 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005966
Gregory P. Smithe9477062005-06-04 06:46:59 +00005967 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5968 * from both DBError and KeyError, since the API only supports
5969 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005970 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00005971 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5972 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005973 Py_file_input, d, d);
5974 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00005975 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005976 PyDict_DelItemString(d, "KeyError");
5977
5978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005979#if !INCOMPLETE_IS_WARNING
5980 MAKE_EX(DBIncompleteError);
5981#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00005982 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005983 MAKE_EX(DBKeyEmptyError);
5984 MAKE_EX(DBKeyExistError);
5985 MAKE_EX(DBLockDeadlockError);
5986 MAKE_EX(DBLockNotGrantedError);
5987 MAKE_EX(DBOldVersionError);
5988 MAKE_EX(DBRunRecoveryError);
5989 MAKE_EX(DBVerifyBadError);
5990 MAKE_EX(DBNoServerError);
5991 MAKE_EX(DBNoServerHomeError);
5992 MAKE_EX(DBNoServerIDError);
5993#if (DBVER >= 33)
5994 MAKE_EX(DBPageNotFoundError);
5995 MAKE_EX(DBSecondaryBadError);
5996#endif
5997
5998 MAKE_EX(DBInvalidArgError);
5999 MAKE_EX(DBAccessError);
6000 MAKE_EX(DBNoSpaceError);
6001 MAKE_EX(DBNoMemoryError);
6002 MAKE_EX(DBAgainError);
6003 MAKE_EX(DBBusyError);
6004 MAKE_EX(DBFileExistsError);
6005 MAKE_EX(DBNoSuchFileError);
6006 MAKE_EX(DBPermissionsError);
6007
6008#undef MAKE_EX
6009
6010 /* Check for errors */
6011 if (PyErr_Occurred()) {
6012 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006013 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 }
6015}
Gregory P. Smith41631e82003-09-21 00:08:14 +00006016
6017/* allow this module to be named _pybsddb so that it can be installed
6018 * and imported on top of python >= 2.3 that includes its own older
6019 * copy of the library named _bsddb without importing the old version. */
6020DL_EXPORT(void) init_pybsddb(void)
6021{
6022 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6023 init_bsddb();
6024}