blob: f5e95664302296483752b747f488b5b96ec8ce38 [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
Jesus Ceaef9764f2008-05-13 18:45:46 +000039 * to compile with Berkeley DB 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
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
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 *
Jesus Ceaef9764f2008-05-13 18:45:46 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
53 * Since January 2008, new maintainer is Jesus Cea <jcea@argo.es>.
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000055 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000057 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000066 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000067 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000068 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000074 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000075 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
Gregory P. Smitha703a212003-11-03 01:04:41 +000091#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000092#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000103#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000104typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#endif
106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000107#ifdef WITH_THREAD
108
109/* These are for when calling Python --> C */
110#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
111#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
112
Mark Hammonda69d4092003-04-22 23:13:27 +0000113/* For 2.3, use the PyGILState_ calls */
114#if (PY_VERSION_HEX >= 0x02030000)
115#define MYDB_USE_GILSTATE
116#endif
117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000118/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000119#if defined(MYDB_USE_GILSTATE)
120#define MYDB_BEGIN_BLOCK_THREADS \
121 PyGILState_STATE __savestate = PyGILState_Ensure();
122#define MYDB_END_BLOCK_THREADS \
123 PyGILState_Release(__savestate);
124#else /* MYDB_USE_GILSTATE */
125/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000126static PyInterpreterState* _db_interpreterState = NULL;
127#define MYDB_BEGIN_BLOCK_THREADS { \
128 PyThreadState* prevState; \
129 PyThreadState* newState; \
130 PyEval_AcquireLock(); \
131 newState = PyThreadState_New(_db_interpreterState); \
132 prevState = PyThreadState_Swap(newState);
133
134#define MYDB_END_BLOCK_THREADS \
135 newState = PyThreadState_Swap(prevState); \
136 PyThreadState_Clear(newState); \
137 PyEval_ReleaseLock(); \
138 PyThreadState_Delete(newState); \
139 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000140#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141
142#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000143/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000144#define MYDB_BEGIN_ALLOW_THREADS
145#define MYDB_END_ALLOW_THREADS
146#define MYDB_BEGIN_BLOCK_THREADS
147#define MYDB_END_BLOCK_THREADS
148
149#endif
150
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000151/* Should DB_INCOMPLETE be turned into a warning or an exception? */
152#define INCOMPLETE_IS_WARNING 1
153
154/* --------------------------------------------------------------------- */
155/* Exceptions */
156
157static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000158static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000159static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000160static PyObject* DBKeyExistError; /* DB_KEYEXIST */
161static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
162static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
163static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
164static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
165static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
166static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
167static PyObject* DBNoServerError; /* DB_NOSERVER */
168static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
169static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
170#if (DBVER >= 33)
171static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
172static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
173#endif
174
175#if !INCOMPLETE_IS_WARNING
176static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
177#endif
178
179static PyObject* DBInvalidArgError; /* EINVAL */
180static PyObject* DBAccessError; /* EACCES */
181static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000182static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000183static PyObject* DBAgainError; /* EAGAIN */
184static PyObject* DBBusyError; /* EBUSY */
185static PyObject* DBFileExistsError; /* EEXIST */
186static PyObject* DBNoSuchFileError; /* ENOENT */
187static PyObject* DBPermissionsError; /* EPERM */
188
Jesus Ceaef9764f2008-05-13 18:45:46 +0000189#if (DBVER >= 42)
190static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
191#endif
192
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000193#if (DBVER < 43)
194#define DB_BUFFER_SMALL ENOMEM
195#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000196
197
198/* --------------------------------------------------------------------- */
199/* Structure definitions */
200
Gregory P. Smith39250532007-10-09 06:02:21 +0000201#if PYTHON_API_VERSION < 1010
202#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205
Gregory P. Smith39250532007-10-09 06:02:21 +0000206/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000207#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000208#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000209
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000210
211staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000212#if (DBVER >= 43)
213staticforward PyTypeObject DBSequence_Type;
214#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000215
Martin v. Löwis83c92012008-04-24 13:17:24 +0000216#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000217/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000218#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000219#endif
220
Christian Heimese93237d2007-12-19 02:37:44 +0000221#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
222#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
223#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
224#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
225#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000226#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000227#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000228#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229
Jesus Ceaef9764f2008-05-13 18:45:46 +0000230#if (DBVER < 46)
231 #define _DBC_close(dbc) dbc->c_close(dbc)
232 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
233 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
234 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
235 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
236 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
237 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
238#else
239 #define _DBC_close(dbc) dbc->close(dbc)
240 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
241 #define _DBC_del(dbc,a) dbc->del(dbc,a)
242 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
243 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
244 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
245 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
246#endif
247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249/* --------------------------------------------------------------------- */
250/* Utility macros and functions */
251
Jesus Ceaef9764f2008-05-13 18:45:46 +0000252#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
253 { \
254 object->sibling_next=backlink; \
255 object->sibling_prev_p=&(backlink); \
256 backlink=object; \
257 if (object->sibling_next) { \
258 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
259 } \
260 }
261
262#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
263 { \
264 if (object->sibling_next) { \
265 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
266 } \
267 *(object->sibling_prev_p)=object->sibling_next; \
268 }
269
270#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
271 { \
272 if (object->sibling_next) { \
273 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
274 } \
275 if (object->sibling_prev_p) { \
276 *(object->sibling_prev_p)=object->sibling_next; \
277 } \
278 }
279
280#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
281 { \
282 object->sibling_next_txn=backlink; \
283 object->sibling_prev_p_txn=&(backlink); \
284 backlink=object; \
285 if (object->sibling_next_txn) { \
286 object->sibling_next_txn->sibling_prev_p_txn= \
287 &(object->sibling_next_txn); \
288 } \
289 }
290
291#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
292 { \
293 if (object->sibling_next_txn) { \
294 object->sibling_next_txn->sibling_prev_p_txn= \
295 object->sibling_prev_p_txn; \
296 } \
297 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
298 }
299
300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301#define RETURN_IF_ERR() \
302 if (makeDBError(err)) { \
303 return NULL; \
304 }
305
306#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
307
Gregory P. Smithe2767172003-11-02 08:06:29 +0000308#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
309 if ((nonNull) == NULL) { \
310 PyObject *errTuple = NULL; \
311 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
312 PyErr_SetObject((pyErrObj), errTuple); \
313 Py_DECREF(errTuple); \
314 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000315 }
316
Gregory P. Smithe2767172003-11-02 08:06:29 +0000317#define CHECK_DB_NOT_CLOSED(dbobj) \
318 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
319
320#define CHECK_ENV_NOT_CLOSED(env) \
321 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000322
323#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000324 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000325
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000326#if (DBVER >= 43)
327#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
328 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
329#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330
331#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
332 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
333
334#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
335
336#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000337 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000338
339
340static int makeDBError(int err);
341
342
343/* Return the access method type of the DBObject */
344static int _DB_get_type(DBObject* self)
345{
346#if (DBVER >= 33)
347 DBTYPE type;
348 int err;
349 err = self->db->get_type(self->db, &type);
350 if (makeDBError(err)) {
351 return -1;
352 }
353 return type;
354#else
355 return self->db->get_type(self->db);
356#endif
357}
358
359
360/* Create a DBT structure (containing key and data values) from Python
361 strings. Returns 1 on success, 0 on an error. */
362static int make_dbt(PyObject* obj, DBT* dbt)
363{
364 CLEAR_DBT(*dbt);
365 if (obj == Py_None) {
366 /* no need to do anything, the structure has already been zeroed */
367 }
368 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
369 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000370 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371 return 0;
372 }
373 return 1;
374}
375
376
377/* Recno and Queue DBs can have integer keys. This function figures out
378 what's been given, verifies that it's allowed, and then makes the DBT.
379
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000380 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000381static int
382make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000383{
384 db_recno_t recno;
385 int type;
386
387 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000388 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000389 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000390 if (type == -1)
391 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000392 if (type == DB_RECNO || type == DB_QUEUE) {
393 PyErr_SetString(
394 PyExc_TypeError,
395 "None keys not allowed for Recno and Queue DB's");
396 return 0;
397 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 /* no need to do anything, the structure has already been zeroed */
399 }
400
401 else if (PyString_Check(keyobj)) {
402 /* verify access method type */
403 type = _DB_get_type(self);
404 if (type == -1)
405 return 0;
406 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 PyErr_SetString(
408 PyExc_TypeError,
409 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000410 return 0;
411 }
412
Gregory P. Smith10bed542007-10-09 06:50:43 +0000413 /*
414 * NOTE(gps): I don't like doing a data copy here, it seems
415 * wasteful. But without a clean way to tell FREE_DBT if it
416 * should free key->data or not we have to. Other places in
417 * the code check for DB_THREAD and forceably set DBT_MALLOC
418 * when we otherwise would leave flags 0 to indicate that.
419 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000420 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000421 if (key->data == NULL) {
422 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
423 return 0;
424 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000425 memcpy(key->data, PyString_AS_STRING(keyobj),
426 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000427 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 key->size = PyString_GET_SIZE(keyobj);
429 }
430
431 else if (PyInt_Check(keyobj)) {
432 /* verify access method type */
433 type = _DB_get_type(self);
434 if (type == -1)
435 return 0;
436 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000437 /* if BTREE then an Integer key is allowed with the
438 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000439 *pflags |= DB_SET_RECNO;
440 }
441 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000442 PyErr_SetString(
443 PyExc_TypeError,
444 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000445 return 0;
446 }
447
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000448 /* Make a key out of the requested recno, use allocated space so DB
449 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 recno = PyInt_AS_LONG(keyobj);
451 key->data = malloc(sizeof(db_recno_t));
452 if (key->data == NULL) {
453 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
454 return 0;
455 }
456 key->ulen = key->size = sizeof(db_recno_t);
457 memcpy(key->data, &recno, sizeof(db_recno_t));
458 key->flags = DB_DBT_REALLOC;
459 }
460 else {
461 PyErr_Format(PyExc_TypeError,
462 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000463 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000464 return 0;
465 }
466
467 return 1;
468}
469
470
471/* Add partial record access to an existing DBT data struct.
472 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
473 and the data storage/retrieval will be done using dlen and doff. */
474static int add_partial_dbt(DBT* d, int dlen, int doff) {
475 /* if neither were set we do nothing (-1 is the default value) */
476 if ((dlen == -1) && (doff == -1)) {
477 return 1;
478 }
479
480 if ((dlen < 0) || (doff < 0)) {
481 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
482 return 0;
483 }
484
485 d->flags = d->flags | DB_DBT_PARTIAL;
486 d->dlen = (unsigned int) dlen;
487 d->doff = (unsigned int) doff;
488 return 1;
489}
490
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
492/* TODO: make this use the native libc strlcpy() when available (BSD) */
493unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
494{
495 unsigned int srclen, copylen;
496
497 srclen = strlen(src);
498 if (n <= 0)
499 return srclen;
500 copylen = (srclen > n-1) ? n-1 : srclen;
501 /* populate dest[0] thru dest[copylen-1] */
502 memcpy(dest, src, copylen);
503 /* guarantee null termination */
504 dest[copylen] = 0;
505
506 return srclen;
507}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000509/* Callback used to save away more information about errors from the DB
510 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000511static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000512#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514#else
515static void _db_errorCallback(const DB_ENV *db_env,
516 const char* prefix, const char* msg)
517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000519 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520}
521
522
Jesus Ceaef9764f2008-05-13 18:45:46 +0000523/*
524** We need these functions because some results
525** are undefined if pointer is NULL. Some other
526** give None instead of "".
527**
528** This functions are static and will be
529** -I hope- inlined.
530*/
531static const char *DummyString = "This string is a simple placeholder";
532static PyObject *Build_PyString(const char *p,int s)
533{
534 if (!p) {
535 p=DummyString;
536 assert(s==0);
537 }
538 return PyString_FromStringAndSize(p,s);
539}
540
541static PyObject *BuildValue_S(const void *p,int s)
542{
543 if (!p) {
544 p=DummyString;
545 assert(s==0);
546 }
547 return Py_BuildValue("s#",p,s);
548}
549
550static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
551{
552 if (!p1) {
553 p1=DummyString;
554 assert(s1==0);
555 }
556 if (!p2) {
557 p2=DummyString;
558 assert(s2==0);
559 }
560 return Py_BuildValue("s#s#",p1,s1,p2,s2);
561}
562
563static PyObject *BuildValue_IS(int i,const void *p,int s)
564{
565 if (!p) {
566 p=DummyString;
567 assert(s==0);
568 }
569 return Py_BuildValue("is#",i,p,s);
570}
571
572static PyObject *BuildValue_LS(long i,const void *p,int s)
573{
574 if (!p) {
575 p=DummyString;
576 assert(s==0);
577 }
578 return Py_BuildValue("ls#",i,p,s);
579}
580
581
582
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000583/* make a nice exception object to raise for errors. */
584static int makeDBError(int err)
585{
586 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000587 PyObject *errObj = NULL;
588 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000589 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000590 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000591
592 switch (err) {
593 case 0: /* successful, no error */ break;
594
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000595#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 case DB_INCOMPLETE:
597#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000598 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
599 /* Ensure that bytes_left never goes negative */
600 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
601 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
602 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000604 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000605 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000606 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000607 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608
609#else /* do an exception instead */
610 errObj = DBIncompleteError;
611#endif
612 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000613#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614
615 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
616 case DB_KEYEXIST: errObj = DBKeyExistError; break;
617 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
618 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
619 case DB_NOTFOUND: errObj = DBNotFoundError; break;
620 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
621 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
622 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
623 case DB_NOSERVER: errObj = DBNoServerError; break;
624 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
625 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
626#if (DBVER >= 33)
627 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
628 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
629#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000630 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000631
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000632#if (DBVER >= 43)
633 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
634 case ENOMEM: errObj = PyExc_MemoryError; break;
635#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000636 case EINVAL: errObj = DBInvalidArgError; break;
637 case EACCES: errObj = DBAccessError; break;
638 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000639 case EAGAIN: errObj = DBAgainError; break;
640 case EBUSY : errObj = DBBusyError; break;
641 case EEXIST: errObj = DBFileExistsError; break;
642 case ENOENT: errObj = DBNoSuchFileError; break;
643 case EPERM : errObj = DBPermissionsError; break;
644
Jesus Ceaef9764f2008-05-13 18:45:46 +0000645#if (DBVER >= 42)
646 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
647#endif
648
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000649 default: errObj = DBError; break;
650 }
651
652 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000653 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
654 /* Ensure that bytes_left never goes negative */
655 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
656 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
657 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000658 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000659 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000661 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000662
663 errTuple = Py_BuildValue("(is)", err, errTxt);
664 PyErr_SetObject(errObj, errTuple);
665 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 }
667
668 return ((errObj != NULL) || exceptionRaised);
669}
670
671
672
673/* set a type exception */
674static void makeTypeError(char* expected, PyObject* found)
675{
676 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000677 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678}
679
680
681/* verify that an obj is either None or a DBTxn, and set the txn pointer */
682static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
683{
684 if (txnobj == Py_None || txnobj == NULL) {
685 *txn = NULL;
686 return 1;
687 }
688 if (DBTxnObject_Check(txnobj)) {
689 *txn = ((DBTxnObject*)txnobj)->txn;
690 return 1;
691 }
692 else
693 makeTypeError("DBTxn", txnobj);
694 return 0;
695}
696
697
698/* Delete a key from a database
699 Returns 0 on success, -1 on an error. */
700static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
701{
702 int err;
703
704 MYDB_BEGIN_ALLOW_THREADS;
705 err = self->db->del(self->db, txn, key, 0);
706 MYDB_END_ALLOW_THREADS;
707 if (makeDBError(err)) {
708 return -1;
709 }
710 self->haveStat = 0;
711 return 0;
712}
713
714
715/* Store a key into a database
716 Returns 0 on success, -1 on an error. */
717static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
718{
719 int err;
720
721 MYDB_BEGIN_ALLOW_THREADS;
722 err = self->db->put(self->db, txn, key, data, flags);
723 MYDB_END_ALLOW_THREADS;
724 if (makeDBError(err)) {
725 return -1;
726 }
727 self->haveStat = 0;
728 return 0;
729}
730
731/* Get a key/data pair from a cursor */
732static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
733 PyObject *args, PyObject *kwargs, char *format)
734{
735 int err;
736 PyObject* retval = NULL;
737 DBT key, data;
738 int dlen = -1;
739 int doff = -1;
740 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000741 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742
743 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
744 &flags, &dlen, &doff))
745 return NULL;
746
747 CHECK_CURSOR_NOT_CLOSED(self);
748
749 flags |= extra_flags;
750 CLEAR_DBT(key);
751 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 if (!add_partial_dbt(&data, dlen, doff))
753 return NULL;
754
755 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000756 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757 MYDB_END_ALLOW_THREADS;
758
Gregory P. Smithe9477062005-06-04 06:46:59 +0000759 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
760 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000761 Py_INCREF(Py_None);
762 retval = Py_None;
763 }
764 else if (makeDBError(err)) {
765 retval = NULL;
766 }
767 else { /* otherwise, success! */
768
769 /* if Recno or Queue, return the key as an Int */
770 switch (_DB_get_type(self->mydb)) {
771 case -1:
772 retval = NULL;
773 break;
774
775 case DB_RECNO:
776 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000777 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000778 break;
779 case DB_HASH:
780 case DB_BTREE:
781 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000782 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 break;
784 }
785 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786 return retval;
787}
788
789
790/* add an integer to a dictionary using the given name as a key */
791static void _addIntToDict(PyObject* dict, char *name, int value)
792{
793 PyObject* v = PyInt_FromLong((long) value);
794 if (!v || PyDict_SetItemString(dict, name, v))
795 PyErr_Clear();
796
797 Py_XDECREF(v);
798}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000799
800/* The same, when the value is a time_t */
801static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
802{
803 PyObject* v;
804 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000805#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000806 if (sizeof(time_t) > sizeof(long))
807 v = PyLong_FromLongLong((PY_LONG_LONG) value);
808 else
809#endif
810 v = PyInt_FromLong((long) value);
811 if (!v || PyDict_SetItemString(dict, name, v))
812 PyErr_Clear();
813
814 Py_XDECREF(v);
815}
816
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000817#if (DBVER >= 43)
818/* add an db_seq_t to a dictionary using the given name as a key */
819static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
820{
821 PyObject* v = PyLong_FromLongLong(value);
822 if (!v || PyDict_SetItemString(dict, name, v))
823 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000825 Py_XDECREF(v);
826}
827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828
Jesus Ceaef9764f2008-05-13 18:45:46 +0000829#if (DBVER >= 40)
830static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
831{
832 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
833 if (!v || PyDict_SetItemString(dict, name, v))
834 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835
Jesus Ceaef9764f2008-05-13 18:45:46 +0000836 Py_XDECREF(v);
837}
838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839
840/* --------------------------------------------------------------------- */
841/* Allocators and deallocators */
842
843static DBObject*
844newDBObject(DBEnvObject* arg, int flags)
845{
846 DBObject* self;
847 DB_ENV* db_env = NULL;
848 int err;
849
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 if (self == NULL)
852 return NULL;
853
854 self->haveStat = 0;
855 self->flags = 0;
856 self->setflags = 0;
857 self->myenvobj = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000858 self->children_cursors = NULL;
859#if (DBVER >=43)
860 self->children_sequences = NULL;
861#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862#if (DBVER >= 33)
863 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000865 self->primaryDBType = 0;
866#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000867 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868
869 /* keep a reference to our python DBEnv object */
870 if (arg) {
871 Py_INCREF(arg);
872 self->myenvobj = arg;
873 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000874 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
875 } else {
876 self->sibling_prev_p=NULL;
877 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000879 self->txn=NULL;
880 self->sibling_prev_p_txn=NULL;
881 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882
883 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000884 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000886 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
887 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888
889 MYDB_BEGIN_ALLOW_THREADS;
890 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000891 if (self->db != NULL) {
892 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000894 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000895#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000897 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000898 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
899 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000900 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (makeDBError(err)) {
902 if (self->myenvobj) {
903 Py_DECREF(self->myenvobj);
904 self->myenvobj = NULL;
905 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000906 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 self = NULL;
908 }
909 return self;
910}
911
912
Jesus Ceaef9764f2008-05-13 18:45:46 +0000913/* Forward declaration */
914static PyObject *DB_close_internal(DBObject* self, int flags);
915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916static void
917DB_dealloc(DBObject* self)
918{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000919 PyObject *dummy;
920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +0000922 dummy=DB_close_internal(self,0);
923 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000925 if (self->in_weakreflist != NULL) {
926 PyObject_ClearWeakRefs((PyObject *) self);
927 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928 if (self->myenvobj) {
929 Py_DECREF(self->myenvobj);
930 self->myenvobj = NULL;
931 }
932#if (DBVER >= 33)
933 if (self->associateCallback != NULL) {
934 Py_DECREF(self->associateCallback);
935 self->associateCallback = NULL;
936 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000937 if (self->btCompareCallback != NULL) {
938 Py_DECREF(self->btCompareCallback);
939 self->btCompareCallback = NULL;
940 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943}
944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +0000946newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000948 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000949 if (self == NULL)
950 return NULL;
951
952 self->dbc = dbc;
953 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000954
955 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
956 if (txn && ((PyObject *)txn!=Py_None)) {
957 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
958 self->txn=txn;
959 } else {
960 self->txn=NULL;
961 }
962
Gregory P. Smitha703a212003-11-03 01:04:41 +0000963 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 Py_INCREF(self->mydb);
965 return self;
966}
967
968
Jesus Ceaef9764f2008-05-13 18:45:46 +0000969/* Forward declaration */
970static PyObject *DBC_close_internal(DBCursorObject* self);
971
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972static void
973DBCursor_dealloc(DBCursorObject* self)
974{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000975 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000976
Jesus Ceaef9764f2008-05-13 18:45:46 +0000977 if (self->dbc != NULL) {
978 dummy=DBC_close_internal(self);
979 Py_XDECREF(dummy);
980 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000981 if (self->in_weakreflist != NULL) {
982 PyObject_ClearWeakRefs((PyObject *) self);
983 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000984 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000986}
987
988
989static DBEnvObject*
990newDBEnvObject(int flags)
991{
992 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000993 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994 if (self == NULL)
995 return NULL;
996
997 self->closed = 1;
998 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000999 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1000 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001001 self->children_dbs = NULL;
1002 self->children_txns = NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001004
Jesus Ceaef9764f2008-05-13 18:45:46 +00001005#if (DBVER >= 40)
1006 self->event_notifyCallback = NULL;
1007#endif
1008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 MYDB_BEGIN_ALLOW_THREADS;
1010 err = db_env_create(&self->db_env, flags);
1011 MYDB_END_ALLOW_THREADS;
1012 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001013 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 self = NULL;
1015 }
1016 else {
1017 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001018 self->db_env->app_private=self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 }
1020 return self;
1021}
1022
Jesus Ceaef9764f2008-05-13 18:45:46 +00001023/* Forward declaration */
1024static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025
1026static void
1027DBEnv_dealloc(DBEnvObject* self)
1028{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001029 PyObject *dummy;
1030
1031 if (self->db_env && !self->closed) {
1032 dummy=DBEnv_close_internal(self,0);
1033 Py_XDECREF(dummy);
1034 }
1035
1036#if (DBVER >= 40)
1037 Py_XDECREF(self->event_notifyCallback);
1038 self->event_notifyCallback = NULL;
1039#endif
1040
Gregory P. Smith31c50652004-06-28 01:20:40 +00001041 if (self->in_weakreflist != NULL) {
1042 PyObject_ClearWeakRefs((PyObject *) self);
1043 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046}
1047
1048
1049static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001050newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001051{
1052 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001053 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001054
Neal Norwitzb4a55812004-07-09 23:30:57 +00001055 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 if (self == NULL)
1057 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001058
Gregory P. Smith31c50652004-06-28 01:20:40 +00001059 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001060 self->children_txns = NULL;
1061 self->children_dbs = NULL;
1062 self->children_cursors = NULL;
1063 self->children_sequences = NULL;
1064 self->flag_prepare = 0;
1065 self->parent_txn = NULL;
1066 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067
Jesus Ceaef9764f2008-05-13 18:45:46 +00001068 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001069 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001070 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001071
1072 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001073 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001074 } else {
1075 MYDB_BEGIN_ALLOW_THREADS;
1076#if (DBVER >= 40)
1077 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1078#else
1079 err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
1080#endif
1081 MYDB_END_ALLOW_THREADS;
1082
1083 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001084 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001085 return NULL;
1086 }
1087 }
1088
Gregory P. Smith664782e2008-05-17 06:12:02 +00001089 /* Can't use 'parent' because could be 'parent==Py_None' */
1090 if (parent_txn) {
1091 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001092 Py_INCREF(parent);
1093 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001094 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001095 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001096 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001097 Py_INCREF(myenv);
1098 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001099 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001100 }
1101
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001102 return self;
1103}
1104
Jesus Ceaef9764f2008-05-13 18:45:46 +00001105/* Forward declaration */
1106static PyObject *
1107DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001108
1109static void
1110DBTxn_dealloc(DBTxnObject* self)
1111{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001112 PyObject *dummy;
1113
1114 if (self->txn) {
1115 int flag_prepare = self->flag_prepare;
1116 dummy=DBTxn_abort_discard_internal(self,0);
1117 Py_XDECREF(dummy);
1118 if (!flag_prepare) {
1119 PyErr_Warn(PyExc_RuntimeWarning,
1120 "DBTxn aborted in destructor. No prior commit() or abort().");
1121 }
1122 }
1123
Gregory P. Smith31c50652004-06-28 01:20:40 +00001124 if (self->in_weakreflist != NULL) {
1125 PyObject_ClearWeakRefs((PyObject *) self);
1126 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127
Jesus Ceaef9764f2008-05-13 18:45:46 +00001128 if (self->env) {
1129 Py_DECREF(self->env);
1130 } else {
1131 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001132 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001134}
1135
1136
1137static DBLockObject*
1138newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1139 db_lockmode_t lock_mode, int flags)
1140{
1141 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001142 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001143 if (self == NULL)
1144 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001145 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146
1147 MYDB_BEGIN_ALLOW_THREADS;
1148#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1150 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151#else
1152 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1153#endif
1154 MYDB_END_ALLOW_THREADS;
1155 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001156 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001157 self = NULL;
1158 }
1159
1160 return self;
1161}
1162
1163
1164static void
1165DBLock_dealloc(DBLockObject* self)
1166{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001167 if (self->in_weakreflist != NULL) {
1168 PyObject_ClearWeakRefs((PyObject *) self);
1169 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001170 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173}
1174
1175
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001176#if (DBVER >= 43)
1177static DBSequenceObject*
1178newDBSequenceObject(DBObject* mydb, int flags)
1179{
1180 int err;
1181 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1182 if (self == NULL)
1183 return NULL;
1184 Py_INCREF(mydb);
1185 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001186
Jesus Ceaef9764f2008-05-13 18:45:46 +00001187 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001188 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001189
1190 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001191
1192 MYDB_BEGIN_ALLOW_THREADS;
1193 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1194 MYDB_END_ALLOW_THREADS;
1195 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001196 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001197 self = NULL;
1198 }
1199
1200 return self;
1201}
1202
Jesus Ceaef9764f2008-05-13 18:45:46 +00001203/* Forward declaration */
1204static PyObject
1205*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001206
1207static void
1208DBSequence_dealloc(DBSequenceObject* self)
1209{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001210 PyObject *dummy;
1211
1212 if (self->sequence != NULL) {
1213 dummy=DBSequence_close_internal(self,0,0);
1214 Py_XDECREF(dummy);
1215 }
1216
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001217 if (self->in_weakreflist != NULL) {
1218 PyObject_ClearWeakRefs((PyObject *) self);
1219 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001220
1221 Py_DECREF(self->mydb);
1222 PyObject_Del(self);
1223}
1224#endif
1225
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001226/* --------------------------------------------------------------------- */
1227/* DB methods */
1228
1229static PyObject*
1230DB_append(DBObject* self, PyObject* args)
1231{
1232 PyObject* txnobj = NULL;
1233 PyObject* dataobj;
1234 db_recno_t recno;
1235 DBT key, data;
1236 DB_TXN *txn = NULL;
1237
Georg Brandl96a8c392006-05-29 21:04:52 +00001238 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001239 return NULL;
1240
1241 CHECK_DB_NOT_CLOSED(self);
1242
1243 /* make a dummy key out of a recno */
1244 recno = 0;
1245 CLEAR_DBT(key);
1246 key.data = &recno;
1247 key.size = sizeof(recno);
1248 key.ulen = key.size;
1249 key.flags = DB_DBT_USERMEM;
1250
1251 if (!make_dbt(dataobj, &data)) return NULL;
1252 if (!checkTxnObj(txnobj, &txn)) return NULL;
1253
1254 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1255 return NULL;
1256
1257 return PyInt_FromLong(recno);
1258}
1259
1260
1261#if (DBVER >= 33)
1262
1263static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001264_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1265 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001266{
1267 int retval = DB_DONOTINDEX;
1268 DBObject* secondaryDB = (DBObject*)db->app_private;
1269 PyObject* callback = secondaryDB->associateCallback;
1270 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001272 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001273
1274
1275 if (callback != NULL) {
1276 MYDB_BEGIN_BLOCK_THREADS;
1277
Thomas Woutersb3153832006-03-08 01:47:19 +00001278 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001279 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001280 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001281 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001282 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001283 result = PyEval_CallObject(callback, args);
1284 }
1285 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001286 PyErr_Print();
1287 }
1288 else if (result == Py_None) {
1289 retval = DB_DONOTINDEX;
1290 }
1291 else if (PyInt_Check(result)) {
1292 retval = PyInt_AsLong(result);
1293 }
1294 else if (PyString_Check(result)) {
1295 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001296 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297
1298 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001299 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1301 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001302 if (secKey->data) {
1303 memcpy(secKey->data, data, size);
1304 secKey->size = size;
1305 retval = 0;
1306 }
1307 else {
1308 PyErr_SetString(PyExc_MemoryError,
1309 "malloc failed in _db_associateCallback");
1310 PyErr_Print();
1311 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 }
1313 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001314 PyErr_SetString(
1315 PyExc_TypeError,
1316 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001317 PyErr_Print();
1318 }
1319
Thomas Woutersb3153832006-03-08 01:47:19 +00001320 Py_XDECREF(args);
1321 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001322
1323 MYDB_END_BLOCK_THREADS;
1324 }
1325 return retval;
1326}
1327
1328
1329static PyObject*
1330DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1331{
1332 int err, flags=0;
1333 DBObject* secondaryDB;
1334 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001335#if (DBVER >= 41)
1336 PyObject *txnobj = NULL;
1337 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001338 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001339 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001340#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001341 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001344#if (DBVER >= 41)
1345 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1346 &secondaryDB, &callback, &flags,
1347 &txnobj)) {
1348#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001349 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001350 &secondaryDB, &callback, &flags)) {
1351#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001352 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001353 }
1354
1355#if (DBVER >= 41)
1356 if (!checkTxnObj(txnobj, &txn)) return NULL;
1357#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001358
1359 CHECK_DB_NOT_CLOSED(self);
1360 if (!DBObject_Check(secondaryDB)) {
1361 makeTypeError("DB", (PyObject*)secondaryDB);
1362 return NULL;
1363 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001364 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001365 if (callback == Py_None) {
1366 callback = NULL;
1367 }
1368 else if (!PyCallable_Check(callback)) {
1369 makeTypeError("Callable", callback);
1370 return NULL;
1371 }
1372
1373 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001374 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001375 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001376 secondaryDB->associateCallback = callback;
1377 secondaryDB->primaryDBType = _DB_get_type(self);
1378
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001379 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1380 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1381 * The global interepreter lock is not initialized until the first
1382 * thread is created using thread.start_new_thread() or fork() is
1383 * called. that would cause the ALLOW_THREADS here to segfault due
1384 * to a null pointer reference if no threads or child processes
1385 * have been created. This works around that and is a no-op if
1386 * threads have already been initialized.
1387 * (see pybsddb-users mailing list post on 2002-08-07)
1388 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001389#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001390 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001391#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001393#if (DBVER >= 41)
1394 err = self->db->associate(self->db,
1395 txn,
1396 secondaryDB->db,
1397 _db_associateCallback,
1398 flags);
1399#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001400 err = self->db->associate(self->db,
1401 secondaryDB->db,
1402 _db_associateCallback,
1403 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001404#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405 MYDB_END_ALLOW_THREADS;
1406
1407 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001408 Py_XDECREF(secondaryDB->associateCallback);
1409 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410 secondaryDB->primaryDBType = 0;
1411 }
1412
1413 RETURN_IF_ERR();
1414 RETURN_NONE();
1415}
1416
1417
1418#endif
1419
1420
1421static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001422DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001424 PyObject *dummy;
1425 int err;
1426
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001428 /* Can be NULL if db is not in an environment */
1429 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1430 if (self->txn) {
1431 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1432 self->txn=NULL;
1433 }
1434
1435 while(self->children_cursors) {
1436 dummy=DBC_close_internal(self->children_cursors);
1437 Py_XDECREF(dummy);
1438 }
1439
1440#if (DBVER >= 43)
1441 while(self->children_sequences) {
1442 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1443 Py_XDECREF(dummy);
1444 }
1445#endif
1446
1447 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001448 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001449 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450 self->db = NULL;
1451 RETURN_IF_ERR();
1452 }
1453 RETURN_NONE();
1454}
1455
Jesus Ceaef9764f2008-05-13 18:45:46 +00001456static PyObject*
1457DB_close(DBObject* self, PyObject* args)
1458{
1459 int flags=0;
1460 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1461 return NULL;
1462 return DB_close_internal(self,flags);
1463}
1464
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466static PyObject*
1467_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1468{
1469 int err, flags=0, type;
1470 PyObject* txnobj = NULL;
1471 PyObject* retval = NULL;
1472 DBT key, data;
1473 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001474 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001475
1476 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1477 &txnobj, &flags))
1478 return NULL;
1479
1480 CHECK_DB_NOT_CLOSED(self);
1481 type = _DB_get_type(self);
1482 if (type == -1)
1483 return NULL;
1484 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001485 PyErr_SetString(PyExc_TypeError,
1486 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
1488 }
1489 if (!checkTxnObj(txnobj, &txn))
1490 return NULL;
1491
1492 CLEAR_DBT(key);
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001495 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001496 data.flags = DB_DBT_MALLOC;
1497 key.flags = DB_DBT_MALLOC;
1498 }
1499
1500 MYDB_BEGIN_ALLOW_THREADS;
1501 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1502 MYDB_END_ALLOW_THREADS;
1503
Gregory P. Smithe9477062005-06-04 06:46:59 +00001504 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1505 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001506 err = 0;
1507 Py_INCREF(Py_None);
1508 retval = Py_None;
1509 }
1510 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001511 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 FREE_DBT(key);
1513 FREE_DBT(data);
1514 }
1515
1516 RETURN_IF_ERR();
1517 return retval;
1518}
1519
1520static PyObject*
1521DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1522{
1523 return _DB_consume(self, args, kwargs, DB_CONSUME);
1524}
1525
1526static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001527DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1528 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529{
1530 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1531}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532
1533
1534static PyObject*
1535DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1536{
1537 int err, flags=0;
1538 DBC* dbc;
1539 PyObject* txnobj = NULL;
1540 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001541 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542
1543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1544 &txnobj, &flags))
1545 return NULL;
1546 CHECK_DB_NOT_CLOSED(self);
1547 if (!checkTxnObj(txnobj, &txn))
1548 return NULL;
1549
1550 MYDB_BEGIN_ALLOW_THREADS;
1551 err = self->db->cursor(self->db, txn, &dbc, flags);
1552 MYDB_END_ALLOW_THREADS;
1553 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001554 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555}
1556
1557
1558static PyObject*
1559DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1560{
1561 PyObject* txnobj = NULL;
1562 int flags = 0;
1563 PyObject* keyobj;
1564 DBT key;
1565 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001566 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001567
1568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1569 &keyobj, &txnobj, &flags))
1570 return NULL;
1571 CHECK_DB_NOT_CLOSED(self);
1572 if (!make_key_dbt(self, keyobj, &key, NULL))
1573 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001574 if (!checkTxnObj(txnobj, &txn)) {
1575 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001576 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001577 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001578
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001579 if (-1 == _DB_delete(self, txn, &key, 0)) {
1580 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001581 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001582 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001583
1584 FREE_DBT(key);
1585 RETURN_NONE();
1586}
1587
1588
1589static PyObject*
1590DB_fd(DBObject* self, PyObject* args)
1591{
1592 int err, the_fd;
1593
1594 if (!PyArg_ParseTuple(args,":fd"))
1595 return NULL;
1596 CHECK_DB_NOT_CLOSED(self);
1597
1598 MYDB_BEGIN_ALLOW_THREADS;
1599 err = self->db->fd(self->db, &the_fd);
1600 MYDB_END_ALLOW_THREADS;
1601 RETURN_IF_ERR();
1602 return PyInt_FromLong(the_fd);
1603}
1604
1605
1606static PyObject*
1607DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1608{
1609 int err, flags=0;
1610 PyObject* txnobj = NULL;
1611 PyObject* keyobj;
1612 PyObject* dfltobj = NULL;
1613 PyObject* retval = NULL;
1614 int dlen = -1;
1615 int doff = -1;
1616 DBT key, data;
1617 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001618 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001619 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001620
1621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001622 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1623 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001624 return NULL;
1625
1626 CHECK_DB_NOT_CLOSED(self);
1627 if (!make_key_dbt(self, keyobj, &key, &flags))
1628 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001629 if (!checkTxnObj(txnobj, &txn)) {
1630 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001632 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001633
1634 CLEAR_DBT(data);
1635 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001636 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637 data.flags = DB_DBT_MALLOC;
1638 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001639 if (!add_partial_dbt(&data, dlen, doff)) {
1640 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001641 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001642 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643
1644 MYDB_BEGIN_ALLOW_THREADS;
1645 err = self->db->get(self->db, txn, &key, &data, flags);
1646 MYDB_END_ALLOW_THREADS;
1647
Gregory P. Smithe9477062005-06-04 06:46:59 +00001648 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649 err = 0;
1650 Py_INCREF(dfltobj);
1651 retval = dfltobj;
1652 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001653 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1654 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 err = 0;
1656 Py_INCREF(Py_None);
1657 retval = Py_None;
1658 }
1659 else if (!err) {
1660 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001661 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001662 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001663 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 FREE_DBT(data);
1665 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001666 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001667
1668 RETURN_IF_ERR();
1669 return retval;
1670}
1671
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001672#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001673static PyObject*
1674DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1675{
1676 int err, flags=0;
1677 PyObject* txnobj = NULL;
1678 PyObject* keyobj;
1679 PyObject* dfltobj = NULL;
1680 PyObject* retval = NULL;
1681 int dlen = -1;
1682 int doff = -1;
1683 DBT key, pkey, data;
1684 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001685 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001686 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001687
1688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1689 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1690 &doff))
1691 return NULL;
1692
1693 CHECK_DB_NOT_CLOSED(self);
1694 if (!make_key_dbt(self, keyobj, &key, &flags))
1695 return NULL;
1696 if (!checkTxnObj(txnobj, &txn)) {
1697 FREE_DBT(key);
1698 return NULL;
1699 }
1700
1701 CLEAR_DBT(data);
1702 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001703 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001704 data.flags = DB_DBT_MALLOC;
1705 }
1706 if (!add_partial_dbt(&data, dlen, doff)) {
1707 FREE_DBT(key);
1708 return NULL;
1709 }
1710
1711 CLEAR_DBT(pkey);
1712 pkey.flags = DB_DBT_MALLOC;
1713
1714 MYDB_BEGIN_ALLOW_THREADS;
1715 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1716 MYDB_END_ALLOW_THREADS;
1717
Gregory P. Smithe9477062005-06-04 06:46:59 +00001718 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001719 err = 0;
1720 Py_INCREF(dfltobj);
1721 retval = dfltobj;
1722 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001723 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1724 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001725 err = 0;
1726 Py_INCREF(Py_None);
1727 retval = Py_None;
1728 }
1729 else if (!err) {
1730 PyObject *pkeyObj;
1731 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001732 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001733
1734 if (self->primaryDBType == DB_RECNO ||
1735 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001736 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001737 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001738 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001739
1740 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1741 {
1742 PyObject *keyObj;
1743 int type = _DB_get_type(self);
1744 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001745 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001746 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001747 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001748#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001749 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001750#else
1751 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1752#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001753 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001754 }
1755 else /* return just the pkey and data */
1756 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001757#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001758 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001759#else
1760 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1761#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001762 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001763 Py_DECREF(dataObj);
1764 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001765 FREE_DBT(pkey);
1766 FREE_DBT(data);
1767 }
1768 FREE_DBT(key);
1769
1770 RETURN_IF_ERR();
1771 return retval;
1772}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001773#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001774
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001775
1776/* Return size of entry */
1777static PyObject*
1778DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1779{
1780 int err, flags=0;
1781 PyObject* txnobj = NULL;
1782 PyObject* keyobj;
1783 PyObject* retval = NULL;
1784 DBT key, data;
1785 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001786 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001787
1788 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1789 &keyobj, &txnobj))
1790 return NULL;
1791 CHECK_DB_NOT_CLOSED(self);
1792 if (!make_key_dbt(self, keyobj, &key, &flags))
1793 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001794 if (!checkTxnObj(txnobj, &txn)) {
1795 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001796 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001797 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001798 CLEAR_DBT(data);
1799
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001800 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1801 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802 data.flags = DB_DBT_USERMEM;
1803 data.ulen = 0;
1804 MYDB_BEGIN_ALLOW_THREADS;
1805 err = self->db->get(self->db, txn, &key, &data, flags);
1806 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001807 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 retval = PyInt_FromLong((long)data.size);
1809 err = 0;
1810 }
1811
1812 FREE_DBT(key);
1813 FREE_DBT(data);
1814 RETURN_IF_ERR();
1815 return retval;
1816}
1817
1818
1819static PyObject*
1820DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1821{
1822 int err, flags=0;
1823 PyObject* txnobj = NULL;
1824 PyObject* keyobj;
1825 PyObject* dataobj;
1826 PyObject* retval = NULL;
1827 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001828 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001830 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831
1832
1833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1834 &keyobj, &dataobj, &txnobj, &flags))
1835 return NULL;
1836
1837 CHECK_DB_NOT_CLOSED(self);
1838 if (!make_key_dbt(self, keyobj, &key, NULL))
1839 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001840 if ( !make_dbt(dataobj, &data) ||
1841 !checkTxnObj(txnobj, &txn) )
1842 {
1843 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001845 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846
1847 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001848 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849
1850 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001851 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001852 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 }
1855
1856 MYDB_BEGIN_ALLOW_THREADS;
1857 err = self->db->get(self->db, txn, &key, &data, flags);
1858 MYDB_END_ALLOW_THREADS;
1859
Gregory P. Smithe9477062005-06-04 06:46:59 +00001860 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1861 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001862 err = 0;
1863 Py_INCREF(Py_None);
1864 retval = Py_None;
1865 }
1866 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001867 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001868 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001869
1870 /* Even though the flags require DB_DBT_MALLOC, data is not always
1871 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1872 if (data.data != orig_data)
1873 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001874 }
1875
1876 FREE_DBT(key);
1877 RETURN_IF_ERR();
1878 return retval;
1879}
1880
1881
1882static PyObject*
1883DB_get_byteswapped(DBObject* self, PyObject* args)
1884{
1885#if (DBVER >= 33)
1886 int err = 0;
1887#endif
1888 int retval = -1;
1889
1890 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1891 return NULL;
1892 CHECK_DB_NOT_CLOSED(self);
1893
1894#if (DBVER >= 33)
1895 MYDB_BEGIN_ALLOW_THREADS;
1896 err = self->db->get_byteswapped(self->db, &retval);
1897 MYDB_END_ALLOW_THREADS;
1898 RETURN_IF_ERR();
1899#else
1900 MYDB_BEGIN_ALLOW_THREADS;
1901 retval = self->db->get_byteswapped(self->db);
1902 MYDB_END_ALLOW_THREADS;
1903#endif
1904 return PyInt_FromLong(retval);
1905}
1906
1907
1908static PyObject*
1909DB_get_type(DBObject* self, PyObject* args)
1910{
1911 int type;
1912
1913 if (!PyArg_ParseTuple(args,":get_type"))
1914 return NULL;
1915 CHECK_DB_NOT_CLOSED(self);
1916
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001918 if (type == -1)
1919 return NULL;
1920 return PyInt_FromLong(type);
1921}
1922
1923
1924static PyObject*
1925DB_join(DBObject* self, PyObject* args)
1926{
1927 int err, flags=0;
1928 int length, x;
1929 PyObject* cursorsObj;
1930 DBC** cursors;
1931 DBC* dbc;
1932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001933 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1934 return NULL;
1935
1936 CHECK_DB_NOT_CLOSED(self);
1937
1938 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001939 PyErr_SetString(PyExc_TypeError,
1940 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001941 return NULL;
1942 }
1943
1944 length = PyObject_Length(cursorsObj);
1945 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001946 if (!cursors) {
1947 PyErr_NoMemory();
1948 return NULL;
1949 }
1950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 cursors[length] = NULL;
1952 for (x=0; x<length; x++) {
1953 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001954 if (item == NULL) {
1955 free(cursors);
1956 return NULL;
1957 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959 PyErr_SetString(PyExc_TypeError,
1960 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 free(cursors);
1962 return NULL;
1963 }
1964 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001965 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001966 }
1967
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->join(self->db, cursors, &dbc, flags);
1970 MYDB_END_ALLOW_THREADS;
1971 free(cursors);
1972 RETURN_IF_ERR();
1973
Gregory P. Smith7441e652003-11-03 21:35:31 +00001974 /* FIXME: this is a buggy interface. The returned cursor
1975 contains internal references to the passed in cursors
1976 but does not hold python references to them or prevent
1977 them from being closed prematurely. This can cause
1978 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001979 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001980}
1981
1982
1983static PyObject*
1984DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1985{
1986 int err, flags=0;
1987 PyObject* txnobj = NULL;
1988 PyObject* keyobj;
1989 DBT key;
1990 DB_TXN *txn = NULL;
1991 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001992 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001993
1994 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1995 &keyobj, &txnobj, &flags))
1996 return NULL;
1997 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001998 if (!make_dbt(keyobj, &key))
1999 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000 return NULL;
2001 if (!checkTxnObj(txnobj, &txn))
2002 return NULL;
2003
2004 MYDB_BEGIN_ALLOW_THREADS;
2005 err = self->db->key_range(self->db, txn, &key, &range, flags);
2006 MYDB_END_ALLOW_THREADS;
2007
2008 RETURN_IF_ERR();
2009 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2010}
2011
2012
2013static PyObject*
2014DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2015{
2016 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2017 char* filename = NULL;
2018 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002019#if (DBVER >= 41)
2020 PyObject *txnobj = NULL;
2021 DB_TXN *txn = NULL;
2022 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002023 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002024 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2025 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002026 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002027 "filename", "dbtype", "flags", "mode", "txn", NULL};
2028#else
2029 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002030 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002031 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2032 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002033 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002034 "filename", "dbtype", "flags", "mode", NULL};
2035#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002036
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037#if (DBVER >= 41)
2038 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2039 &filename, &dbname, &type, &flags, &mode,
2040 &txnobj))
2041#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002043 &filename, &dbname, &type, &flags,
2044 &mode))
2045#endif
2046 {
2047 PyErr_Clear();
2048 type = DB_UNKNOWN; flags = 0; mode = 0660;
2049 filename = NULL; dbname = NULL;
2050#if (DBVER >= 41)
2051 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2052 kwnames_basic,
2053 &filename, &type, &flags, &mode,
2054 &txnobj))
2055 return NULL;
2056#else
2057 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2058 kwnames_basic,
2059 &filename, &type, &flags, &mode))
2060 return NULL;
2061#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002062 }
2063
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002064#if (DBVER >= 41)
2065 if (!checkTxnObj(txnobj, &txn)) return NULL;
2066#endif
2067
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002068 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002069 PyObject *t = Py_BuildValue("(is)", 0,
2070 "Cannot call open() twice for DB object");
2071 PyErr_SetObject(DBError, t);
2072 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002073 return NULL;
2074 }
2075
Jesus Ceaef9764f2008-05-13 18:45:46 +00002076#if (DBVER >= 41)
2077 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2078 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2079 self->txn=(DBTxnObject *)txnobj;
2080 } else {
2081 self->txn=NULL;
2082 }
2083#else
2084 self->txn=NULL;
2085#endif
2086
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002087 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002088#if (DBVER >= 41)
2089 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2090#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002091 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002092#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002093 MYDB_END_ALLOW_THREADS;
2094 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002095 PyObject *dummy;
2096
2097 dummy=DB_close_internal(self,0);
2098 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002099 return NULL;
2100 }
2101
Gregory P. Smithfc006692007-11-05 09:06:28 +00002102#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002103 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002104#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002105
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002106 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002107
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002108 RETURN_NONE();
2109}
2110
2111
2112static PyObject*
2113DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2114{
2115 int flags=0;
2116 PyObject* txnobj = NULL;
2117 int dlen = -1;
2118 int doff = -1;
2119 PyObject* keyobj, *dataobj, *retval;
2120 DBT key, data;
2121 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002122 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002123 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002124
2125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2126 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2127 return NULL;
2128
2129 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002130 if (!make_key_dbt(self, keyobj, &key, NULL))
2131 return NULL;
2132 if ( !make_dbt(dataobj, &data) ||
2133 !add_partial_dbt(&data, dlen, doff) ||
2134 !checkTxnObj(txnobj, &txn) )
2135 {
2136 FREE_DBT(key);
2137 return NULL;
2138 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002139
2140 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2141 FREE_DBT(key);
2142 return NULL;
2143 }
2144
2145 if (flags & DB_APPEND)
2146 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2147 else {
2148 retval = Py_None;
2149 Py_INCREF(retval);
2150 }
2151 FREE_DBT(key);
2152 return retval;
2153}
2154
2155
2156
2157static PyObject*
2158DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2159{
2160 char* filename;
2161 char* database = NULL;
2162 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002163 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002164
2165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2166 &filename, &database, &flags))
2167 return NULL;
2168 CHECK_DB_NOT_CLOSED(self);
2169
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002170 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002171 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002172 RETURN_IF_ERR();
2173 RETURN_NONE();
2174}
2175
2176
2177
2178static PyObject*
2179DB_rename(DBObject* self, PyObject* args)
2180{
2181 char* filename;
2182 char* database;
2183 char* newname;
2184 int err, flags=0;
2185
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002186 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2187 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002188 return NULL;
2189 CHECK_DB_NOT_CLOSED(self);
2190
2191 MYDB_BEGIN_ALLOW_THREADS;
2192 err = self->db->rename(self->db, filename, database, newname, flags);
2193 MYDB_END_ALLOW_THREADS;
2194 RETURN_IF_ERR();
2195 RETURN_NONE();
2196}
2197
2198
2199static PyObject*
2200DB_set_bt_minkey(DBObject* self, PyObject* args)
2201{
2202 int err, minkey;
2203
2204 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2205 return NULL;
2206 CHECK_DB_NOT_CLOSED(self);
2207
2208 MYDB_BEGIN_ALLOW_THREADS;
2209 err = self->db->set_bt_minkey(self->db, minkey);
2210 MYDB_END_ALLOW_THREADS;
2211 RETURN_IF_ERR();
2212 RETURN_NONE();
2213}
2214
Neal Norwitz84562352005-10-20 04:30:15 +00002215#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002217_default_cmp(const DBT *leftKey,
2218 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219{
2220 int res;
2221 int lsize = leftKey->size, rsize = rightKey->size;
2222
Georg Brandlef1701f2006-03-07 14:57:48 +00002223 res = memcmp(leftKey->data, rightKey->data,
2224 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002225
2226 if (res == 0) {
2227 if (lsize < rsize) {
2228 res = -1;
2229 }
2230 else if (lsize > rsize) {
2231 res = 1;
2232 }
2233 }
2234 return res;
2235}
2236
2237static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002238_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002239 const DBT *leftKey,
2240 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002241{
2242 int res = 0;
2243 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002244 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002245 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002246
2247 if (self == NULL || self->btCompareCallback == NULL) {
2248 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002249 PyErr_SetString(PyExc_TypeError,
2250 (self == 0
2251 ? "DB_bt_compare db is NULL."
2252 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002253 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002254 PyErr_Print();
2255 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002256 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002257 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002258 MYDB_BEGIN_BLOCK_THREADS;
2259
Jesus Ceaef9764f2008-05-13 18:45:46 +00002260 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002261 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002262 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002263 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002264 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002265 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002266 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002267 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002268 PyErr_Print();
2269 res = _default_cmp(leftKey, rightKey);
2270 } else if (PyInt_Check(result)) {
2271 res = PyInt_AsLong(result);
2272 } else {
2273 PyErr_SetString(PyExc_TypeError,
2274 "DB_bt_compare callback MUST return an int.");
2275 /* we're in a callback within the DB code, we can't raise */
2276 PyErr_Print();
2277 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002278 }
2279
Thomas Woutersb3153832006-03-08 01:47:19 +00002280 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002281 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002282
2283 MYDB_END_BLOCK_THREADS;
2284 }
2285 return res;
2286}
2287
2288static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002289DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002290{
2291 int err;
2292 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002293 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002294
Georg Brandlef1701f2006-03-07 14:57:48 +00002295 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002296 return NULL;
2297
Georg Brandlef1701f2006-03-07 14:57:48 +00002298 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002299
Georg Brandlef1701f2006-03-07 14:57:48 +00002300 if (!PyCallable_Check(comparator)) {
2301 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002302 return NULL;
2303 }
2304
2305 /*
2306 * Perform a test call of the comparator function with two empty
2307 * string objects here. verify that it returns an int (0).
2308 * err if not.
2309 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002310 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002311 result = PyEval_CallObject(comparator, tuple);
2312 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002313 if (result == NULL)
2314 return NULL;
2315 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002316 PyErr_SetString(PyExc_TypeError,
2317 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002318 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002319 } else if (PyInt_AsLong(result) != 0) {
2320 PyErr_SetString(PyExc_TypeError,
2321 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002322 return NULL;
2323 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002324 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002325
2326 /* We don't accept multiple set_bt_compare operations, in order to
2327 * simplify the code. This would have no real use, as one cannot
2328 * change the function once the db is opened anyway */
2329 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002330 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002331 return NULL;
2332 }
2333
Georg Brandlef1701f2006-03-07 14:57:48 +00002334 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002335 self->btCompareCallback = comparator;
2336
2337 /* This is to workaround a problem with un-initialized threads (see
2338 comment in DB_associate) */
2339#ifdef WITH_THREAD
2340 PyEval_InitThreads();
2341#endif
2342
Thomas Woutersb3153832006-03-08 01:47:19 +00002343 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002344
2345 if (err) {
2346 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002347 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002348 self->btCompareCallback = NULL;
2349 }
2350
Georg Brandlef1701f2006-03-07 14:57:48 +00002351 RETURN_IF_ERR();
2352 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002353}
Neal Norwitz84562352005-10-20 04:30:15 +00002354#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002355
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002356
2357static PyObject*
2358DB_set_cachesize(DBObject* self, PyObject* args)
2359{
2360 int err;
2361 int gbytes = 0, bytes = 0, ncache = 0;
2362
2363 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2364 &gbytes,&bytes,&ncache))
2365 return NULL;
2366 CHECK_DB_NOT_CLOSED(self);
2367
2368 MYDB_BEGIN_ALLOW_THREADS;
2369 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2370 MYDB_END_ALLOW_THREADS;
2371 RETURN_IF_ERR();
2372 RETURN_NONE();
2373}
2374
2375
2376static PyObject*
2377DB_set_flags(DBObject* self, PyObject* args)
2378{
2379 int err, flags;
2380
2381 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2382 return NULL;
2383 CHECK_DB_NOT_CLOSED(self);
2384
2385 MYDB_BEGIN_ALLOW_THREADS;
2386 err = self->db->set_flags(self->db, flags);
2387 MYDB_END_ALLOW_THREADS;
2388 RETURN_IF_ERR();
2389
2390 self->setflags |= flags;
2391 RETURN_NONE();
2392}
2393
2394
2395static PyObject*
2396DB_set_h_ffactor(DBObject* self, PyObject* args)
2397{
2398 int err, ffactor;
2399
2400 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2401 return NULL;
2402 CHECK_DB_NOT_CLOSED(self);
2403
2404 MYDB_BEGIN_ALLOW_THREADS;
2405 err = self->db->set_h_ffactor(self->db, ffactor);
2406 MYDB_END_ALLOW_THREADS;
2407 RETURN_IF_ERR();
2408 RETURN_NONE();
2409}
2410
2411
2412static PyObject*
2413DB_set_h_nelem(DBObject* self, PyObject* args)
2414{
2415 int err, nelem;
2416
2417 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2418 return NULL;
2419 CHECK_DB_NOT_CLOSED(self);
2420
2421 MYDB_BEGIN_ALLOW_THREADS;
2422 err = self->db->set_h_nelem(self->db, nelem);
2423 MYDB_END_ALLOW_THREADS;
2424 RETURN_IF_ERR();
2425 RETURN_NONE();
2426}
2427
2428
2429static PyObject*
2430DB_set_lorder(DBObject* self, PyObject* args)
2431{
2432 int err, lorder;
2433
2434 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2435 return NULL;
2436 CHECK_DB_NOT_CLOSED(self);
2437
2438 MYDB_BEGIN_ALLOW_THREADS;
2439 err = self->db->set_lorder(self->db, lorder);
2440 MYDB_END_ALLOW_THREADS;
2441 RETURN_IF_ERR();
2442 RETURN_NONE();
2443}
2444
2445
2446static PyObject*
2447DB_set_pagesize(DBObject* self, PyObject* args)
2448{
2449 int err, pagesize;
2450
2451 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2452 return NULL;
2453 CHECK_DB_NOT_CLOSED(self);
2454
2455 MYDB_BEGIN_ALLOW_THREADS;
2456 err = self->db->set_pagesize(self->db, pagesize);
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459 RETURN_NONE();
2460}
2461
2462
2463static PyObject*
2464DB_set_re_delim(DBObject* self, PyObject* args)
2465{
2466 int err;
2467 char delim;
2468
2469 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2470 PyErr_Clear();
2471 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2472 return NULL;
2473 }
2474
2475 CHECK_DB_NOT_CLOSED(self);
2476
2477 MYDB_BEGIN_ALLOW_THREADS;
2478 err = self->db->set_re_delim(self->db, delim);
2479 MYDB_END_ALLOW_THREADS;
2480 RETURN_IF_ERR();
2481 RETURN_NONE();
2482}
2483
2484static PyObject*
2485DB_set_re_len(DBObject* self, PyObject* args)
2486{
2487 int err, len;
2488
2489 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2490 return NULL;
2491 CHECK_DB_NOT_CLOSED(self);
2492
2493 MYDB_BEGIN_ALLOW_THREADS;
2494 err = self->db->set_re_len(self->db, len);
2495 MYDB_END_ALLOW_THREADS;
2496 RETURN_IF_ERR();
2497 RETURN_NONE();
2498}
2499
2500
2501static PyObject*
2502DB_set_re_pad(DBObject* self, PyObject* args)
2503{
2504 int err;
2505 char pad;
2506
2507 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2508 PyErr_Clear();
2509 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2510 return NULL;
2511 }
2512 CHECK_DB_NOT_CLOSED(self);
2513
2514 MYDB_BEGIN_ALLOW_THREADS;
2515 err = self->db->set_re_pad(self->db, pad);
2516 MYDB_END_ALLOW_THREADS;
2517 RETURN_IF_ERR();
2518 RETURN_NONE();
2519}
2520
2521
2522static PyObject*
2523DB_set_re_source(DBObject* self, PyObject* args)
2524{
2525 int err;
2526 char *re_source;
2527
2528 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2529 return NULL;
2530 CHECK_DB_NOT_CLOSED(self);
2531
2532 MYDB_BEGIN_ALLOW_THREADS;
2533 err = self->db->set_re_source(self->db, re_source);
2534 MYDB_END_ALLOW_THREADS;
2535 RETURN_IF_ERR();
2536 RETURN_NONE();
2537}
2538
2539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002540static PyObject*
2541DB_set_q_extentsize(DBObject* self, PyObject* args)
2542{
2543 int err;
2544 int extentsize;
2545
2546 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2547 return NULL;
2548 CHECK_DB_NOT_CLOSED(self);
2549
2550 MYDB_BEGIN_ALLOW_THREADS;
2551 err = self->db->set_q_extentsize(self->db, extentsize);
2552 MYDB_END_ALLOW_THREADS;
2553 RETURN_IF_ERR();
2554 RETURN_NONE();
2555}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002556
2557static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002558DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002559{
2560 int err, flags = 0, type;
2561 void* sp;
2562 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002563#if (DBVER >= 43)
2564 PyObject* txnobj = NULL;
2565 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002566 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002567#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002568 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002569#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002570
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002571#if (DBVER >= 43)
2572 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2573 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002574 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002575 if (!checkTxnObj(txnobj, &txn))
2576 return NULL;
2577#else
2578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2579 return NULL;
2580#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002581 CHECK_DB_NOT_CLOSED(self);
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002584#if (DBVER >= 43)
2585 err = self->db->stat(self->db, txn, &sp, flags);
2586#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587 err = self->db->stat(self->db, &sp, flags);
2588#else
2589 err = self->db->stat(self->db, &sp, NULL, flags);
2590#endif
2591 MYDB_END_ALLOW_THREADS;
2592 RETURN_IF_ERR();
2593
2594 self->haveStat = 1;
2595
2596 /* Turn the stat structure into a dictionary */
2597 type = _DB_get_type(self);
2598 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2599 free(sp);
2600 return NULL;
2601 }
2602
2603#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2604#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2605#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2606
2607 switch (type) {
2608 case DB_HASH:
2609 MAKE_HASH_ENTRY(magic);
2610 MAKE_HASH_ENTRY(version);
2611 MAKE_HASH_ENTRY(nkeys);
2612 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002613#if (DBVER >= 46)
2614 MAKE_HASH_ENTRY(pagecnt);
2615#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002617#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002618 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002619#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002620 MAKE_HASH_ENTRY(ffactor);
2621 MAKE_HASH_ENTRY(buckets);
2622 MAKE_HASH_ENTRY(free);
2623 MAKE_HASH_ENTRY(bfree);
2624 MAKE_HASH_ENTRY(bigpages);
2625 MAKE_HASH_ENTRY(big_bfree);
2626 MAKE_HASH_ENTRY(overflows);
2627 MAKE_HASH_ENTRY(ovfl_free);
2628 MAKE_HASH_ENTRY(dup);
2629 MAKE_HASH_ENTRY(dup_free);
2630 break;
2631
2632 case DB_BTREE:
2633 case DB_RECNO:
2634 MAKE_BT_ENTRY(magic);
2635 MAKE_BT_ENTRY(version);
2636 MAKE_BT_ENTRY(nkeys);
2637 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002638#if (DBVER >= 46)
2639 MAKE_BT_ENTRY(pagecnt);
2640#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002641 MAKE_BT_ENTRY(pagesize);
2642 MAKE_BT_ENTRY(minkey);
2643 MAKE_BT_ENTRY(re_len);
2644 MAKE_BT_ENTRY(re_pad);
2645 MAKE_BT_ENTRY(levels);
2646 MAKE_BT_ENTRY(int_pg);
2647 MAKE_BT_ENTRY(leaf_pg);
2648 MAKE_BT_ENTRY(dup_pg);
2649 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002650#if (DBVER >= 43)
2651 MAKE_BT_ENTRY(empty_pg);
2652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002653 MAKE_BT_ENTRY(free);
2654 MAKE_BT_ENTRY(int_pgfree);
2655 MAKE_BT_ENTRY(leaf_pgfree);
2656 MAKE_BT_ENTRY(dup_pgfree);
2657 MAKE_BT_ENTRY(over_pgfree);
2658 break;
2659
2660 case DB_QUEUE:
2661 MAKE_QUEUE_ENTRY(magic);
2662 MAKE_QUEUE_ENTRY(version);
2663 MAKE_QUEUE_ENTRY(nkeys);
2664 MAKE_QUEUE_ENTRY(ndata);
2665 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002666#if (DBVER > 40)
2667 MAKE_QUEUE_ENTRY(extentsize);
2668#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002669 MAKE_QUEUE_ENTRY(pages);
2670 MAKE_QUEUE_ENTRY(re_len);
2671 MAKE_QUEUE_ENTRY(re_pad);
2672 MAKE_QUEUE_ENTRY(pgfree);
2673#if (DBVER == 31)
2674 MAKE_QUEUE_ENTRY(start);
2675#endif
2676 MAKE_QUEUE_ENTRY(first_recno);
2677 MAKE_QUEUE_ENTRY(cur_recno);
2678 break;
2679
2680 default:
2681 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2682 Py_DECREF(d);
2683 d = NULL;
2684 }
2685
2686#undef MAKE_HASH_ENTRY
2687#undef MAKE_BT_ENTRY
2688#undef MAKE_QUEUE_ENTRY
2689
2690 free(sp);
2691 return d;
2692}
2693
2694static PyObject*
2695DB_sync(DBObject* self, PyObject* args)
2696{
2697 int err;
2698 int flags = 0;
2699
2700 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2701 return NULL;
2702 CHECK_DB_NOT_CLOSED(self);
2703
2704 MYDB_BEGIN_ALLOW_THREADS;
2705 err = self->db->sync(self->db, flags);
2706 MYDB_END_ALLOW_THREADS;
2707 RETURN_IF_ERR();
2708 RETURN_NONE();
2709}
2710
2711
2712#if (DBVER >= 33)
2713static PyObject*
2714DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2715{
2716 int err, flags=0;
2717 u_int32_t count=0;
2718 PyObject* txnobj = NULL;
2719 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002720 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721
2722 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2723 &txnobj, &flags))
2724 return NULL;
2725 CHECK_DB_NOT_CLOSED(self);
2726 if (!checkTxnObj(txnobj, &txn))
2727 return NULL;
2728
2729 MYDB_BEGIN_ALLOW_THREADS;
2730 err = self->db->truncate(self->db, txn, &count, flags);
2731 MYDB_END_ALLOW_THREADS;
2732 RETURN_IF_ERR();
2733 return PyInt_FromLong(count);
2734}
2735#endif
2736
2737
2738static PyObject*
2739DB_upgrade(DBObject* self, PyObject* args)
2740{
2741 int err, flags=0;
2742 char *filename;
2743
2744 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2745 return NULL;
2746 CHECK_DB_NOT_CLOSED(self);
2747
2748 MYDB_BEGIN_ALLOW_THREADS;
2749 err = self->db->upgrade(self->db, filename, flags);
2750 MYDB_END_ALLOW_THREADS;
2751 RETURN_IF_ERR();
2752 RETURN_NONE();
2753}
2754
2755
2756static PyObject*
2757DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2758{
2759 int err, flags=0;
2760 char* fileName;
2761 char* dbName=NULL;
2762 char* outFileName=NULL;
2763 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002764 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002765 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002766
2767 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2768 &fileName, &dbName, &outFileName, &flags))
2769 return NULL;
2770
2771 CHECK_DB_NOT_CLOSED(self);
2772 if (outFileName)
2773 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002774 /* XXX(nnorwitz): it should probably be an exception if outFile
2775 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002776
2777 MYDB_BEGIN_ALLOW_THREADS;
2778 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2779 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002780 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002781 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002782
Jesus Ceaef9764f2008-05-13 18:45:46 +00002783 { /* DB.verify acts as a DB handle destructor (like close) */
2784 PyObject *error;
2785
2786 error=DB_close_internal(self,0);
2787 if (error ) {
2788 return error;
2789 }
2790 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002791
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792 RETURN_IF_ERR();
2793 RETURN_NONE();
2794}
2795
2796
2797static PyObject*
2798DB_set_get_returns_none(DBObject* self, PyObject* args)
2799{
2800 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002801 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802
2803 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2804 return NULL;
2805 CHECK_DB_NOT_CLOSED(self);
2806
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002807 if (self->moduleFlags.getReturnsNone)
2808 ++oldValue;
2809 if (self->moduleFlags.cursorSetReturnsNone)
2810 ++oldValue;
2811 self->moduleFlags.getReturnsNone = (flags >= 1);
2812 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 return PyInt_FromLong(oldValue);
2814}
2815
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002816#if (DBVER >= 41)
2817static PyObject*
2818DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2819{
2820 int err;
2821 u_int32_t flags=0;
2822 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002823 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002824
2825 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2826 &passwd, &flags)) {
2827 return NULL;
2828 }
2829
2830 MYDB_BEGIN_ALLOW_THREADS;
2831 err = self->db->set_encrypt(self->db, passwd, flags);
2832 MYDB_END_ALLOW_THREADS;
2833
2834 RETURN_IF_ERR();
2835 RETURN_NONE();
2836}
2837#endif /* DBVER >= 41 */
2838
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839
2840/*-------------------------------------------------------------- */
2841/* Mapping and Dictionary-like access routines */
2842
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002843Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002844{
2845 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002846 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 int flags = 0;
2848 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002849 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850
2851 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002852 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2853 PyErr_SetObject(DBError, t);
2854 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855 return -1;
2856 }
2857
2858 if (self->haveStat) { /* Has the stat function been called recently? If
2859 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002860 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 }
2862
2863 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002864redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002865#if (DBVER >= 43)
2866 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2867#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868 err = self->db->stat(self->db, &sp, flags);
2869#else
2870 err = self->db->stat(self->db, &sp, NULL, flags);
2871#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002872
2873 /* All the stat structures have matching fields upto the ndata field,
2874 so we can use any of them for the type cast */
2875 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2876
Jesus Ceaef9764f2008-05-13 18:45:46 +00002877 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002878 * redo a full stat to make sure.
2879 * Fixes SF python bug 1493322, pybsddb bug 1184012
2880 */
2881 if (size == 0 && (flags & DB_FAST_STAT)) {
2882 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002883 if (!err)
2884 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002885 goto redo_stat_for_length;
2886 }
2887
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002888 MYDB_END_ALLOW_THREADS;
2889
2890 if (err)
2891 return -1;
2892
2893 self->haveStat = 1;
2894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002895 free(sp);
2896 return size;
2897}
2898
2899
2900PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2901{
2902 int err;
2903 PyObject* retval;
2904 DBT key;
2905 DBT data;
2906
2907 CHECK_DB_NOT_CLOSED(self);
2908 if (!make_key_dbt(self, keyobj, &key, NULL))
2909 return NULL;
2910
2911 CLEAR_DBT(data);
2912 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002913 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002914 data.flags = DB_DBT_MALLOC;
2915 }
2916 MYDB_BEGIN_ALLOW_THREADS;
2917 err = self->db->get(self->db, NULL, &key, &data, 0);
2918 MYDB_END_ALLOW_THREADS;
2919 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2920 PyErr_SetObject(PyExc_KeyError, keyobj);
2921 retval = NULL;
2922 }
2923 else if (makeDBError(err)) {
2924 retval = NULL;
2925 }
2926 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002927 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002928 FREE_DBT(data);
2929 }
2930
2931 FREE_DBT(key);
2932 return retval;
2933}
2934
2935
2936static int
2937DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2938{
2939 DBT key, data;
2940 int retval;
2941 int flags = 0;
2942
2943 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002944 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2945 PyErr_SetObject(DBError, t);
2946 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002947 return -1;
2948 }
2949
2950 if (!make_key_dbt(self, keyobj, &key, NULL))
2951 return -1;
2952
2953 if (dataobj != NULL) {
2954 if (!make_dbt(dataobj, &data))
2955 retval = -1;
2956 else {
2957 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002958 /* dictionaries shouldn't have duplicate keys */
2959 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 retval = _DB_put(self, NULL, &key, &data, flags);
2961
2962 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002963 /* try deleting any old record that matches and then PUT it
2964 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965 _DB_delete(self, NULL, &key, 0);
2966 PyErr_Clear();
2967 retval = _DB_put(self, NULL, &key, &data, flags);
2968 }
2969 }
2970 }
2971 else {
2972 /* dataobj == NULL, so delete the key */
2973 retval = _DB_delete(self, NULL, &key, 0);
2974 }
2975 FREE_DBT(key);
2976 return retval;
2977}
2978
2979
2980static PyObject*
2981DB_has_key(DBObject* self, PyObject* args)
2982{
2983 int err;
2984 PyObject* keyobj;
2985 DBT key, data;
2986 PyObject* txnobj = NULL;
2987 DB_TXN *txn = NULL;
2988
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002989 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990 return NULL;
2991 CHECK_DB_NOT_CLOSED(self);
2992 if (!make_key_dbt(self, keyobj, &key, NULL))
2993 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002994 if (!checkTxnObj(txnobj, &txn)) {
2995 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002997 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002999 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003000 it has a record but can't allocate a buffer for the data. This saves
3001 having to deal with data we won't be using.
3002 */
3003 CLEAR_DBT(data);
3004 data.flags = DB_DBT_USERMEM;
3005
3006 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003007 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003008 MYDB_END_ALLOW_THREADS;
3009 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003010
3011 if (err == DB_BUFFER_SMALL || err == 0) {
3012 return PyInt_FromLong(1);
3013 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3014 return PyInt_FromLong(0);
3015 }
3016
3017 makeDBError(err);
3018 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003019}
3020
3021
3022#define _KEYS_LIST 1
3023#define _VALUES_LIST 2
3024#define _ITEMS_LIST 3
3025
3026static PyObject*
3027_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3028{
3029 int err, dbtype;
3030 DBT key;
3031 DBT data;
3032 DBC *cursor;
3033 PyObject* list;
3034 PyObject* item = NULL;
3035
3036 CHECK_DB_NOT_CLOSED(self);
3037 CLEAR_DBT(key);
3038 CLEAR_DBT(data);
3039
3040 dbtype = _DB_get_type(self);
3041 if (dbtype == -1)
3042 return NULL;
3043
3044 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003045 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003047
3048 /* get a cursor */
3049 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003050 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003052 if (makeDBError(err)) {
3053 Py_DECREF(list);
3054 return NULL;
3055 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057 while (1) { /* use the cursor to traverse the DB, collecting items */
3058 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003059 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 MYDB_END_ALLOW_THREADS;
3061
3062 if (err) {
3063 /* for any error, break out of the loop */
3064 break;
3065 }
3066
3067 switch (type) {
3068 case _KEYS_LIST:
3069 switch(dbtype) {
3070 case DB_BTREE:
3071 case DB_HASH:
3072 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003073 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003074 break;
3075 case DB_RECNO:
3076 case DB_QUEUE:
3077 item = PyInt_FromLong(*((db_recno_t*)key.data));
3078 break;
3079 }
3080 break;
3081
3082 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003083 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003084 break;
3085
3086 case _ITEMS_LIST:
3087 switch(dbtype) {
3088 case DB_BTREE:
3089 case DB_HASH:
3090 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003091 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003092 break;
3093 case DB_RECNO:
3094 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003095 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003096 break;
3097 }
3098 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003099 default:
3100 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3101 item = NULL;
3102 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003103 }
3104 if (item == NULL) {
3105 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003106 list = NULL;
3107 goto done;
3108 }
3109 PyList_Append(list, item);
3110 Py_DECREF(item);
3111 }
3112
Gregory P. Smithe9477062005-06-04 06:46:59 +00003113 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3114 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003115 Py_DECREF(list);
3116 list = NULL;
3117 }
3118
3119 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003120 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003121 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 MYDB_END_ALLOW_THREADS;
3123 return list;
3124}
3125
3126
3127static PyObject*
3128DB_keys(DBObject* self, PyObject* args)
3129{
3130 PyObject* txnobj = NULL;
3131 DB_TXN *txn = NULL;
3132
Georg Brandl96a8c392006-05-29 21:04:52 +00003133 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003134 return NULL;
3135 if (!checkTxnObj(txnobj, &txn))
3136 return NULL;
3137 return _DB_make_list(self, txn, _KEYS_LIST);
3138}
3139
3140
3141static PyObject*
3142DB_items(DBObject* self, PyObject* args)
3143{
3144 PyObject* txnobj = NULL;
3145 DB_TXN *txn = NULL;
3146
Georg Brandl96a8c392006-05-29 21:04:52 +00003147 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003148 return NULL;
3149 if (!checkTxnObj(txnobj, &txn))
3150 return NULL;
3151 return _DB_make_list(self, txn, _ITEMS_LIST);
3152}
3153
3154
3155static PyObject*
3156DB_values(DBObject* self, PyObject* args)
3157{
3158 PyObject* txnobj = NULL;
3159 DB_TXN *txn = NULL;
3160
Georg Brandl96a8c392006-05-29 21:04:52 +00003161 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 return NULL;
3163 if (!checkTxnObj(txnobj, &txn))
3164 return NULL;
3165 return _DB_make_list(self, txn, _VALUES_LIST);
3166}
3167
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168/* --------------------------------------------------------------------- */
3169/* DBCursor methods */
3170
3171
3172static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003173DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174{
3175 int err = 0;
3176
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003178 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3179 if (self->txn) {
3180 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3181 self->txn=NULL;
3182 }
3183
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003184 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003185 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003187 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 }
3189 RETURN_IF_ERR();
3190 RETURN_NONE();
3191}
3192
Jesus Ceaef9764f2008-05-13 18:45:46 +00003193static PyObject*
3194DBC_close(DBCursorObject* self, PyObject* args)
3195{
3196 if (!PyArg_ParseTuple(args, ":close"))
3197 return NULL;
3198
3199 return DBC_close_internal(self);
3200}
3201
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003202
3203static PyObject*
3204DBC_count(DBCursorObject* self, PyObject* args)
3205{
3206 int err = 0;
3207 db_recno_t count;
3208 int flags = 0;
3209
3210 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3211 return NULL;
3212
3213 CHECK_CURSOR_NOT_CLOSED(self);
3214
3215 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003216 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003217 MYDB_END_ALLOW_THREADS;
3218 RETURN_IF_ERR();
3219
3220 return PyInt_FromLong(count);
3221}
3222
3223
3224static PyObject*
3225DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3226{
3227 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3228}
3229
3230
3231static PyObject*
3232DBC_delete(DBCursorObject* self, PyObject* args)
3233{
3234 int err, flags=0;
3235
3236 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3237 return NULL;
3238
3239 CHECK_CURSOR_NOT_CLOSED(self);
3240
3241 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003242 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003243 MYDB_END_ALLOW_THREADS;
3244 RETURN_IF_ERR();
3245
3246 self->mydb->haveStat = 0;
3247 RETURN_NONE();
3248}
3249
3250
3251static PyObject*
3252DBC_dup(DBCursorObject* self, PyObject* args)
3253{
3254 int err, flags =0;
3255 DBC* dbc = NULL;
3256
3257 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3258 return NULL;
3259
3260 CHECK_CURSOR_NOT_CLOSED(self);
3261
3262 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003263 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 MYDB_END_ALLOW_THREADS;
3265 RETURN_IF_ERR();
3266
Jesus Ceaef9764f2008-05-13 18:45:46 +00003267 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003268}
3269
3270static PyObject*
3271DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3272{
3273 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3274}
3275
3276
3277static PyObject*
3278DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3279{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003280 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003281 PyObject* keyobj = NULL;
3282 PyObject* dataobj = NULL;
3283 PyObject* retval = NULL;
3284 int dlen = -1;
3285 int doff = -1;
3286 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003287 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003288 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003289
3290 CLEAR_DBT(key);
3291 CLEAR_DBT(data);
3292 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003293 &flags, &dlen, &doff))
3294 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003295 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003296 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3297 &kwnames[1],
3298 &keyobj, &flags, &dlen, &doff))
3299 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003300 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003301 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3302 kwnames, &keyobj, &dataobj,
3303 &flags, &dlen, &doff))
3304 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305 return NULL;
3306 }
3307 }
3308 }
3309
3310 CHECK_CURSOR_NOT_CLOSED(self);
3311
3312 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3313 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003314 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3315 (!add_partial_dbt(&data, dlen, doff)) )
3316 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003317 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003318 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003319 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003320
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003321 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003322 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003323 MYDB_END_ALLOW_THREADS;
3324
Gregory P. Smithe9477062005-06-04 06:46:59 +00003325 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3326 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003327 Py_INCREF(Py_None);
3328 retval = Py_None;
3329 }
3330 else if (makeDBError(err)) {
3331 retval = NULL;
3332 }
3333 else {
3334 switch (_DB_get_type(self->mydb)) {
3335 case -1:
3336 retval = NULL;
3337 break;
3338 case DB_BTREE:
3339 case DB_HASH:
3340 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003341 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342 break;
3343 case DB_RECNO:
3344 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003345 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346 break;
3347 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003349 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003350 return retval;
3351}
3352
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003353#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003354static PyObject*
3355DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3356{
3357 int err, flags=0;
3358 PyObject* keyobj = NULL;
3359 PyObject* dataobj = NULL;
3360 PyObject* retval = NULL;
3361 int dlen = -1;
3362 int doff = -1;
3363 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003364 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3365 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003366
3367 CLEAR_DBT(key);
3368 CLEAR_DBT(data);
3369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3370 &flags, &dlen, &doff))
3371 {
3372 PyErr_Clear();
3373 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003374 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003375 &keyobj, &flags, &dlen, &doff))
3376 {
3377 PyErr_Clear();
3378 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3379 kwnames, &keyobj, &dataobj,
3380 &flags, &dlen, &doff))
3381 {
3382 return NULL;
3383 }
3384 }
3385 }
3386
3387 CHECK_CURSOR_NOT_CLOSED(self);
3388
3389 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3390 return NULL;
3391 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3392 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003393 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003394 return NULL;
3395 }
3396
Gregory P. Smith19699a92004-06-28 04:06:49 +00003397 CLEAR_DBT(pkey);
3398 pkey.flags = DB_DBT_MALLOC;
3399
3400 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003401 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003402 MYDB_END_ALLOW_THREADS;
3403
Gregory P. Smithe9477062005-06-04 06:46:59 +00003404 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3405 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003406 Py_INCREF(Py_None);
3407 retval = Py_None;
3408 }
3409 else if (makeDBError(err)) {
3410 retval = NULL;
3411 }
3412 else {
3413 PyObject *pkeyObj;
3414 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003415 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003416
3417 if (self->mydb->primaryDBType == DB_RECNO ||
3418 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003419 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003420 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003421 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003422
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003423 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003424 {
3425 PyObject *keyObj;
3426 int type = _DB_get_type(self->mydb);
3427 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003428 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003429 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003430 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003431#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003432 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003433#else
3434 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3435#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003436 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003437 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003438 }
3439 else /* return just the pkey and data */
3440 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003441#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003442 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003443#else
3444 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3445#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003446 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003447 Py_DECREF(dataObj);
3448 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003449 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003450 }
3451 /* the only time REALLOC should be set is if we used an integer
3452 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003453 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003454 FREE_DBT(key);
3455 }
3456 return retval;
3457}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003458#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461static PyObject*
3462DBC_get_recno(DBCursorObject* self, PyObject* args)
3463{
3464 int err;
3465 db_recno_t recno;
3466 DBT key;
3467 DBT data;
3468
3469 if (!PyArg_ParseTuple(args, ":get_recno"))
3470 return NULL;
3471
3472 CHECK_CURSOR_NOT_CLOSED(self);
3473
3474 CLEAR_DBT(key);
3475 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003476
3477 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003478 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 MYDB_END_ALLOW_THREADS;
3480 RETURN_IF_ERR();
3481
3482 recno = *((db_recno_t*)data.data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003483 return PyInt_FromLong(recno);
3484}
3485
3486
3487static PyObject*
3488DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3489{
3490 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3491}
3492
3493
3494static PyObject*
3495DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3496{
3497 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3498}
3499
3500
3501static PyObject*
3502DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3503{
3504 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3505}
3506
3507
3508static PyObject*
3509DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3510{
3511 int err, flags = 0;
3512 PyObject* keyobj, *dataobj;
3513 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003514 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003515 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 int dlen = -1;
3517 int doff = -1;
3518
3519 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3520 &keyobj, &dataobj, &flags, &dlen, &doff))
3521 return NULL;
3522
3523 CHECK_CURSOR_NOT_CLOSED(self);
3524
3525 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3526 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 if (!make_dbt(dataobj, &data) ||
3528 !add_partial_dbt(&data, dlen, doff) )
3529 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003530 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003532 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533
3534 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003535 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003537 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 RETURN_IF_ERR();
3539 self->mydb->haveStat = 0;
3540 RETURN_NONE();
3541}
3542
3543
3544static PyObject*
3545DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3546{
3547 int err, flags = 0;
3548 DBT key, data;
3549 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003550 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003551 int dlen = -1;
3552 int doff = -1;
3553
3554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3555 &keyobj, &flags, &dlen, &doff))
3556 return NULL;
3557
3558 CHECK_CURSOR_NOT_CLOSED(self);
3559
3560 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3561 return NULL;
3562
3563 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003564 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003565 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003567 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003568
3569 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003570 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003572 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3573 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003574 Py_INCREF(Py_None);
3575 retval = Py_None;
3576 }
3577 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578 retval = NULL;
3579 }
3580 else {
3581 switch (_DB_get_type(self->mydb)) {
3582 case -1:
3583 retval = NULL;
3584 break;
3585 case DB_BTREE:
3586 case DB_HASH:
3587 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003588 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 break;
3590 case DB_RECNO:
3591 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003592 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003593 break;
3594 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003595 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003597 /* the only time REALLOC should be set is if we used an integer
3598 * key that make_key_dbt malloc'd for us. always free these. */
3599 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003600 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003601 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602
3603 return retval;
3604}
3605
3606
3607static PyObject*
3608DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3609{
3610 int err, flags = 0;
3611 DBT key, data;
3612 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003613 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003614 int dlen = -1;
3615 int doff = -1;
3616
3617 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3618 &keyobj, &flags, &dlen, &doff))
3619 return NULL;
3620
3621 CHECK_CURSOR_NOT_CLOSED(self);
3622
3623 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3624 return NULL;
3625
3626 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003627 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003628 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003629 return NULL;
3630 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003631 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003632 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003633 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003634 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3635 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003636 Py_INCREF(Py_None);
3637 retval = Py_None;
3638 }
3639 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003640 retval = NULL;
3641 }
3642 else {
3643 switch (_DB_get_type(self->mydb)) {
3644 case -1:
3645 retval = NULL;
3646 break;
3647 case DB_BTREE:
3648 case DB_HASH:
3649 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003650 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003651 break;
3652 case DB_RECNO:
3653 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003654 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003655 break;
3656 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003657 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003658 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003659 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003660 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003661 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003662 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003663 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003664
3665 return retval;
3666}
3667
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003668static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3670 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003671{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003672 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003673 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003674 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003675
Gregory P. Smith7441e652003-11-03 21:35:31 +00003676 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3678 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003679 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003680 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003681 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003682 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683
3684 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003685 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003687 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 Py_INCREF(Py_None);
3689 retval = Py_None;
3690 }
3691 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 retval = NULL;
3693 }
3694 else {
3695 switch (_DB_get_type(self->mydb)) {
3696 case -1:
3697 retval = NULL;
3698 break;
3699 case DB_BTREE:
3700 case DB_HASH:
3701 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003702 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003703 break;
3704 case DB_RECNO:
3705 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003706 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003707 break;
3708 }
3709 }
3710
Jesus Ceaef9764f2008-05-13 18:45:46 +00003711 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 return retval;
3713}
3714
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003715static PyObject*
3716DBC_get_both(DBCursorObject* self, PyObject* args)
3717{
3718 int flags=0;
3719 PyObject *keyobj, *dataobj;
3720
3721 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3722 return NULL;
3723
Gregory P. Smith7441e652003-11-03 21:35:31 +00003724 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003725 CHECK_CURSOR_NOT_CLOSED(self);
3726
3727 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3728 self->mydb->moduleFlags.getReturnsNone);
3729}
3730
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003731/* Return size of entry */
3732static PyObject*
3733DBC_get_current_size(DBCursorObject* self, PyObject* args)
3734{
3735 int err, flags=DB_CURRENT;
3736 PyObject* retval = NULL;
3737 DBT key, data;
3738
3739 if (!PyArg_ParseTuple(args, ":get_current_size"))
3740 return NULL;
3741 CHECK_CURSOR_NOT_CLOSED(self);
3742 CLEAR_DBT(key);
3743 CLEAR_DBT(data);
3744
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003745 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003746 getting the record size. */
3747 data.flags = DB_DBT_USERMEM;
3748 data.ulen = 0;
3749 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003750 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003751 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003752 if (err == DB_BUFFER_SMALL || !err) {
3753 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003754 retval = PyInt_FromLong((long)data.size);
3755 err = 0;
3756 }
3757
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003758 RETURN_IF_ERR();
3759 return retval;
3760}
3761
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003762static PyObject*
3763DBC_set_both(DBCursorObject* self, PyObject* args)
3764{
3765 int flags=0;
3766 PyObject *keyobj, *dataobj;
3767
3768 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3769 return NULL;
3770
Gregory P. Smith7441e652003-11-03 21:35:31 +00003771 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003772 CHECK_CURSOR_NOT_CLOSED(self);
3773
3774 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3775 self->mydb->moduleFlags.cursorSetReturnsNone);
3776}
3777
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003778
3779static PyObject*
3780DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3781{
3782 int err, irecno, flags=0;
3783 db_recno_t recno;
3784 DBT key, data;
3785 PyObject* retval;
3786 int dlen = -1;
3787 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003788 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789
3790 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3791 &irecno, &flags, &dlen, &doff))
3792 return NULL;
3793
3794 CHECK_CURSOR_NOT_CLOSED(self);
3795
3796 CLEAR_DBT(key);
3797 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003798 /* use allocated space so DB will be able to realloc room for the real
3799 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 key.data = malloc(sizeof(db_recno_t));
3801 if (key.data == NULL) {
3802 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3803 return NULL;
3804 }
3805 key.size = sizeof(db_recno_t);
3806 key.ulen = key.size;
3807 memcpy(key.data, &recno, sizeof(db_recno_t));
3808 key.flags = DB_DBT_REALLOC;
3809
3810 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003811 if (!add_partial_dbt(&data, dlen, doff)) {
3812 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003814 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815
3816 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003817 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003819 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3820 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003821 Py_INCREF(Py_None);
3822 retval = Py_None;
3823 }
3824 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003825 retval = NULL;
3826 }
3827 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003828 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003829 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003830 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003831
3832 return retval;
3833}
3834
3835
3836static PyObject*
3837DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3838{
3839 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3840}
3841
3842
3843static PyObject*
3844DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3845{
3846 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3847}
3848
3849
3850static PyObject*
3851DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3852{
3853 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3854}
3855
3856
3857static PyObject*
3858DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3859{
3860 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3861}
3862
3863
3864static PyObject*
3865DBC_join_item(DBCursorObject* self, PyObject* args)
3866{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003867 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003868 DBT key, data;
3869 PyObject* retval;
3870
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003871 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003872 return NULL;
3873
3874 CHECK_CURSOR_NOT_CLOSED(self);
3875
3876 CLEAR_DBT(key);
3877 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003878
3879 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003880 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003881 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003882 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3883 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003884 Py_INCREF(Py_None);
3885 retval = Py_None;
3886 }
3887 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003888 retval = NULL;
3889 }
3890 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003891 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003892 }
3893
3894 return retval;
3895}
3896
3897
3898
3899/* --------------------------------------------------------------------- */
3900/* DBEnv methods */
3901
3902
3903static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003904DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003905{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003906 PyObject *dummy;
3907 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003908
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003909 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003910 while(self->children_txns) {
3911 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3912 Py_XDECREF(dummy);
3913 }
3914 while(self->children_dbs) {
3915 dummy=DB_close_internal(self->children_dbs,0);
3916 Py_XDECREF(dummy);
3917 }
3918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->close(self->db_env, flags);
3921 MYDB_END_ALLOW_THREADS;
3922 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003923 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003924 self->closed = 1;
3925 self->db_env = NULL;
3926 RETURN_IF_ERR();
3927 }
3928 RETURN_NONE();
3929}
3930
Jesus Ceaef9764f2008-05-13 18:45:46 +00003931static PyObject*
3932DBEnv_close(DBEnvObject* self, PyObject* args)
3933{
3934 int flags = 0;
3935
3936 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3937 return NULL;
3938 return DBEnv_close_internal(self,flags);
3939}
3940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003941
3942static PyObject*
3943DBEnv_open(DBEnvObject* self, PyObject* args)
3944{
3945 int err, flags=0, mode=0660;
3946 char *db_home;
3947
3948 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3949 return NULL;
3950
3951 CHECK_ENV_NOT_CLOSED(self);
3952
3953 MYDB_BEGIN_ALLOW_THREADS;
3954 err = self->db_env->open(self->db_env, db_home, flags, mode);
3955 MYDB_END_ALLOW_THREADS;
3956 RETURN_IF_ERR();
3957 self->closed = 0;
3958 self->flags = flags;
3959 RETURN_NONE();
3960}
3961
3962
3963static PyObject*
3964DBEnv_remove(DBEnvObject* self, PyObject* args)
3965{
3966 int err, flags=0;
3967 char *db_home;
3968
3969 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3970 return NULL;
3971 CHECK_ENV_NOT_CLOSED(self);
3972 MYDB_BEGIN_ALLOW_THREADS;
3973 err = self->db_env->remove(self->db_env, db_home, flags);
3974 MYDB_END_ALLOW_THREADS;
3975 RETURN_IF_ERR();
3976 RETURN_NONE();
3977}
3978
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003979#if (DBVER >= 41)
3980static PyObject*
3981DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3982{
3983 int err;
3984 u_int32_t flags=0;
3985 char *file = NULL;
3986 char *database = NULL;
3987 PyObject *txnobj = NULL;
3988 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003989 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003990 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003991
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003993 &file, &database, &txnobj, &flags)) {
3994 return NULL;
3995 }
3996 if (!checkTxnObj(txnobj, &txn)) {
3997 return NULL;
3998 }
3999 CHECK_ENV_NOT_CLOSED(self);
4000 MYDB_BEGIN_ALLOW_THREADS;
4001 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4002 MYDB_END_ALLOW_THREADS;
4003 RETURN_IF_ERR();
4004 RETURN_NONE();
4005}
4006
4007static PyObject*
4008DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4009{
4010 int err;
4011 u_int32_t flags=0;
4012 char *file = NULL;
4013 char *database = NULL;
4014 char *newname = NULL;
4015 PyObject *txnobj = NULL;
4016 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004017 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004018 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004019
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004020 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004021 &file, &database, &newname, &txnobj, &flags)) {
4022 return NULL;
4023 }
4024 if (!checkTxnObj(txnobj, &txn)) {
4025 return NULL;
4026 }
4027 CHECK_ENV_NOT_CLOSED(self);
4028 MYDB_BEGIN_ALLOW_THREADS;
4029 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4030 flags);
4031 MYDB_END_ALLOW_THREADS;
4032 RETURN_IF_ERR();
4033 RETURN_NONE();
4034}
4035
4036static PyObject*
4037DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4038{
4039 int err;
4040 u_int32_t flags=0;
4041 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004042 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004043
4044 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4045 &passwd, &flags)) {
4046 return NULL;
4047 }
4048
4049 MYDB_BEGIN_ALLOW_THREADS;
4050 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4051 MYDB_END_ALLOW_THREADS;
4052
4053 RETURN_IF_ERR();
4054 RETURN_NONE();
4055}
4056#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004057
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004058#if (DBVER >= 40)
4059static PyObject*
4060DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4061{
4062 int err;
4063 u_int32_t flags=0;
4064 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004065 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004066
4067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4068 &timeout, &flags)) {
4069 return NULL;
4070 }
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4074 MYDB_END_ALLOW_THREADS;
4075
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079#endif /* DBVER >= 40 */
4080
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004081static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004082DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4083{
4084 int err;
4085 long shm_key = 0;
4086
4087 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 err = self->db_env->set_shm_key(self->db_env, shm_key);
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
4095
4096static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004097DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4098{
4099 int err, gbytes=0, bytes=0, ncache=0;
4100
4101 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4102 &gbytes, &bytes, &ncache))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112
4113
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
4115DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4116{
4117 int err, flags=0, onoff=0;
4118
4119 if (!PyArg_ParseTuple(args, "ii:set_flags",
4120 &flags, &onoff))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_flags(self->db_env, flags, onoff);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004130
4131
4132static PyObject*
4133DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4134{
4135 int err;
4136 char *dir;
4137
4138 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4139 return NULL;
4140 CHECK_ENV_NOT_CLOSED(self);
4141
4142 MYDB_BEGIN_ALLOW_THREADS;
4143 err = self->db_env->set_data_dir(self->db_env, dir);
4144 MYDB_END_ALLOW_THREADS;
4145 RETURN_IF_ERR();
4146 RETURN_NONE();
4147}
4148
4149
4150static PyObject*
4151DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4152{
4153 int err, lg_bsize;
4154
4155 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4158
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4164}
4165
4166
4167static PyObject*
4168DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4169{
4170 int err;
4171 char *dir;
4172
4173 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lg_dir(self->db_env, dir);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184static PyObject*
4185DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4186{
4187 int err, lg_max;
4188
4189 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4190 return NULL;
4191 CHECK_ENV_NOT_CLOSED(self);
4192
4193 MYDB_BEGIN_ALLOW_THREADS;
4194 err = self->db_env->set_lg_max(self->db_env, lg_max);
4195 MYDB_END_ALLOW_THREADS;
4196 RETURN_IF_ERR();
4197 RETURN_NONE();
4198}
4199
Jesus Ceaef9764f2008-05-13 18:45:46 +00004200#if (DBVER >= 42)
4201static PyObject*
4202DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
4203{
4204 int err;
4205 u_int32_t lg_max;
4206
4207 if (!PyArg_ParseTuple(args, ":get_lg_max"))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4210
4211 MYDB_BEGIN_ALLOW_THREADS;
4212 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 return PyInt_FromLong(lg_max);
4216}
4217#endif
4218
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004219
Neal Norwitz84562352005-10-20 04:30:15 +00004220#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004221static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004222DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4223{
4224 int err, lg_max;
4225
4226 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4227 return NULL;
4228 CHECK_ENV_NOT_CLOSED(self);
4229
4230 MYDB_BEGIN_ALLOW_THREADS;
4231 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4232 MYDB_END_ALLOW_THREADS;
4233 RETURN_IF_ERR();
4234 RETURN_NONE();
4235}
Neal Norwitz84562352005-10-20 04:30:15 +00004236#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004237
4238
4239static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004240DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4241{
4242 int err, lk_detect;
4243
4244 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4245 return NULL;
4246 CHECK_ENV_NOT_CLOSED(self);
4247
4248 MYDB_BEGIN_ALLOW_THREADS;
4249 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4250 MYDB_END_ALLOW_THREADS;
4251 RETURN_IF_ERR();
4252 RETURN_NONE();
4253}
4254
4255
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004256#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004257static PyObject*
4258DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4259{
4260 int err, max;
4261
4262 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4263 return NULL;
4264 CHECK_ENV_NOT_CLOSED(self);
4265
4266 MYDB_BEGIN_ALLOW_THREADS;
4267 err = self->db_env->set_lk_max(self->db_env, max);
4268 MYDB_END_ALLOW_THREADS;
4269 RETURN_IF_ERR();
4270 RETURN_NONE();
4271}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004272#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004273
4274
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004275
4276static PyObject*
4277DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4278{
4279 int err, max;
4280
4281 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4282 return NULL;
4283 CHECK_ENV_NOT_CLOSED(self);
4284
4285 MYDB_BEGIN_ALLOW_THREADS;
4286 err = self->db_env->set_lk_max_locks(self->db_env, max);
4287 MYDB_END_ALLOW_THREADS;
4288 RETURN_IF_ERR();
4289 RETURN_NONE();
4290}
4291
4292
4293static PyObject*
4294DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4295{
4296 int err, max;
4297
4298 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4299 return NULL;
4300 CHECK_ENV_NOT_CLOSED(self);
4301
4302 MYDB_BEGIN_ALLOW_THREADS;
4303 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4304 MYDB_END_ALLOW_THREADS;
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307}
4308
4309
4310static PyObject*
4311DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4312{
4313 int err, max;
4314
4315 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4316 return NULL;
4317 CHECK_ENV_NOT_CLOSED(self);
4318
4319 MYDB_BEGIN_ALLOW_THREADS;
4320 err = self->db_env->set_lk_max_objects(self->db_env, max);
4321 MYDB_END_ALLOW_THREADS;
4322 RETURN_IF_ERR();
4323 RETURN_NONE();
4324}
4325
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004326
4327static PyObject*
4328DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4329{
4330 int err, mp_mmapsize;
4331
4332 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4333 return NULL;
4334 CHECK_ENV_NOT_CLOSED(self);
4335
4336 MYDB_BEGIN_ALLOW_THREADS;
4337 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4338 MYDB_END_ALLOW_THREADS;
4339 RETURN_IF_ERR();
4340 RETURN_NONE();
4341}
4342
4343
4344static PyObject*
4345DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4346{
4347 int err;
4348 char *dir;
4349
4350 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4351 return NULL;
4352 CHECK_ENV_NOT_CLOSED(self);
4353
4354 MYDB_BEGIN_ALLOW_THREADS;
4355 err = self->db_env->set_tmp_dir(self->db_env, dir);
4356 MYDB_END_ALLOW_THREADS;
4357 RETURN_IF_ERR();
4358 RETURN_NONE();
4359}
4360
4361
Jesus Ceaef9764f2008-05-13 18:45:46 +00004362#if (DBVER >= 40)
4363static PyObject*
4364DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
4365{
4366 int flags = DB_FIRST;
4367 int err, i;
4368 PyObject *list, *tuple, *gid;
4369 DBTxnObject *txn;
4370#define PREPLIST_LEN 16
4371 DB_PREPLIST preplist[PREPLIST_LEN];
4372 long retp;
4373
4374 if (!PyArg_ParseTuple(args, ":txn_recover"))
4375 return NULL;
4376
4377 CHECK_ENV_NOT_CLOSED(self);
4378
4379 list=PyList_New(0);
4380 if (!list)
4381 return NULL;
4382 while (!0) {
4383 MYDB_BEGIN_ALLOW_THREADS
4384 err=self->db_env->txn_recover(self->db_env,
4385 preplist, PREPLIST_LEN, &retp, flags);
4386#undef PREPLIST_LEN
4387 MYDB_END_ALLOW_THREADS
4388 if (err) {
4389 Py_DECREF(list);
4390 RETURN_IF_ERR();
4391 }
4392 if (!retp) break;
4393 flags=DB_NEXT; /* Prepare for next loop pass */
4394 for (i=0; i<retp; i++) {
4395 gid=PyString_FromStringAndSize((char *)(preplist[i].gid),
4396 DB_XIDDATASIZE);
4397 if (!gid) {
4398 Py_DECREF(list);
4399 return NULL;
4400 }
4401 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4402 if (!txn) {
4403 Py_DECREF(list);
4404 Py_DECREF(gid);
4405 return NULL;
4406 }
4407 txn->flag_prepare=1; /* Recover state */
4408 tuple=PyTuple_New(2);
4409 if (!tuple) {
4410 Py_DECREF(list);
4411 Py_DECREF(gid);
4412 Py_DECREF(txn);
4413 return NULL;
4414 }
4415 if (PyTuple_SetItem(tuple, 0, gid)) {
4416 Py_DECREF(list);
4417 Py_DECREF(gid);
4418 Py_DECREF(txn);
4419 Py_DECREF(tuple);
4420 return NULL;
4421 }
4422 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4423 Py_DECREF(list);
4424 Py_DECREF(txn);
4425 Py_DECREF(tuple); /* This delete the "gid" also */
4426 return NULL;
4427 }
4428 if (PyList_Append(list, tuple)) {
4429 Py_DECREF(list);
4430 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4431 return NULL;
4432 }
4433 Py_DECREF(tuple);
4434 }
4435 }
4436 return list;
4437}
4438#endif
4439
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004440static PyObject*
4441DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4442{
4443 int flags = 0;
4444 PyObject* txnobj = NULL;
4445 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004446 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004447
4448 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4449 &txnobj, &flags))
4450 return NULL;
4451
4452 if (!checkTxnObj(txnobj, &txn))
4453 return NULL;
4454 CHECK_ENV_NOT_CLOSED(self);
4455
Jesus Ceaef9764f2008-05-13 18:45:46 +00004456 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004457}
4458
4459
4460static PyObject*
4461DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4462{
4463 int err, kbyte=0, min=0, flags=0;
4464
4465 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4466 return NULL;
4467 CHECK_ENV_NOT_CLOSED(self);
4468
4469 MYDB_BEGIN_ALLOW_THREADS;
4470#if (DBVER >= 40)
4471 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4472#else
4473 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4474#endif
4475 MYDB_END_ALLOW_THREADS;
4476 RETURN_IF_ERR();
4477 RETURN_NONE();
4478}
4479
4480
4481static PyObject*
4482DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4483{
4484 int err, max;
4485
4486 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4487 return NULL;
4488 CHECK_ENV_NOT_CLOSED(self);
4489
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004490 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004491 RETURN_IF_ERR();
4492 RETURN_NONE();
4493}
4494
4495
4496static PyObject*
4497DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4498{
4499 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004500 long stamp;
4501 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004502
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004503 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004504 return NULL;
4505 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004506 timestamp = (time_t)stamp;
4507 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004508 RETURN_IF_ERR();
4509 RETURN_NONE();
4510}
4511
4512
4513static PyObject*
4514DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4515{
4516 int err, atype, flags=0;
4517 int aborted = 0;
4518
4519 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4520 return NULL;
4521 CHECK_ENV_NOT_CLOSED(self);
4522
4523 MYDB_BEGIN_ALLOW_THREADS;
4524#if (DBVER >= 40)
4525 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4526#else
4527 err = lock_detect(self->db_env, flags, atype, &aborted);
4528#endif
4529 MYDB_END_ALLOW_THREADS;
4530 RETURN_IF_ERR();
4531 return PyInt_FromLong(aborted);
4532}
4533
4534
4535static PyObject*
4536DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4537{
4538 int flags=0;
4539 int locker, lock_mode;
4540 DBT obj;
4541 PyObject* objobj;
4542
4543 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4544 return NULL;
4545
4546
4547 if (!make_dbt(objobj, &obj))
4548 return NULL;
4549
4550 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4551}
4552
4553
4554static PyObject*
4555DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4556{
4557 int err;
4558 u_int32_t theID;
4559
4560 if (!PyArg_ParseTuple(args, ":lock_id"))
4561 return NULL;
4562
4563 CHECK_ENV_NOT_CLOSED(self);
4564 MYDB_BEGIN_ALLOW_THREADS;
4565#if (DBVER >= 40)
4566 err = self->db_env->lock_id(self->db_env, &theID);
4567#else
4568 err = lock_id(self->db_env, &theID);
4569#endif
4570 MYDB_END_ALLOW_THREADS;
4571 RETURN_IF_ERR();
4572
4573 return PyInt_FromLong((long)theID);
4574}
4575
Gregory P. Smithac11e022007-11-05 02:56:31 +00004576#if (DBVER >= 40)
4577static PyObject*
4578DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4579{
4580 int err;
4581 u_int32_t theID;
4582
4583 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4584 return NULL;
4585
4586 CHECK_ENV_NOT_CLOSED(self);
4587 MYDB_BEGIN_ALLOW_THREADS;
4588 err = self->db_env->lock_id_free(self->db_env, theID);
4589 MYDB_END_ALLOW_THREADS;
4590 RETURN_IF_ERR();
4591 RETURN_NONE();
4592}
4593#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004594
4595static PyObject*
4596DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4597{
4598 int err;
4599 DBLockObject* dblockobj;
4600
4601 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4602 return NULL;
4603
4604 CHECK_ENV_NOT_CLOSED(self);
4605 MYDB_BEGIN_ALLOW_THREADS;
4606#if (DBVER >= 40)
4607 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4608#else
4609 err = lock_put(self->db_env, &dblockobj->lock);
4610#endif
4611 MYDB_END_ALLOW_THREADS;
4612 RETURN_IF_ERR();
4613 RETURN_NONE();
4614}
4615
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004616#if (DBVER >= 44)
4617static PyObject*
4618DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4619{
4620 int err;
4621 char *file;
4622 u_int32_t flags = 0;
4623 static char* kwnames[] = { "file", "flags", NULL};
4624
4625 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4626 &file, &flags))
4627 return NULL;
4628 CHECK_ENV_NOT_CLOSED(self);
4629
4630 MYDB_BEGIN_ALLOW_THREADS;
4631 err = self->db_env->lsn_reset(self->db_env, file, flags);
4632 MYDB_END_ALLOW_THREADS;
4633 RETURN_IF_ERR();
4634 RETURN_NONE();
4635}
4636#endif /* DBVER >= 4.4 */
4637
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004638#if (DBVER >= 40)
4639static PyObject*
4640DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4641{
4642 int err;
4643 DB_LOG_STAT* statp = NULL;
4644 PyObject* d = NULL;
4645 u_int32_t flags = 0;
4646
4647 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4648 return NULL;
4649 CHECK_ENV_NOT_CLOSED(self);
4650
4651 MYDB_BEGIN_ALLOW_THREADS;
4652 err = self->db_env->log_stat(self->db_env, &statp, flags);
4653 MYDB_END_ALLOW_THREADS;
4654 RETURN_IF_ERR();
4655
4656 /* Turn the stat structure into a dictionary */
4657 d = PyDict_New();
4658 if (d == NULL) {
4659 if (statp)
4660 free(statp);
4661 return NULL;
4662 }
4663
4664#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4665
4666 MAKE_ENTRY(magic);
4667 MAKE_ENTRY(version);
4668 MAKE_ENTRY(mode);
4669 MAKE_ENTRY(lg_bsize);
4670#if (DBVER >= 44)
4671 MAKE_ENTRY(lg_size);
4672 MAKE_ENTRY(record);
4673#endif
4674#if (DBVER <= 40)
4675 MAKE_ENTRY(lg_max);
4676#endif
4677 MAKE_ENTRY(w_mbytes);
4678 MAKE_ENTRY(w_bytes);
4679 MAKE_ENTRY(wc_mbytes);
4680 MAKE_ENTRY(wc_bytes);
4681 MAKE_ENTRY(wcount);
4682 MAKE_ENTRY(wcount_fill);
4683#if (DBVER >= 44)
4684 MAKE_ENTRY(rcount);
4685#endif
4686 MAKE_ENTRY(scount);
4687 MAKE_ENTRY(cur_file);
4688 MAKE_ENTRY(cur_offset);
4689 MAKE_ENTRY(disk_file);
4690 MAKE_ENTRY(disk_offset);
4691 MAKE_ENTRY(maxcommitperflush);
4692 MAKE_ENTRY(mincommitperflush);
4693 MAKE_ENTRY(regsize);
4694 MAKE_ENTRY(region_wait);
4695 MAKE_ENTRY(region_nowait);
4696
4697#undef MAKE_ENTRY
4698 free(statp);
4699 return d;
4700} /* DBEnv_log_stat */
4701#endif /* DBVER >= 4.0 for log_stat method */
4702
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004703
4704static PyObject*
4705DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4706{
4707 int err;
4708 DB_LOCK_STAT* sp;
4709 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004710 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004711
4712 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4713 return NULL;
4714 CHECK_ENV_NOT_CLOSED(self);
4715
4716 MYDB_BEGIN_ALLOW_THREADS;
4717#if (DBVER >= 40)
4718 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4719#else
4720#if (DBVER >= 33)
4721 err = lock_stat(self->db_env, &sp);
4722#else
4723 err = lock_stat(self->db_env, &sp, NULL);
4724#endif
4725#endif
4726 MYDB_END_ALLOW_THREADS;
4727 RETURN_IF_ERR();
4728
4729 /* Turn the stat structure into a dictionary */
4730 d = PyDict_New();
4731 if (d == NULL) {
4732 free(sp);
4733 return NULL;
4734 }
4735
4736#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4737
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004738#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004739 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004740#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004741#if (DBVER >=41)
4742 MAKE_ENTRY(id);
4743 MAKE_ENTRY(cur_maxid);
4744#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004745 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004746 MAKE_ENTRY(maxlocks);
4747 MAKE_ENTRY(maxlockers);
4748 MAKE_ENTRY(maxobjects);
4749 MAKE_ENTRY(nlocks);
4750 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004751 MAKE_ENTRY(nlockers);
4752 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004753 MAKE_ENTRY(nobjects);
4754 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004755 MAKE_ENTRY(nrequests);
4756 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004757#if (DBVER >= 44)
4758 MAKE_ENTRY(nupgrade);
4759 MAKE_ENTRY(ndowngrade);
4760#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004761#if (DBVER < 44)
4762 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004763 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004764#else
4765 MAKE_ENTRY(lock_nowait);
4766 MAKE_ENTRY(lock_wait);
4767#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004768 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004769#if (DBVER >= 41)
4770 MAKE_ENTRY(locktimeout);
4771 MAKE_ENTRY(txntimeout);
4772#endif
4773#if (DBVER >= 40)
4774 MAKE_ENTRY(nlocktimeouts);
4775 MAKE_ENTRY(ntxntimeouts);
4776#endif
4777#if (DBVER >= 46)
4778 MAKE_ENTRY(objs_wait);
4779 MAKE_ENTRY(objs_nowait);
4780 MAKE_ENTRY(lockers_wait);
4781 MAKE_ENTRY(lockers_nowait);
4782 MAKE_ENTRY(locks_wait);
4783 MAKE_ENTRY(locks_nowait);
4784 MAKE_ENTRY(hash_len);
4785#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004786 MAKE_ENTRY(regsize);
4787 MAKE_ENTRY(region_wait);
4788 MAKE_ENTRY(region_nowait);
4789
4790#undef MAKE_ENTRY
4791 free(sp);
4792 return d;
4793}
4794
Jesus Ceaef9764f2008-05-13 18:45:46 +00004795#if (DBVER >= 40)
4796static PyObject*
4797DBEnv_log_flush(DBEnvObject* self, PyObject* args)
4798{
4799 int err;
4800
4801 if (!PyArg_ParseTuple(args, ":log_flush"))
4802 return NULL;
4803 CHECK_ENV_NOT_CLOSED(self);
4804
4805 MYDB_BEGIN_ALLOW_THREADS
4806 err = self->db_env->log_flush(self->db_env, NULL);
4807 MYDB_END_ALLOW_THREADS
4808
4809 RETURN_IF_ERR();
4810 RETURN_NONE();
4811}
4812#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813
4814static PyObject*
4815DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4816{
4817 int flags=0;
4818 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004819 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004820 PyObject* list;
4821 PyObject* item = NULL;
4822
4823 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4824 return NULL;
4825
4826 CHECK_ENV_NOT_CLOSED(self);
4827 MYDB_BEGIN_ALLOW_THREADS;
4828#if (DBVER >= 40)
4829 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4830#elif (DBVER == 33)
4831 err = log_archive(self->db_env, &log_list, flags);
4832#else
4833 err = log_archive(self->db_env, &log_list, flags, NULL);
4834#endif
4835 MYDB_END_ALLOW_THREADS;
4836 RETURN_IF_ERR();
4837
Gregory P. Smithbad47452006-06-05 00:33:35 +00004838 list = PyList_New(0);
4839 if (list == NULL) {
4840 if (log_list)
4841 free(log_list);
4842 return NULL;
4843 }
4844
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004845 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004846 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004847 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4848 item = PyString_FromString (*log_list);
4849 if (item == NULL) {
4850 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004851 list = NULL;
4852 break;
4853 }
4854 PyList_Append(list, item);
4855 Py_DECREF(item);
4856 }
4857 free(log_list_start);
4858 }
4859 return list;
4860}
4861
4862
4863static PyObject*
4864DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4865{
4866 int err;
4867 DB_TXN_STAT* sp;
4868 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004869 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004870
4871 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4872 return NULL;
4873 CHECK_ENV_NOT_CLOSED(self);
4874
4875 MYDB_BEGIN_ALLOW_THREADS;
4876#if (DBVER >= 40)
4877 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4878#elif (DBVER == 33)
4879 err = txn_stat(self->db_env, &sp);
4880#else
4881 err = txn_stat(self->db_env, &sp, NULL);
4882#endif
4883 MYDB_END_ALLOW_THREADS;
4884 RETURN_IF_ERR();
4885
4886 /* Turn the stat structure into a dictionary */
4887 d = PyDict_New();
4888 if (d == NULL) {
4889 free(sp);
4890 return NULL;
4891 }
4892
Jesus Ceaef9764f2008-05-13 18:45:46 +00004893#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4894#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4895#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004896
Jesus Ceaef9764f2008-05-13 18:45:46 +00004897#if (DBVER >= 40)
4898 MAKE_DB_LSN_ENTRY(last_ckp);
4899#endif
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004900 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004901 MAKE_ENTRY(last_txnid);
4902 MAKE_ENTRY(maxtxns);
4903 MAKE_ENTRY(nactive);
4904 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004905#if (DBVER >= 45)
4906 MAKE_ENTRY(nsnapshot);
4907 MAKE_ENTRY(maxnsnapshot);
4908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004909 MAKE_ENTRY(nbegins);
4910 MAKE_ENTRY(naborts);
4911 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004912#if (DBVER >= 40)
4913 MAKE_ENTRY(nrestores);
4914#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004915 MAKE_ENTRY(regsize);
4916 MAKE_ENTRY(region_wait);
4917 MAKE_ENTRY(region_nowait);
4918
Jesus Ceaef9764f2008-05-13 18:45:46 +00004919#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004920#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004921#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004922 free(sp);
4923 return d;
4924}
4925
4926
4927static PyObject*
4928DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4929{
4930 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004931 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004932
4933 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4934 return NULL;
4935 CHECK_ENV_NOT_CLOSED(self);
4936
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004937 if (self->moduleFlags.getReturnsNone)
4938 ++oldValue;
4939 if (self->moduleFlags.cursorSetReturnsNone)
4940 ++oldValue;
4941 self->moduleFlags.getReturnsNone = (flags >= 1);
4942 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004943 return PyInt_FromLong(oldValue);
4944}
4945
Jesus Ceaef9764f2008-05-13 18:45:46 +00004946#if (DBVER >= 40)
4947static PyObject*
4948DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
4949{
4950 int err;
4951 int which, onoff;
4952
4953 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
4954 return NULL;
4955 }
4956 CHECK_ENV_NOT_CLOSED(self);
4957 MYDB_BEGIN_ALLOW_THREADS;
4958 err = self->db_env->set_verbose(self->db_env, which, onoff);
4959 MYDB_END_ALLOW_THREADS;
4960 RETURN_IF_ERR();
4961 RETURN_NONE();
4962}
4963
4964#if (DBVER >= 42)
4965static PyObject*
4966DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
4967{
4968 int err;
4969 int which;
4970 int verbose;
4971
4972 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
4973 return NULL;
4974 }
4975 CHECK_ENV_NOT_CLOSED(self);
4976 MYDB_BEGIN_ALLOW_THREADS;
4977 err = self->db_env->get_verbose(self->db_env, which, &verbose);
4978 MYDB_END_ALLOW_THREADS;
4979 RETURN_IF_ERR();
4980 return PyBool_FromLong(verbose);
4981}
4982#endif
4983#endif
4984
4985#if (DBVER >= 45)
4986static void
4987_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
4988{
4989 DBEnvObject *dbenv;
4990 PyObject* callback;
4991 PyObject* args;
4992 PyObject* result = NULL;
4993
4994 MYDB_BEGIN_BLOCK_THREADS;
4995 dbenv = (DBEnvObject *)db_env->app_private;
4996 callback = dbenv->event_notifyCallback;
4997 if (callback) {
4998 if (event == DB_EVENT_REP_NEWMASTER) {
4999 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5000 } else {
5001 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5002 }
5003 if (args) {
5004 result = PyEval_CallObject(callback, args);
5005 }
5006 if ((!args) || (!result)) {
5007 PyErr_Print();
5008 }
5009 Py_XDECREF(args);
5010 Py_XDECREF(result);
5011 }
5012 MYDB_END_BLOCK_THREADS;
5013}
5014#endif
5015
5016#if (DBVER >= 45)
5017static PyObject*
5018DBEnv_set_event_notify(DBEnvObject* self, PyObject* args)
5019{
5020 int err;
5021 PyObject *notifyFunc;
5022
5023 if (!PyArg_ParseTuple(args, "O:set_event_notify", &notifyFunc)) {
5024 return NULL;
5025 }
5026
5027 CHECK_ENV_NOT_CLOSED(self);
5028
5029 if (!PyCallable_Check(notifyFunc)) {
5030 makeTypeError("Callable", notifyFunc);
5031 return NULL;
5032 }
5033
5034 Py_XDECREF(self->event_notifyCallback);
5035 Py_INCREF(notifyFunc);
5036 self->event_notifyCallback = notifyFunc;
5037
5038 MYDB_BEGIN_ALLOW_THREADS;
5039 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5040 MYDB_END_ALLOW_THREADS;
5041
5042 if (err) {
5043 Py_DECREF(notifyFunc);
5044 self->event_notifyCallback = NULL;
5045 }
5046
5047 RETURN_IF_ERR();
5048 RETURN_NONE();
5049}
5050#endif
5051
5052
5053/* --------------------------------------------------------------------- */
5054/* REPLICATION METHODS: Base Replication */
5055
5056#if (DBVER >= 45)
5057static PyObject*
5058DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5059{
5060 int err;
5061 int nsites;
5062
5063 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5064 return NULL;
5065 }
5066 CHECK_ENV_NOT_CLOSED(self);
5067 MYDB_BEGIN_ALLOW_THREADS;
5068 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5069 MYDB_END_ALLOW_THREADS;
5070 RETURN_IF_ERR();
5071 RETURN_NONE();
5072}
5073
5074static PyObject*
5075DBEnv_rep_get_nsites(DBEnvObject* self, PyObject* args)
5076{
5077 int err;
5078 int nsites;
5079
5080 if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
5081 return NULL;
5082 }
5083 CHECK_ENV_NOT_CLOSED(self);
5084 MYDB_BEGIN_ALLOW_THREADS;
5085 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5086 MYDB_END_ALLOW_THREADS;
5087 RETURN_IF_ERR();
5088 return PyInt_FromLong(nsites);
5089}
5090
5091static PyObject*
5092DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5093{
5094 int err;
5095 int priority;
5096
5097 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5098 return NULL;
5099 }
5100 CHECK_ENV_NOT_CLOSED(self);
5101 MYDB_BEGIN_ALLOW_THREADS;
5102 err = self->db_env->rep_set_priority(self->db_env, priority);
5103 MYDB_END_ALLOW_THREADS;
5104 RETURN_IF_ERR();
5105 RETURN_NONE();
5106}
5107
5108static PyObject*
5109DBEnv_rep_get_priority(DBEnvObject* self, PyObject* args)
5110{
5111 int err;
5112 int priority;
5113
5114 if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
5115 return NULL;
5116 }
5117 CHECK_ENV_NOT_CLOSED(self);
5118 MYDB_BEGIN_ALLOW_THREADS;
5119 err = self->db_env->rep_get_priority(self->db_env, &priority);
5120 MYDB_END_ALLOW_THREADS;
5121 RETURN_IF_ERR();
5122 return PyInt_FromLong(priority);
5123}
5124
5125static PyObject*
5126DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5127{
5128 int err;
5129 int which, timeout;
5130
5131 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5132 return NULL;
5133 }
5134 CHECK_ENV_NOT_CLOSED(self);
5135 MYDB_BEGIN_ALLOW_THREADS;
5136 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5137 MYDB_END_ALLOW_THREADS;
5138 RETURN_IF_ERR();
5139 RETURN_NONE();
5140}
5141
5142static PyObject*
5143DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5144{
5145 int err;
5146 int which;
5147 u_int32_t timeout;
5148
5149 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5150 return NULL;
5151 }
5152 CHECK_ENV_NOT_CLOSED(self);
5153 MYDB_BEGIN_ALLOW_THREADS;
5154 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5155 MYDB_END_ALLOW_THREADS;
5156 RETURN_IF_ERR();
5157 return PyInt_FromLong(timeout);
5158}
5159#endif
5160
5161/* --------------------------------------------------------------------- */
5162/* REPLICATION METHODS: Replication Manager */
5163
5164#if (DBVER >= 45)
5165static PyObject*
5166DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5167 kwargs)
5168{
5169 int err;
5170 int nthreads, flags;
5171 static char* kwnames[] = {"nthreads","flags", NULL};
5172
5173 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5174 "ii:repmgr_start", kwnames, &nthreads, &flags))
5175 {
5176 return NULL;
5177 }
5178 CHECK_ENV_NOT_CLOSED(self);
5179 MYDB_BEGIN_ALLOW_THREADS;
5180 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5181 MYDB_END_ALLOW_THREADS;
5182 RETURN_IF_ERR();
5183 RETURN_NONE();
5184}
5185
5186static PyObject*
5187DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5188 kwargs)
5189{
5190 int err;
5191 char *host;
5192 int port;
5193 int flags = 0;
5194 static char* kwnames[] = {"host", "port", "flags", NULL};
5195
5196 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5197 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5198 {
5199 return NULL;
5200 }
5201 CHECK_ENV_NOT_CLOSED(self);
5202 MYDB_BEGIN_ALLOW_THREADS;
5203 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5204 MYDB_END_ALLOW_THREADS;
5205 RETURN_IF_ERR();
5206 RETURN_NONE();
5207}
5208
5209static PyObject*
5210DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5211 kwargs)
5212{
5213 int err;
5214 char *host;
5215 int port;
5216 int flags = 0;
5217 int eidp;
5218 static char* kwnames[] = {"host", "port", "flags", NULL};
5219
5220 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5221 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5222 {
5223 return NULL;
5224 }
5225 CHECK_ENV_NOT_CLOSED(self);
5226 MYDB_BEGIN_ALLOW_THREADS;
5227 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5228 MYDB_END_ALLOW_THREADS;
5229 RETURN_IF_ERR();
5230 return PyInt_FromLong(eidp);
5231}
5232
5233static PyObject*
5234DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5235{
5236 int err;
5237 int ack_policy;
5238
5239 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5240 {
5241 return NULL;
5242 }
5243 CHECK_ENV_NOT_CLOSED(self);
5244 MYDB_BEGIN_ALLOW_THREADS;
5245 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5246 MYDB_END_ALLOW_THREADS;
5247 RETURN_IF_ERR();
5248 RETURN_NONE();
5249}
5250
5251static PyObject*
5252DBEnv_repmgr_get_ack_policy(DBEnvObject* self, PyObject* args)
5253{
5254 int err;
5255 int ack_policy;
5256
5257 if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
5258 {
5259 return NULL;
5260 }
5261 CHECK_ENV_NOT_CLOSED(self);
5262 MYDB_BEGIN_ALLOW_THREADS;
5263 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5264 MYDB_END_ALLOW_THREADS;
5265 RETURN_IF_ERR();
5266 return PyInt_FromLong(ack_policy);
5267}
5268
5269static PyObject*
5270DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
5271{
5272 int err;
5273 unsigned int countp;
5274 DB_REPMGR_SITE *listp;
5275 PyObject *stats, *key, *tuple;
5276
5277 if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
5278 {
5279 return NULL;
5280 }
5281 CHECK_ENV_NOT_CLOSED(self);
5282 MYDB_BEGIN_ALLOW_THREADS;
5283 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5284 MYDB_END_ALLOW_THREADS;
5285 RETURN_IF_ERR();
5286
5287 stats=PyDict_New();
5288 if (stats == NULL) {
5289 free(listp);
5290 return NULL;
5291 }
5292
5293 for(;countp--;) {
5294 key=PyInt_FromLong(listp[countp].eid);
5295 if(!key) {
5296 Py_DECREF(stats);
5297 free(listp);
5298 return NULL;
5299 }
5300#if (PY_VERSION_HEX >= 0x02040000)
5301 tuple=Py_BuildValue("(sII)", listp[countp].host,
5302 listp[countp].port, listp[countp].status);
5303#else
5304 tuple=Py_BuildValue("(sii)", listp[countp].host,
5305 listp[countp].port, listp[countp].status);
5306#endif
5307 if(!tuple) {
5308 Py_DECREF(key);
5309 Py_DECREF(stats);
5310 free(listp);
5311 return NULL;
5312 }
5313 if(PyDict_SetItem(stats, key, tuple)) {
5314 Py_DECREF(key);
5315 Py_DECREF(tuple);
5316 Py_DECREF(stats);
5317 free(listp);
5318 return NULL;
5319 }
5320 }
5321 free(listp);
5322 return stats;
5323}
5324#endif
5325
5326#if (DBVER >= 46)
5327static PyObject*
5328DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5329{
5330 int err;
5331 int flags=0;
5332 static char* kwnames[] = { "flags", NULL };
5333
5334 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5335 kwnames, &flags))
5336 {
5337 return NULL;
5338 }
5339 CHECK_ENV_NOT_CLOSED(self);
5340 MYDB_BEGIN_ALLOW_THREADS;
5341 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5342 MYDB_END_ALLOW_THREADS;
5343 RETURN_IF_ERR();
5344 RETURN_NONE();
5345}
5346
5347static PyObject*
5348DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5349{
5350 int err;
5351 int flags=0;
5352 DB_REPMGR_STAT *statp;
5353 PyObject *stats;
5354 static char* kwnames[] = { "flags", NULL };
5355
5356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5357 kwnames, &flags))
5358 {
5359 return NULL;
5360 }
5361 CHECK_ENV_NOT_CLOSED(self);
5362 MYDB_BEGIN_ALLOW_THREADS;
5363 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5364 MYDB_END_ALLOW_THREADS;
5365 RETURN_IF_ERR();
5366
5367 stats=PyDict_New();
5368 if (stats == NULL) {
5369 free(statp);
5370 return NULL;
5371 }
5372
5373#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5374
5375 MAKE_ENTRY(perm_failed);
5376 MAKE_ENTRY(msgs_queued);
5377 MAKE_ENTRY(msgs_dropped);
5378 MAKE_ENTRY(connection_drop);
5379 MAKE_ENTRY(connect_fail);
5380
5381#undef MAKE_ENTRY
5382
5383 free(statp);
5384 return stats;
5385}
5386#endif
5387
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005388
5389/* --------------------------------------------------------------------- */
5390/* DBTxn methods */
5391
5392
Jesus Ceaef9764f2008-05-13 18:45:46 +00005393static void _close_transaction_cursors(DBTxnObject* txn)
5394{
5395 PyObject *dummy;
5396
5397 while(txn->children_cursors) {
5398 PyErr_Warn(PyExc_RuntimeWarning,
5399 "Must close cursors before resolving a transaction.");
5400 dummy=DBC_close_internal(txn->children_cursors);
5401 Py_XDECREF(dummy);
5402 }
5403}
5404
5405static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5406{
5407 DBObject *db;
5408#if (DBVER >= 43)
5409 DBSequenceObject *dbs;
5410#endif
5411
5412 while (txn->children_dbs) {
5413 db=txn->children_dbs;
5414 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5415 if (txn->parent_txn) {
5416 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5417 db->txn=txn->parent_txn;
5418 } else {
5419 /* The db is already linked to its environment,
5420 ** so nothing to do.
5421 */
5422 db->txn=NULL;
5423 }
5424 }
5425
5426#if (DBVER >= 43)
5427 while (txn->children_sequences) {
5428 dbs=txn->children_sequences;
5429 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5430 if (txn->parent_txn) {
5431 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5432 dbs->txn=txn->parent_txn;
5433 } else {
5434 /* The sequence is already linked to its
5435 ** parent db. Nothing to do.
5436 */
5437 dbs->txn=NULL;
5438 }
5439 }
5440#endif
5441}
5442
5443
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005444static PyObject*
5445DBTxn_commit(DBTxnObject* self, PyObject* args)
5446{
5447 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005448 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005449
5450 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5451 return NULL;
5452
Jesus Ceaef9764f2008-05-13 18:45:46 +00005453 _close_transaction_cursors(self);
5454
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005455 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005456 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005457 "after txn_commit, txn_abort "
5458 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005459 PyErr_SetObject(DBError, t);
5460 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005461 return NULL;
5462 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005463 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005464 txn = self->txn;
5465 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005466
5467 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5468
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005469 MYDB_BEGIN_ALLOW_THREADS;
5470#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005471 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005472#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005473 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005474#endif
5475 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005476
5477 _promote_transaction_dbs_and_sequences(self);
5478
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005479 RETURN_IF_ERR();
5480 RETURN_NONE();
5481}
5482
5483static PyObject*
5484DBTxn_prepare(DBTxnObject* self, PyObject* args)
5485{
5486#if (DBVER >= 33)
5487 int err;
5488 char* gid=NULL;
5489 int gid_size=0;
5490
5491 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5492 return NULL;
5493
5494 if (gid_size != DB_XIDDATASIZE) {
5495 PyErr_SetString(PyExc_TypeError,
5496 "gid must be DB_XIDDATASIZE bytes long");
5497 return NULL;
5498 }
5499
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005500 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005501 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005502 "after txn_commit, txn_abort "
5503 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005504 PyErr_SetObject(DBError, t);
5505 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005506 return NULL;
5507 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005508 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005509 MYDB_BEGIN_ALLOW_THREADS;
5510#if (DBVER >= 40)
5511 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5512#else
5513 err = txn_prepare(self->txn, (u_int8_t*)gid);
5514#endif
5515 MYDB_END_ALLOW_THREADS;
5516 RETURN_IF_ERR();
5517 RETURN_NONE();
5518#else
5519 int err;
5520
5521 if (!PyArg_ParseTuple(args, ":prepare"))
5522 return NULL;
5523
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005524 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005525 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005526 "after txn_commit, txn_abort "
5527 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005528 PyErr_SetObject(DBError, t);
5529 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005530 return NULL;
5531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005532 MYDB_BEGIN_ALLOW_THREADS;
5533 err = txn_prepare(self->txn);
5534 MYDB_END_ALLOW_THREADS;
5535 RETURN_IF_ERR();
5536 RETURN_NONE();
5537#endif
5538}
5539
5540
5541static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005542DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005543{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005544 PyObject *dummy;
5545 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005546 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005547
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005548 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005549 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005550 "after txn_commit, txn_abort "
5551 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005552 PyErr_SetObject(DBError, t);
5553 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005554 return NULL;
5555 }
5556 txn = self->txn;
5557 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005558
5559 _close_transaction_cursors(self);
5560#if (DBVER >= 43)
5561 while (self->children_sequences) {
5562 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5563 Py_XDECREF(dummy);
5564 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005565#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005566 while (self->children_dbs) {
5567 dummy=DB_close_internal(self->children_dbs,0);
5568 Py_XDECREF(dummy);
5569 }
5570
5571 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5572
5573 MYDB_BEGIN_ALLOW_THREADS;
5574 if (discard) {
5575 assert(!self->flag_prepare);
5576#if (DBVER >= 40)
5577 err = txn->discard(txn,0);
5578#else
5579 err = txn_discard(txn);
5580#endif
5581 } else {
5582 /*
5583 ** If the transaction is in the "prepare" or "recover" state,
5584 ** we better do not implicitly abort it.
5585 */
5586 if (!self->flag_prepare) {
5587#if (DBVER >= 40)
5588 err = txn->abort(txn);
5589#else
5590 err = txn_abort(txn);
5591#endif
5592 }
5593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005594 MYDB_END_ALLOW_THREADS;
5595 RETURN_IF_ERR();
5596 RETURN_NONE();
5597}
5598
Jesus Ceaef9764f2008-05-13 18:45:46 +00005599static PyObject*
5600DBTxn_abort(DBTxnObject* self, PyObject* args)
5601{
5602 if (!PyArg_ParseTuple(args, ":abort"))
5603 return NULL;
5604
5605 self->flag_prepare=0;
5606 _close_transaction_cursors(self);
5607
5608 return DBTxn_abort_discard_internal(self,0);
5609}
5610
5611static PyObject*
5612DBTxn_discard(DBTxnObject* self, PyObject* args)
5613{
5614 if (!PyArg_ParseTuple(args, ":discard"))
5615 return NULL;
5616
5617 self->flag_prepare=0;
5618 _close_transaction_cursors(self);
5619
5620 return DBTxn_abort_discard_internal(self,1);
5621}
5622
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005623
5624static PyObject*
5625DBTxn_id(DBTxnObject* self, PyObject* args)
5626{
5627 int id;
5628
5629 if (!PyArg_ParseTuple(args, ":id"))
5630 return NULL;
5631
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005632 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005633 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005634 "after txn_commit, txn_abort "
5635 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005636 PyErr_SetObject(DBError, t);
5637 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005638 return NULL;
5639 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005640 MYDB_BEGIN_ALLOW_THREADS;
5641#if (DBVER >= 40)
5642 id = self->txn->id(self->txn);
5643#else
5644 id = txn_id(self->txn);
5645#endif
5646 MYDB_END_ALLOW_THREADS;
5647 return PyInt_FromLong(id);
5648}
5649
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005650#if (DBVER >= 43)
5651/* --------------------------------------------------------------------- */
5652/* DBSequence methods */
5653
5654
5655static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005656DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005657{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005658 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005659
Jesus Ceaef9764f2008-05-13 18:45:46 +00005660 if (self->sequence!=NULL) {
5661 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5662 if (self->txn) {
5663 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5664 self->txn=NULL;
5665 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005666
Jesus Ceaef9764f2008-05-13 18:45:46 +00005667 if (!do_not_close) {
5668 MYDB_BEGIN_ALLOW_THREADS
5669 err = self->sequence->close(self->sequence, flags);
5670 MYDB_END_ALLOW_THREADS
5671 }
5672 self->sequence = NULL;
5673
5674 RETURN_IF_ERR();
5675 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005676
5677 RETURN_NONE();
5678}
5679
5680static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005681DBSequence_close(DBSequenceObject* self, PyObject* args)
5682{
5683 int flags=0;
5684 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5685 return NULL;
5686
5687 return DBSequence_close_internal(self,flags,0);
5688}
5689
5690static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005691DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5692{
5693 int err, flags = 0;
5694 int delta = 1;
5695 db_seq_t value;
5696 PyObject *txnobj = NULL;
5697 DB_TXN *txn = NULL;
5698 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5700 return NULL;
5701 CHECK_SEQUENCE_NOT_CLOSED(self)
5702
5703 if (!checkTxnObj(txnobj, &txn))
5704 return NULL;
5705
5706 MYDB_BEGIN_ALLOW_THREADS
5707 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5708 MYDB_END_ALLOW_THREADS
5709
5710 RETURN_IF_ERR();
5711 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005712}
5713
5714static PyObject*
5715DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5716{
5717 if (!PyArg_ParseTuple(args,":get_dbp"))
5718 return NULL;
5719 CHECK_SEQUENCE_NOT_CLOSED(self)
5720 Py_INCREF(self->mydb);
5721 return (PyObject* )self->mydb;
5722}
5723
5724static PyObject*
5725DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5726{
5727 int err;
5728 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00005729 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005730
5731 if (!PyArg_ParseTuple(args,":get_key"))
5732 return NULL;
5733
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005734 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005735 CHECK_SEQUENCE_NOT_CLOSED(self)
5736 MYDB_BEGIN_ALLOW_THREADS
5737 err = self->sequence->get_key(self->sequence, &key);
5738 MYDB_END_ALLOW_THREADS
5739
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005740 if (!err)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005741 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005742
5743 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005744 RETURN_IF_ERR();
5745
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005746 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005747}
5748
5749static PyObject*
5750DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5751{
5752 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005753 PY_LONG_LONG value;
5754 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005755 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005756 return NULL;
5757 CHECK_SEQUENCE_NOT_CLOSED(self)
5758
Jesus Ceaef9764f2008-05-13 18:45:46 +00005759 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005760 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005761 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005762 MYDB_END_ALLOW_THREADS
5763
5764 RETURN_IF_ERR();
5765
5766 RETURN_NONE();
5767}
5768
5769static PyObject*
5770DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5771{
5772 int err, flags = 0;
5773 PyObject* keyobj;
5774 PyObject *txnobj = NULL;
5775 DB_TXN *txn = NULL;
5776 DBT key;
5777
5778 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005779 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005780 return NULL;
5781
5782 if (!checkTxnObj(txnobj, &txn))
5783 return NULL;
5784
5785 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
5786 return NULL;
5787
5788 MYDB_BEGIN_ALLOW_THREADS
5789 err = self->sequence->open(self->sequence, txn, &key, flags);
5790 MYDB_END_ALLOW_THREADS
5791
5792 CLEAR_DBT(key);
5793 RETURN_IF_ERR();
5794
Jesus Ceaef9764f2008-05-13 18:45:46 +00005795 if (txn) {
5796 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
5797 self->txn=(DBTxnObject *)txnobj;
5798 }
5799
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005800 RETURN_NONE();
5801}
5802
5803static PyObject*
5804DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5805{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005806 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005807 int err, flags = 0;
5808 PyObject *txnobj = NULL;
5809 DB_TXN *txn = NULL;
5810
5811 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005812 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005813 return NULL;
5814
5815 if (!checkTxnObj(txnobj, &txn))
5816 return NULL;
5817
5818 CHECK_SEQUENCE_NOT_CLOSED(self)
5819
5820 MYDB_BEGIN_ALLOW_THREADS
5821 err = self->sequence->remove(self->sequence, txn, flags);
5822 MYDB_END_ALLOW_THREADS
5823
Jesus Ceaef9764f2008-05-13 18:45:46 +00005824 dummy=DBSequence_close_internal(self,flags,1);
5825 Py_XDECREF(dummy);
5826
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005827 RETURN_IF_ERR();
5828 RETURN_NONE();
5829}
5830
5831static PyObject*
5832DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5833{
5834 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005835 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005836 return NULL;
5837 CHECK_SEQUENCE_NOT_CLOSED(self)
5838
5839 MYDB_BEGIN_ALLOW_THREADS
5840 err = self->sequence->set_cachesize(self->sequence, size);
5841 MYDB_END_ALLOW_THREADS
5842
5843 RETURN_IF_ERR();
5844 RETURN_NONE();
5845}
5846
5847static PyObject*
5848DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5849{
5850 int err, size;
5851 if (!PyArg_ParseTuple(args,":get_cachesize"))
5852 return NULL;
5853 CHECK_SEQUENCE_NOT_CLOSED(self)
5854
5855 MYDB_BEGIN_ALLOW_THREADS
5856 err = self->sequence->get_cachesize(self->sequence, &size);
5857 MYDB_END_ALLOW_THREADS
5858
5859 RETURN_IF_ERR();
5860 return PyInt_FromLong(size);
5861}
5862
5863static PyObject*
5864DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5865{
5866 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005867 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005868 return NULL;
5869 CHECK_SEQUENCE_NOT_CLOSED(self)
5870
5871 MYDB_BEGIN_ALLOW_THREADS
5872 err = self->sequence->set_flags(self->sequence, flags);
5873 MYDB_END_ALLOW_THREADS
5874
5875 RETURN_IF_ERR();
5876 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005877}
5878
5879static PyObject*
5880DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5881{
5882 unsigned int flags;
5883 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005884 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005885 return NULL;
5886 CHECK_SEQUENCE_NOT_CLOSED(self)
5887
5888 MYDB_BEGIN_ALLOW_THREADS
5889 err = self->sequence->get_flags(self->sequence, &flags);
5890 MYDB_END_ALLOW_THREADS
5891
5892 RETURN_IF_ERR();
5893 return PyInt_FromLong((int)flags);
5894}
5895
5896static PyObject*
5897DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5898{
5899 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005900 PY_LONG_LONG min, max;
5901 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005902 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005903 return NULL;
5904 CHECK_SEQUENCE_NOT_CLOSED(self)
5905
Jesus Ceaef9764f2008-05-13 18:45:46 +00005906 min2=min; /* If truncation, compiler should show a warning */
5907 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005908 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005909 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005910 MYDB_END_ALLOW_THREADS
5911
5912 RETURN_IF_ERR();
5913 RETURN_NONE();
5914}
5915
5916static PyObject*
5917DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5918{
5919 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005920 PY_LONG_LONG min, max;
5921 db_seq_t min2, max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005922 if (!PyArg_ParseTuple(args,":get_range"))
5923 return NULL;
5924 CHECK_SEQUENCE_NOT_CLOSED(self)
5925
5926 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005927 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005928 MYDB_END_ALLOW_THREADS
5929
5930 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00005931 min=min2; /* If truncation, compiler should show a warning */
5932 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005933 return Py_BuildValue("(LL)", min, max);
5934}
5935
5936static PyObject*
5937DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5938{
5939 int err, flags = 0;
5940 DB_SEQUENCE_STAT* sp = NULL;
5941 PyObject* dict_stat;
5942 static char* kwnames[] = {"flags", NULL };
5943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5944 return NULL;
5945 CHECK_SEQUENCE_NOT_CLOSED(self);
5946
5947 MYDB_BEGIN_ALLOW_THREADS;
5948 err = self->sequence->stat(self->sequence, &sp, flags);
5949 MYDB_END_ALLOW_THREADS;
5950 RETURN_IF_ERR();
5951
5952 if ((dict_stat = PyDict_New()) == NULL) {
5953 free(sp);
5954 return NULL;
5955 }
5956
5957
5958#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5959#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5960
5961 MAKE_INT_ENTRY(wait);
5962 MAKE_INT_ENTRY(nowait);
5963 MAKE_LONG_LONG_ENTRY(current);
5964 MAKE_LONG_LONG_ENTRY(value);
5965 MAKE_LONG_LONG_ENTRY(last_value);
5966 MAKE_LONG_LONG_ENTRY(min);
5967 MAKE_LONG_LONG_ENTRY(max);
5968 MAKE_INT_ENTRY(cache_size);
5969 MAKE_INT_ENTRY(flags);
5970
5971#undef MAKE_INT_ENTRY
5972#undef MAKE_LONG_LONG_ENTRY
5973
5974 free(sp);
5975 return dict_stat;
5976}
5977#endif
5978
5979
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005980/* --------------------------------------------------------------------- */
5981/* Method definition tables and type objects */
5982
5983static PyMethodDef DB_methods[] = {
5984 {"append", (PyCFunction)DB_append, METH_VARARGS},
5985#if (DBVER >= 33)
5986 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5987#endif
5988 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005989 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5990 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005991 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5992 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5993 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5994 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005995#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005996 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005997#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005998 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5999 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
6000 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6001 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
6002 {"join", (PyCFunction)DB_join, METH_VARARGS},
6003 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6004 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6005 {"items", (PyCFunction)DB_items, METH_VARARGS},
6006 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6007 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6008 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6009 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6010 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6011 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006012#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00006013 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006014#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006015 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006016#if (DBVER >= 41)
6017 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6018#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006019 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6020 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6021 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6022 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6023 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6024 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6025 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6026 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6027 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006028 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006029 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006030 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6031#if (DBVER >= 33)
6032 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6033#endif
6034 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
6035 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6036 {"values", (PyCFunction)DB_values, METH_VARARGS},
6037 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6038 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6039 {NULL, NULL} /* sentinel */
6040};
6041
6042
6043static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006044 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006045 (binaryfunc)DB_subscript, /*mp_subscript*/
6046 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6047};
6048
6049
6050static PyMethodDef DBCursor_methods[] = {
6051 {"close", (PyCFunction)DBC_close, METH_VARARGS},
6052 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6053 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6054 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6055 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6056 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6057 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006058#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006059 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006060#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006061 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
6062 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6063 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6064 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6065 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6066 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6067 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6068 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00006069 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006070 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006071 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6072 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6073 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6074 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6075 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6076 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6077 {NULL, NULL} /* sentinel */
6078};
6079
6080
6081static PyMethodDef DBEnv_methods[] = {
6082 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6083 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6084 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006085#if (DBVER >= 41)
6086 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6087 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6088 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6089#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006090#if (DBVER >= 40)
6091 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6092#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006093 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006094 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6095 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006096 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006097 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6098 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6099 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006100#if (DBVER >= 42)
6101 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
6102#endif
Neal Norwitz84562352005-10-20 04:30:15 +00006103#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00006104 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006105#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006106 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006107#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006108 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006109#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006110 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6111 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6112 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006113 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6114 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6115 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6116 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6117 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6118 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006119 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006120 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6121 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6122 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006123#if (DBVER >= 40)
6124 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006126 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6127 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6128 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006129#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006130 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_VARARGS},
6131#endif
6132#if (DBVER >= 40)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006133 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6134#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006135#if (DBVER >= 44)
6136 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6137#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006138 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006139#if (DBVER >= 40)
6140 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
6141#endif
6142#if (DBVER >= 40)
6143 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6144#if (DBVER >= 42)
6145 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6146#endif
6147#endif
6148#if (DBVER >= 45)
6149 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
6150#endif
6151#if (DBVER >= 45)
6152 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6153 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
6154 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6155 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
6156 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6157 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6158#endif
6159#if (DBVER >= 45)
6160 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6161 METH_VARARGS|METH_KEYWORDS},
6162 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6163 METH_VARARGS|METH_KEYWORDS},
6164 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6165 METH_VARARGS|METH_KEYWORDS},
6166 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6167 METH_VARARGS},
6168 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6169 METH_VARARGS},
6170 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6171 METH_VARARGS},
6172#endif
6173#if (DBVER >= 46)
6174 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6175 METH_VARARGS|METH_KEYWORDS},
6176 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6177 METH_VARARGS|METH_KEYWORDS},
6178#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006179 {NULL, NULL} /* sentinel */
6180};
6181
6182
6183static PyMethodDef DBTxn_methods[] = {
6184 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6185 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006186 {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006187 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
6188 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
6189 {NULL, NULL} /* sentinel */
6190};
6191
6192
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006193#if (DBVER >= 43)
6194static PyMethodDef DBSequence_methods[] = {
6195 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6196 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6197 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
6198 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006199 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6200 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6201 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6202 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6203 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
6204 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6205 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
6206 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6207 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
6208 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6209 {NULL, NULL} /* sentinel */
6210};
6211#endif
6212
6213
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006214static PyObject*
6215DB_getattr(DBObject* self, char *name)
6216{
6217 return Py_FindMethod(DB_methods, (PyObject* )self, name);
6218}
6219
6220
6221static PyObject*
6222DBEnv_getattr(DBEnvObject* self, char *name)
6223{
6224 if (!strcmp(name, "db_home")) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006225 const char *home = NULL;
6226 CHECK_ENV_NOT_CLOSED(self);
6227#if (DBVER >= 42)
6228 self->db_env->get_home(self->db_env, &home);
6229#else
6230 home=self->db_env->db_home;
6231#endif
6232 if (home == NULL) {
6233 RETURN_NONE();
6234 }
6235 return PyString_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006236 }
6237
6238 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
6239}
6240
6241
6242static PyObject*
6243DBCursor_getattr(DBCursorObject* self, char *name)
6244{
6245 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
6246}
6247
6248static PyObject*
6249DBTxn_getattr(DBTxnObject* self, char *name)
6250{
6251 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
6252}
6253
6254static PyObject*
6255DBLock_getattr(DBLockObject* self, char *name)
6256{
6257 return NULL;
6258}
6259
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006260#if (DBVER >= 43)
6261static PyObject*
6262DBSequence_getattr(DBSequenceObject* self, char *name)
6263{
6264 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
6265}
6266#endif
6267
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006268statichere PyTypeObject DB_Type = {
6269 PyObject_HEAD_INIT(NULL)
6270 0, /*ob_size*/
6271 "DB", /*tp_name*/
6272 sizeof(DBObject), /*tp_basicsize*/
6273 0, /*tp_itemsize*/
6274 /* methods */
6275 (destructor)DB_dealloc, /*tp_dealloc*/
6276 0, /*tp_print*/
6277 (getattrfunc)DB_getattr, /*tp_getattr*/
6278 0, /*tp_setattr*/
6279 0, /*tp_compare*/
6280 0, /*tp_repr*/
6281 0, /*tp_as_number*/
6282 0, /*tp_as_sequence*/
6283 &DB_mapping,/*tp_as_mapping*/
6284 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006285 0, /* tp_call */
6286 0, /* tp_str */
6287 0, /* tp_getattro */
6288 0, /* tp_setattro */
6289 0, /* tp_as_buffer */
6290 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6291 0, /* tp_doc */
6292 0, /* tp_traverse */
6293 0, /* tp_clear */
6294 0, /* tp_richcompare */
6295 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006296};
6297
6298
6299statichere PyTypeObject DBCursor_Type = {
6300 PyObject_HEAD_INIT(NULL)
6301 0, /*ob_size*/
6302 "DBCursor", /*tp_name*/
6303 sizeof(DBCursorObject), /*tp_basicsize*/
6304 0, /*tp_itemsize*/
6305 /* methods */
6306 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6307 0, /*tp_print*/
6308 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
6309 0, /*tp_setattr*/
6310 0, /*tp_compare*/
6311 0, /*tp_repr*/
6312 0, /*tp_as_number*/
6313 0, /*tp_as_sequence*/
6314 0, /*tp_as_mapping*/
6315 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00006316 0, /* tp_call */
6317 0, /* tp_str */
6318 0, /* tp_getattro */
6319 0, /* tp_setattro */
6320 0, /* tp_as_buffer */
6321 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6322 0, /* tp_doc */
6323 0, /* tp_traverse */
6324 0, /* tp_clear */
6325 0, /* tp_richcompare */
6326 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006327};
6328
6329
6330statichere PyTypeObject DBEnv_Type = {
6331 PyObject_HEAD_INIT(NULL)
6332 0, /*ob_size*/
6333 "DBEnv", /*tp_name*/
6334 sizeof(DBEnvObject), /*tp_basicsize*/
6335 0, /*tp_itemsize*/
6336 /* methods */
6337 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6338 0, /*tp_print*/
6339 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
6340 0, /*tp_setattr*/
6341 0, /*tp_compare*/
6342 0, /*tp_repr*/
6343 0, /*tp_as_number*/
6344 0, /*tp_as_sequence*/
6345 0, /*tp_as_mapping*/
6346 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006347 0, /* tp_call */
6348 0, /* tp_str */
6349 0, /* tp_getattro */
6350 0, /* tp_setattro */
6351 0, /* tp_as_buffer */
6352 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6353 0, /* tp_doc */
6354 0, /* tp_traverse */
6355 0, /* tp_clear */
6356 0, /* tp_richcompare */
6357 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006358};
6359
6360statichere PyTypeObject DBTxn_Type = {
6361 PyObject_HEAD_INIT(NULL)
6362 0, /*ob_size*/
6363 "DBTxn", /*tp_name*/
6364 sizeof(DBTxnObject), /*tp_basicsize*/
6365 0, /*tp_itemsize*/
6366 /* methods */
6367 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6368 0, /*tp_print*/
6369 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
6370 0, /*tp_setattr*/
6371 0, /*tp_compare*/
6372 0, /*tp_repr*/
6373 0, /*tp_as_number*/
6374 0, /*tp_as_sequence*/
6375 0, /*tp_as_mapping*/
6376 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006377 0, /* tp_call */
6378 0, /* tp_str */
6379 0, /* tp_getattro */
6380 0, /* tp_setattro */
6381 0, /* tp_as_buffer */
6382 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6383 0, /* tp_doc */
6384 0, /* tp_traverse */
6385 0, /* tp_clear */
6386 0, /* tp_richcompare */
6387 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006388};
6389
6390
6391statichere PyTypeObject DBLock_Type = {
6392 PyObject_HEAD_INIT(NULL)
6393 0, /*ob_size*/
6394 "DBLock", /*tp_name*/
6395 sizeof(DBLockObject), /*tp_basicsize*/
6396 0, /*tp_itemsize*/
6397 /* methods */
6398 (destructor)DBLock_dealloc, /*tp_dealloc*/
6399 0, /*tp_print*/
6400 (getattrfunc)DBLock_getattr, /*tp_getattr*/
6401 0, /*tp_setattr*/
6402 0, /*tp_compare*/
6403 0, /*tp_repr*/
6404 0, /*tp_as_number*/
6405 0, /*tp_as_sequence*/
6406 0, /*tp_as_mapping*/
6407 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006408 0, /* tp_call */
6409 0, /* tp_str */
6410 0, /* tp_getattro */
6411 0, /* tp_setattro */
6412 0, /* tp_as_buffer */
6413 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6414 0, /* tp_doc */
6415 0, /* tp_traverse */
6416 0, /* tp_clear */
6417 0, /* tp_richcompare */
6418 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006419};
6420
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006421#if (DBVER >= 43)
6422statichere PyTypeObject DBSequence_Type = {
6423 PyObject_HEAD_INIT(NULL)
6424 0, /*ob_size*/
6425 "DBSequence", /*tp_name*/
6426 sizeof(DBSequenceObject), /*tp_basicsize*/
6427 0, /*tp_itemsize*/
6428 /* methods */
6429 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6430 0, /*tp_print*/
6431 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
6432 0, /*tp_setattr*/
6433 0, /*tp_compare*/
6434 0, /*tp_repr*/
6435 0, /*tp_as_number*/
6436 0, /*tp_as_sequence*/
6437 0, /*tp_as_mapping*/
6438 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006439 0, /* tp_call */
6440 0, /* tp_str */
6441 0, /* tp_getattro */
6442 0, /* tp_setattro */
6443 0, /* tp_as_buffer */
6444 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6445 0, /* tp_doc */
6446 0, /* tp_traverse */
6447 0, /* tp_clear */
6448 0, /* tp_richcompare */
6449 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006450};
6451#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006452
6453/* --------------------------------------------------------------------- */
6454/* Module-level functions */
6455
6456static PyObject*
6457DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6458{
6459 PyObject* dbenvobj = NULL;
6460 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006461 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006462
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006463 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6464 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006465 return NULL;
6466 if (dbenvobj == Py_None)
6467 dbenvobj = NULL;
6468 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6469 makeTypeError("DBEnv", dbenvobj);
6470 return NULL;
6471 }
6472
6473 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6474}
6475
6476
6477static PyObject*
6478DBEnv_construct(PyObject* self, PyObject* args)
6479{
6480 int flags = 0;
6481 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6482 return (PyObject* )newDBEnvObject(flags);
6483}
6484
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006485#if (DBVER >= 43)
6486static PyObject*
6487DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6488{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006489 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006490 int flags = 0;
6491 static char* kwnames[] = { "db", "flags", NULL};
6492
6493 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6494 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006495 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006496 makeTypeError("DB", dbobj);
6497 return NULL;
6498 }
6499 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6500}
6501#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006502
6503static char bsddb_version_doc[] =
6504"Returns a tuple of major, minor, and patch release numbers of the\n\
6505underlying DB library.";
6506
6507static PyObject*
6508bsddb_version(PyObject* self, PyObject* args)
6509{
6510 int major, minor, patch;
6511
6512 if (!PyArg_ParseTuple(args, ":version"))
6513 return NULL;
6514 db_version(&major, &minor, &patch);
6515 return Py_BuildValue("(iii)", major, minor, patch);
6516}
6517
6518
6519/* List of functions defined in the module */
6520
6521static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006522 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6523 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6524#if (DBVER >= 43)
6525 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6526#endif
6527 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006528 {NULL, NULL} /* sentinel */
6529};
6530
Gregory P. Smith39250532007-10-09 06:02:21 +00006531/* API structure */
6532static BSDDB_api bsddb_api;
6533
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006534
6535/* --------------------------------------------------------------------- */
6536/* Module initialization */
6537
6538
6539/* Convenience routine to export an integer value.
6540 * Errors are silently ignored, for better or for worse...
6541 */
6542#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6543
Gregory P. Smith41631e82003-09-21 00:08:14 +00006544#define MODULE_NAME_MAX_LEN 11
6545static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006546
6547DL_EXPORT(void) init_bsddb(void)
6548{
6549 PyObject* m;
6550 PyObject* d;
6551 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
6552 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
6553 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006554 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006555
6556 /* Initialize the type of the new type objects here; doing it here
6557 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00006558 Py_TYPE(&DB_Type) = &PyType_Type;
6559 Py_TYPE(&DBCursor_Type) = &PyType_Type;
6560 Py_TYPE(&DBEnv_Type) = &PyType_Type;
6561 Py_TYPE(&DBTxn_Type) = &PyType_Type;
6562 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006563#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00006564 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006565#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006566
6567
Mark Hammonda69d4092003-04-22 23:13:27 +00006568#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006569 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006570 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006571#endif
6572
6573 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006574 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00006575 if (m == NULL)
6576 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006577
6578 /* Add some symbolic constants to the module */
6579 d = PyModule_GetDict(m);
6580 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6581 PyDict_SetItemString(d, "cvsid", cvsid_s);
6582 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6583 Py_DECREF(pybsddb_version_s);
6584 pybsddb_version_s = NULL;
6585 Py_DECREF(cvsid_s);
6586 cvsid_s = NULL;
6587 Py_DECREF(db_version_s);
6588 db_version_s = NULL;
6589
6590 ADD_INT(d, DB_VERSION_MAJOR);
6591 ADD_INT(d, DB_VERSION_MINOR);
6592 ADD_INT(d, DB_VERSION_PATCH);
6593
6594 ADD_INT(d, DB_MAX_PAGES);
6595 ADD_INT(d, DB_MAX_RECORDS);
6596
Gregory P. Smith41631e82003-09-21 00:08:14 +00006597#if (DBVER >= 42)
6598 ADD_INT(d, DB_RPCCLIENT);
6599#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006600 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006601 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006602 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6603#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006604 ADD_INT(d, DB_XA_CREATE);
6605
6606 ADD_INT(d, DB_CREATE);
6607 ADD_INT(d, DB_NOMMAP);
6608 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006609#if (DBVER >= 45)
6610 ADD_INT(d, DB_MULTIVERSION);
6611#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006612
6613 ADD_INT(d, DB_FORCE);
6614 ADD_INT(d, DB_INIT_CDB);
6615 ADD_INT(d, DB_INIT_LOCK);
6616 ADD_INT(d, DB_INIT_LOG);
6617 ADD_INT(d, DB_INIT_MPOOL);
6618 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006619 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006620
Jesus Ceaef9764f2008-05-13 18:45:46 +00006621#if (DBVER >= 40)
6622 ADD_INT(d, DB_XIDDATASIZE);
6623#endif
6624
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006625 ADD_INT(d, DB_RECOVER);
6626 ADD_INT(d, DB_RECOVER_FATAL);
6627 ADD_INT(d, DB_TXN_NOSYNC);
6628 ADD_INT(d, DB_USE_ENVIRON);
6629 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6630
6631 ADD_INT(d, DB_LOCKDOWN);
6632 ADD_INT(d, DB_PRIVATE);
6633 ADD_INT(d, DB_SYSTEM_MEM);
6634
6635 ADD_INT(d, DB_TXN_SYNC);
6636 ADD_INT(d, DB_TXN_NOWAIT);
6637
6638 ADD_INT(d, DB_EXCL);
6639 ADD_INT(d, DB_FCNTL_LOCKING);
6640 ADD_INT(d, DB_ODDFILESIZE);
6641 ADD_INT(d, DB_RDWRMASTER);
6642 ADD_INT(d, DB_RDONLY);
6643 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006644 ADD_INT(d, DB_EXTENT);
6645 ADD_INT(d, DB_CDB_ALLDB);
6646 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006647 ADD_INT(d, DB_UPGRADE);
6648
6649 ADD_INT(d, DB_AGGRESSIVE);
6650 ADD_INT(d, DB_NOORDERCHK);
6651 ADD_INT(d, DB_ORDERCHKONLY);
6652 ADD_INT(d, DB_PR_PAGE);
6653#if ! (DBVER >= 33)
6654 ADD_INT(d, DB_VRFY_FLAGMASK);
6655 ADD_INT(d, DB_PR_HEADERS);
6656#endif
6657 ADD_INT(d, DB_PR_RECOVERYTEST);
6658 ADD_INT(d, DB_SALVAGE);
6659
6660 ADD_INT(d, DB_LOCK_NORUN);
6661 ADD_INT(d, DB_LOCK_DEFAULT);
6662 ADD_INT(d, DB_LOCK_OLDEST);
6663 ADD_INT(d, DB_LOCK_RANDOM);
6664 ADD_INT(d, DB_LOCK_YOUNGEST);
6665#if (DBVER >= 33)
6666 ADD_INT(d, DB_LOCK_MAXLOCKS);
6667 ADD_INT(d, DB_LOCK_MINLOCKS);
6668 ADD_INT(d, DB_LOCK_MINWRITE);
6669#endif
6670
Jesus Ceaef9764f2008-05-13 18:45:46 +00006671#if (DBVER >= 40)
6672 ADD_INT(d, DB_LOCK_EXPIRE);
6673#endif
6674#if (DBVER >= 43)
6675 ADD_INT(d, DB_LOCK_MAXWRITE);
6676#endif
6677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006678
6679#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006680 /* docs say to use zero instead */
6681 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006682#else
6683 ADD_INT(d, DB_LOCK_CONFLICT);
6684#endif
6685
6686 ADD_INT(d, DB_LOCK_DUMP);
6687 ADD_INT(d, DB_LOCK_GET);
6688 ADD_INT(d, DB_LOCK_INHERIT);
6689 ADD_INT(d, DB_LOCK_PUT);
6690 ADD_INT(d, DB_LOCK_PUT_ALL);
6691 ADD_INT(d, DB_LOCK_PUT_OBJ);
6692
6693 ADD_INT(d, DB_LOCK_NG);
6694 ADD_INT(d, DB_LOCK_READ);
6695 ADD_INT(d, DB_LOCK_WRITE);
6696 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006697 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006698 ADD_INT(d, DB_LOCK_IWRITE);
6699 ADD_INT(d, DB_LOCK_IREAD);
6700 ADD_INT(d, DB_LOCK_IWR);
6701#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00006702#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006703 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00006704#else
6705 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
6706#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006707 ADD_INT(d, DB_LOCK_WWRITE);
6708#endif
6709
6710 ADD_INT(d, DB_LOCK_RECORD);
6711 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006712 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006713#if (DBVER >= 33)
6714 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
6715#endif
6716
6717 ADD_INT(d, DB_LOCK_NOWAIT);
6718 ADD_INT(d, DB_LOCK_RECORD);
6719 ADD_INT(d, DB_LOCK_UPGRADE);
6720
6721#if (DBVER >= 33)
6722 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006723#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006724 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006725#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006726 ADD_INT(d, DB_LSTAT_FREE);
6727 ADD_INT(d, DB_LSTAT_HELD);
6728#if (DBVER == 33)
6729 ADD_INT(d, DB_LSTAT_NOGRANT);
6730#endif
6731 ADD_INT(d, DB_LSTAT_PENDING);
6732 ADD_INT(d, DB_LSTAT_WAITING);
6733#endif
6734
6735 ADD_INT(d, DB_ARCH_ABS);
6736 ADD_INT(d, DB_ARCH_DATA);
6737 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00006738#if (DBVER >= 42)
6739 ADD_INT(d, DB_ARCH_REMOVE);
6740#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006741
6742 ADD_INT(d, DB_BTREE);
6743 ADD_INT(d, DB_HASH);
6744 ADD_INT(d, DB_RECNO);
6745 ADD_INT(d, DB_QUEUE);
6746 ADD_INT(d, DB_UNKNOWN);
6747
6748 ADD_INT(d, DB_DUP);
6749 ADD_INT(d, DB_DUPSORT);
6750 ADD_INT(d, DB_RECNUM);
6751 ADD_INT(d, DB_RENUMBER);
6752 ADD_INT(d, DB_REVSPLITOFF);
6753 ADD_INT(d, DB_SNAPSHOT);
6754
6755 ADD_INT(d, DB_JOIN_NOSORT);
6756
6757 ADD_INT(d, DB_AFTER);
6758 ADD_INT(d, DB_APPEND);
6759 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006760#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006761 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006762#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006763#if (DBVER >= 41)
6764 _addIntToDict(d, "DB_CHECKPOINT", 0);
6765#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006766 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006767 ADD_INT(d, DB_CURLSN);
6768#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00006769#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006770 ADD_INT(d, DB_COMMIT);
6771#endif
6772 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006773 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006774 ADD_INT(d, DB_CURRENT);
6775#if (DBVER >= 33)
6776 ADD_INT(d, DB_FAST_STAT);
6777#endif
6778 ADD_INT(d, DB_FIRST);
6779 ADD_INT(d, DB_FLUSH);
6780 ADD_INT(d, DB_GET_BOTH);
6781 ADD_INT(d, DB_GET_RECNO);
6782 ADD_INT(d, DB_JOIN_ITEM);
6783 ADD_INT(d, DB_KEYFIRST);
6784 ADD_INT(d, DB_KEYLAST);
6785 ADD_INT(d, DB_LAST);
6786 ADD_INT(d, DB_NEXT);
6787 ADD_INT(d, DB_NEXT_DUP);
6788 ADD_INT(d, DB_NEXT_NODUP);
6789 ADD_INT(d, DB_NODUPDATA);
6790 ADD_INT(d, DB_NOOVERWRITE);
6791 ADD_INT(d, DB_NOSYNC);
6792 ADD_INT(d, DB_POSITION);
6793 ADD_INT(d, DB_PREV);
6794 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006795#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006796 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006797#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006798 ADD_INT(d, DB_SET);
6799 ADD_INT(d, DB_SET_RANGE);
6800 ADD_INT(d, DB_SET_RECNO);
6801 ADD_INT(d, DB_WRITECURSOR);
6802
6803 ADD_INT(d, DB_OPFLAGS_MASK);
6804 ADD_INT(d, DB_RMW);
6805#if (DBVER >= 33)
6806 ADD_INT(d, DB_DIRTY_READ);
6807 ADD_INT(d, DB_MULTIPLE);
6808 ADD_INT(d, DB_MULTIPLE_KEY);
6809#endif
6810
Gregory P. Smith29602d22006-01-24 09:46:48 +00006811#if (DBVER >= 44)
6812 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6813 ADD_INT(d, DB_READ_COMMITTED);
6814#endif
6815
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006816#if (DBVER >= 33)
6817 ADD_INT(d, DB_DONOTINDEX);
6818#endif
6819
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006820#if (DBVER >= 41)
6821 _addIntToDict(d, "DB_INCOMPLETE", 0);
6822#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006823 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006824#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006825 ADD_INT(d, DB_KEYEMPTY);
6826 ADD_INT(d, DB_KEYEXIST);
6827 ADD_INT(d, DB_LOCK_DEADLOCK);
6828 ADD_INT(d, DB_LOCK_NOTGRANTED);
6829 ADD_INT(d, DB_NOSERVER);
6830 ADD_INT(d, DB_NOSERVER_HOME);
6831 ADD_INT(d, DB_NOSERVER_ID);
6832 ADD_INT(d, DB_NOTFOUND);
6833 ADD_INT(d, DB_OLD_VERSION);
6834 ADD_INT(d, DB_RUNRECOVERY);
6835 ADD_INT(d, DB_VERIFY_BAD);
6836#if (DBVER >= 33)
6837 ADD_INT(d, DB_PAGE_NOTFOUND);
6838 ADD_INT(d, DB_SECONDARY_BAD);
6839#endif
6840#if (DBVER >= 40)
6841 ADD_INT(d, DB_STAT_CLEAR);
6842 ADD_INT(d, DB_REGION_INIT);
6843 ADD_INT(d, DB_NOLOCKING);
6844 ADD_INT(d, DB_YIELDCPU);
6845 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6846 ADD_INT(d, DB_NOPANIC);
6847#endif
6848
Jesus Ceaef9764f2008-05-13 18:45:46 +00006849#if (DBVER >= 41)
6850 ADD_INT(d, DB_OVERWRITE);
6851#endif
6852
Gregory P. Smithaae141a2007-11-01 21:08:14 +00006853#ifdef DB_REGISTER
6854 ADD_INT(d, DB_REGISTER);
6855#endif
6856
Gregory P. Smith41631e82003-09-21 00:08:14 +00006857#if (DBVER >= 42)
6858 ADD_INT(d, DB_TIME_NOTGRANTED);
6859 ADD_INT(d, DB_TXN_NOT_DURABLE);
6860 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
6861 ADD_INT(d, DB_LOG_AUTOREMOVE);
6862 ADD_INT(d, DB_DIRECT_LOG);
6863 ADD_INT(d, DB_DIRECT_DB);
6864 ADD_INT(d, DB_INIT_REP);
6865 ADD_INT(d, DB_ENCRYPT);
6866 ADD_INT(d, DB_CHKSUM);
6867#endif
6868
Jesus Ceaef9764f2008-05-13 18:45:46 +00006869#if (DBVER >= 44)
6870 ADD_INT(d, DB_DSYNC_DB);
6871#endif
6872
6873#if (DBVER >= 45)
6874 ADD_INT(d, DB_TXN_SNAPSHOT);
6875#endif
6876
6877#if (DBVER >= 40)
6878 ADD_INT(d, DB_VERB_DEADLOCK);
6879#if (DBVER >= 46)
6880 ADD_INT(d, DB_VERB_FILEOPS);
6881 ADD_INT(d, DB_VERB_FILEOPS_ALL);
6882#endif
6883 ADD_INT(d, DB_VERB_RECOVERY);
6884#if (DBVER >= 44)
6885 ADD_INT(d, DB_VERB_REGISTER);
6886#endif
6887 ADD_INT(d, DB_VERB_REPLICATION);
6888 ADD_INT(d, DB_VERB_WAITSFOR);
6889#endif
6890
6891#if (DBVER >= 45)
6892 ADD_INT(d, DB_EVENT_PANIC);
6893 ADD_INT(d, DB_EVENT_REP_CLIENT);
6894#if (DBVER >= 46)
6895 ADD_INT(d, DB_EVENT_REP_ELECTED);
6896#endif
6897 ADD_INT(d, DB_EVENT_REP_MASTER);
6898 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
6899#if (DBVER >= 46)
6900 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
6901#endif
6902 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
6903 ADD_INT(d, DB_EVENT_WRITE_FAILED);
6904#endif
6905
6906#if (DBVER >= 40)
6907 ADD_INT(d, DB_REP_MASTER);
6908 ADD_INT(d, DB_REP_CLIENT);
6909#if (DBVER >= 45)
6910 ADD_INT(d, DB_REP_ELECTION);
6911
6912 ADD_INT(d, DB_REP_ACK_TIMEOUT);
6913 ADD_INT(d, DB_REP_CONNECTION_RETRY);
6914 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
6915 ADD_INT(d, DB_REP_ELECTION_RETRY);
6916#endif
6917#if (DBVER >= 46)
6918 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
6919 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
6920#endif
6921#endif
6922
6923#if (DBVER >= 45)
6924 ADD_INT(d, DB_REPMGR_PEER);
6925 ADD_INT(d, DB_REPMGR_ACKS_ALL);
6926 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
6927 ADD_INT(d, DB_REPMGR_ACKS_NONE);
6928 ADD_INT(d, DB_REPMGR_ACKS_ONE);
6929 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
6930 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
6931 ADD_INT(d, DB_REPMGR_CONNECTED);
6932 ADD_INT(d, DB_REPMGR_DISCONNECTED);
6933 ADD_INT(d, DB_STAT_CLEAR);
6934 ADD_INT(d, DB_STAT_ALL);
6935#endif
6936
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006937#if (DBVER >= 43)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006938 ADD_INT(d, DB_DSYNC_LOG);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006939 ADD_INT(d, DB_LOG_INMEMORY);
6940 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006941 ADD_INT(d, DB_SEQ_DEC);
6942 ADD_INT(d, DB_SEQ_INC);
6943 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006944#endif
6945
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006946#if (DBVER >= 41)
6947 ADD_INT(d, DB_ENCRYPT_AES);
6948 ADD_INT(d, DB_AUTO_COMMIT);
6949#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00006950 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006951 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
6952#endif
6953
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006954 ADD_INT(d, EINVAL);
6955 ADD_INT(d, EACCES);
6956 ADD_INT(d, ENOSPC);
6957 ADD_INT(d, ENOMEM);
6958 ADD_INT(d, EAGAIN);
6959 ADD_INT(d, EBUSY);
6960 ADD_INT(d, EEXIST);
6961 ADD_INT(d, ENOENT);
6962 ADD_INT(d, EPERM);
6963
Barry Warsaw1baa9822003-03-31 19:51:29 +00006964#if (DBVER >= 40)
6965 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
6966 ADD_INT(d, DB_SET_TXN_TIMEOUT);
6967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006968
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006969 /* The exception name must be correct for pickled exception *
6970 * objects to unpickle properly. */
6971#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6972#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6973#else
6974#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6975#endif
6976
6977 /* All the rest of the exceptions derive only from DBError */
6978#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6979 PyDict_SetItemString(d, #name, name)
6980
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006981 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006982 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6983 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006984
Gregory P. Smithe9477062005-06-04 06:46:59 +00006985 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6986 * from both DBError and KeyError, since the API only supports
6987 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006988 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006989 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6990 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006991 Py_file_input, d, d);
6992 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006993 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006994 PyDict_DelItemString(d, "KeyError");
6995
6996
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006997#if !INCOMPLETE_IS_WARNING
6998 MAKE_EX(DBIncompleteError);
6999#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007000 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007001 MAKE_EX(DBKeyEmptyError);
7002 MAKE_EX(DBKeyExistError);
7003 MAKE_EX(DBLockDeadlockError);
7004 MAKE_EX(DBLockNotGrantedError);
7005 MAKE_EX(DBOldVersionError);
7006 MAKE_EX(DBRunRecoveryError);
7007 MAKE_EX(DBVerifyBadError);
7008 MAKE_EX(DBNoServerError);
7009 MAKE_EX(DBNoServerHomeError);
7010 MAKE_EX(DBNoServerIDError);
7011#if (DBVER >= 33)
7012 MAKE_EX(DBPageNotFoundError);
7013 MAKE_EX(DBSecondaryBadError);
7014#endif
7015
7016 MAKE_EX(DBInvalidArgError);
7017 MAKE_EX(DBAccessError);
7018 MAKE_EX(DBNoSpaceError);
7019 MAKE_EX(DBNoMemoryError);
7020 MAKE_EX(DBAgainError);
7021 MAKE_EX(DBBusyError);
7022 MAKE_EX(DBFileExistsError);
7023 MAKE_EX(DBNoSuchFileError);
7024 MAKE_EX(DBPermissionsError);
7025
Jesus Ceaef9764f2008-05-13 18:45:46 +00007026#if (DBVER >= 42)
7027 MAKE_EX(DBRepHandleDeadError);
7028#endif
7029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007030#undef MAKE_EX
7031
Gregory P. Smith39250532007-10-09 06:02:21 +00007032 /* Initiliase the C API structure and add it to the module */
7033 bsddb_api.db_type = &DB_Type;
7034 bsddb_api.dbcursor_type = &DBCursor_Type;
7035 bsddb_api.dbenv_type = &DBEnv_Type;
7036 bsddb_api.dbtxn_type = &DBTxn_Type;
7037 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007038#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007039 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007040#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007041 bsddb_api.makeDBError = makeDBError;
7042
7043 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7044 PyDict_SetItemString(d, "api", py_api);
7045 Py_DECREF(py_api);
7046
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007047 /* Check for errors */
7048 if (PyErr_Occurred()) {
7049 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007050 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007051 }
7052}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007053
7054/* allow this module to be named _pybsddb so that it can be installed
7055 * and imported on top of python >= 2.3 that includes its own older
7056 * copy of the library named _bsddb without importing the old version. */
7057DL_EXPORT(void) init_pybsddb(void)
7058{
7059 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7060 init_bsddb();
7061}